Rectangle animation in PyQT5: why is QtCore not defined?

I am trying to animate a rectangle in PyQT by creating an animation loop. I did it in TKinter using a method window.after()

and am trying to do the same in PyQt5 with QtCore.QTimer.singleShot()

, however when I run the code it says it QtCore

is not defined yet. I believe I imported It !? Also - would this method work anyway? Is there a better way?

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_())

      

+3


source to share


2 answers


The link is QtCore

undefined because you are using an asterisk import:

from PyQt5.QtCore import *

      

it imports everything inside QtCore

into the global namespace, but does not import the name QtCore

.

You can actually use:

QTimer.singleShot(x)

      

unnecessarily QtCore.

ahead.

However, you should probably use:



from PyQt5 import QtCore

      

That said:

I have no idea why you use a timer singleShot

when you don't want one shot timer, but period one. You should do something like:

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_())

      

An object QTimer

called with start(msec)

emits a signal timeout()

every msec

milliseconds. This way you don't have to restart it every time.

Also, I find it really ugly to fix instances by changing their methods like you do in animate()

c mw.paintEvent = paintEvent

. Also: you can put this line outside the function.

Note . Inside a function that updates the values ​​that you should call mw.update()

, otherwise not generated paintEvent

. Also, it looks like it timer

gets garbage collected by blocking the timer, so it's better to just have a global reference to it.

+1


source


You have not imported QTCore, you have imported everything into QTCore.

Change the import method

Try to change this:

from PyQt5.QtCore import *

      

:

from PyQt5 import QtCore

      



Or change the way you call QTimer

change this:

QTCore.QTimer.singleShot(33, animate)

      

:

QTImer.singleShot(33, animate)

      

+3


source







All Articles