Reputation: 3459
I am trying to animate a rectangle in PyQT by creating an animation loop. I have done this in TKinter using the window.after()
method and am trying to do the same thing in PyQt5 using QtCore.QTimer.singleShot()
, however, when I run the code it says that QtCore
is not defined yet I believe that I have imported it!? Also - would this method work anyway? Is there a better method?
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_())
Upvotes: 3
Views: 8305
Reputation: 101919
The QtCore
reference is undefined because you are using a star import:
from PyQt5.QtCore import *
this imports everything that is inside QtCore
into the global namespace but it does not import the name QtCore
.
In fact you can use:
QTimer.singleShot(x)
without the need for QtCore.
in front.
However you should probably use:
from PyQt5 import QtCore
This said:
I have no idea why you are using the singleShot
timer when you do not want a single shot timer but a 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_())
The QTimer
object called with start(msec)
will emit a timeout()
signal every msec
milliseconds. In this way you don't have to restart it every time.
Moreover I find really ugly to patch instances by changing their methods like you are doing in animate()
with mw.paintEvent = paintEvent
. Besides: you could put that line outside the function.
Note: Inside the function that updates the values you have to call mw.update()
otherwise no paintEvent
is generated.
Moreover it seems like timer
is getting garbage collected, thus blocking the timer so it's better to just have a global reference to it.
Upvotes: 3
Reputation: 385830
You haven't imported QTCore, you've imported everything in QTCore.
Try changing this:
from PyQt5.QtCore import *
to this:
from PyQt5 import QtCore
change this:
QTCore.QTimer.singleShot(33, animate)
to this:
QTImer.singleShot(33, animate)
Upvotes: 3