在PyQT5中为矩形添加动画效果:为什么QtCore未被定义?

3

我正在尝试通过创建动画循环来在PyQT中制作一个矩形动画。我已经使用window.after()方法在TKinter中完成了这个操作,并试图在PyQt5中使用QtCore.QTimer.singleShot()做同样的事情,但是当我运行代码时它会提示QtCore未定义,而我相信我已经导入了它!此外-这种方法能行吗?有更好的方法吗?

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.Qt import *
from PyQt5.QtCore import *


def animate():
    global a
    global x
    mw.paintEvent = paintEvent
    a = a+1
    x = x+1
    QtCore.QTimer.singleShot(33, animate)


def paintEvent(e):
    qp = QPainter()
    qp.begin(mw)
    qp.setBrush(QColor(200, 0, 0))
    qp.drawRect(a, b, x, y)
    qp.end()

a = 10
b = 15
x = 90
y = 60

app = QApplication(sys.argv)

mw = QMainWindow()
mw.setWindowTitle('PyQt5 - Main Window')
mw.setWindowIcon(QIcon("icon.jpg"))
mw.resize(300,100)

animate()

mw.show()
sys.exit(app.exec_())
2个回答

3

您没有导入QTCore,而是导入了QTCore中的所有内容。

更改导入方式

尝试更改为:

from PyQt5.QtCore import *

转换为:

from PyQt5 import QtCore

或者,更改您调用QTimer的方式

将其更改为:

QTCore.QTimer.singleShot(33, animate)

转换为:

QTImer.singleShot(33, animate)

太棒了!再次感谢Bryan。现在它可以运行了,但是矩形不会自动移动 - 窗口不会更新绘图,除非我拖动窗口变大或变小 - 你有什么想法吗? - sw123456
我想我刚刚找到了这个最后一个问题的答案!谢谢。 - sw123456
其实,我还没有弄清楚为什么矩形不能正确更新?由于某种原因非常有bug - 只有在调整窗口大小时才会更新矩形!有什么想法吗? - sw123456
好的,问题解决了 - 动画循环中没有添加mw.update()这一行代码。再次感谢您的帮助! - sw123456

3

由于您使用了星号导入,QtCore参考未定义:

from PyQt5.QtCore import *

这行代码将QtCore中的所有内容导入到全局命名空间中,但它并不导入QtCore这个名称。

实际上你可以使用以下代码:

QTimer.singleShot(x)

不需要在前面添加QtCore.

然而,你应该尽量使用:

from PyQt5 import QtCore

这样说:

我不知道为什么你在使用 singleShot 定时器,因为你不需要单次触发,而是需要周期性触发。你应该做如下修改:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.Qt import *
from PyQt5.QtCore import *


class MyWindow(QMainWindow):
    def paintEvent(self, event):
        qp = QPainter()
        qp.begin(self)
        qp.setBrush(QColor(200, 0, 0))
        qp.drawRect(a, b, x, y)
        qp.end()


def updateValues():
    global a, x
    a += 1
    x += 1
    mw.update()  # <-- update the window!


a = 10
b = 15
x = 90
y = 60

app = QApplication(sys.argv)

mw = MyWindow()
mw.setWindowTitle('PyQt5 - Main Window')
mw.setWindowIcon(QIcon("icon.jpg"))
mw.resize(300,100)

timer = QTimer()
timer.timeout.connect(updateValues)
timer.start(33)

mw.show()
sys.exit(app.exec_())
start(msec)被调用的QTimer对象将每msec毫秒发出一个timeout()信号。这种方法可以避免每次重新启动它。
此外,我发现通过更改实例的方法来修补实例(例如在animate()中使用mw.paintEvent = paintEvent)非常丑陋。同时,您还可以将该行代码放在函数外面。 注意:在更新值的函数内部,必须调用mw.update(),否则不会生成paintEvent事件。 此外,似乎timer即将被回收,从而阻止了定时器的使用,因此最好只是将其全局引用。

谢谢您的建议。我知道这段代码很丑陋 - 我只是觉得先学习编写过程式代码,然后再学习面向对象编程更容易理解。另外,您提供的上面那段代码似乎没有动画效果。我的解决方案有动画效果,但有些小问题 - 只有在我拖动窗口变小或变大时才会更新。您有什么想法吗? - sw123456
@sw123456 我刚刚解决了这个问题。错误非常简单:你忘记调用 update()repaint(),因此没有生成任何 paintEvent,因此窗口没有更新。当调整大小时它被更新是因为调整大小会导致 paintEvent - Bakuriu
太棒了!非常感谢 - 总是那些简单的问题!非常感谢您的帮助! - sw123456

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接