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_())
source to share
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.
source to share
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)
source to share