Hello Everyone , I will explain on how to create a rotating circle using the concept of multithreading , qraphicsscene aand qgraphicsview. I struggled a lot to get the syntax( noobish I know) , but this is just to ensure no-one suffers the same.
from PyQt4 import QtGui , QtCore import sys , time #this imports the required libraries
We will be inheriting QtGui.QWidget , to create the basic user interface design.
class Example(QtGui.QWidget): def __init__(self): #Initialising the parent class and calling self.UI super(Example , self).__init__() self.UI()
My UI function should just have a layout with a graphics view and a button say Run . So this will be my function.
#Inside the UI function. //Self Explanatory (Creating and adding widgets to my layout) self.setWindowTitle('Revolving Circle') self.setGeometry(200 , 200 , 500 , 500) layout = QtGui.QGridLayout(self) button = QtGui.QPushButton('Revolve') view = QtGui.QGraphicsView() scene = QtGui.QGraphicsScene() view.setScene(scene) layout.addWidget(view , 0 , 0) layout.addWidget(button , 0 ,1) self.show() button.clicked.connect(self.revolve) #Connecting the button signal to the function revolve
Now for creating the circle and the line connecting the centre to the circumference of the circle.
#Inside the UI function circle = QtGui.QGraphicsEllipseItem(150 , 250 , 50 , 50) scene.addItem(circle)
The parameters that QGraphicsEllipseItem takes? Um. well , assume the ellipse is enclosed in a rectangle , the first two
numbers give the x and y coordinates , of the top left corner of the rectangle , the third and fourth give me the length
of the major axis and minor axis respectively.Now to add the line that represents the radius of the circle.
self.lin = QtCore.QLineF(QtCore.QPointF(175 , 275) , QtCore.QPointF(200 , 275)) self.line1 = QtGui.QGraphicsLineItem.setLine() self.line1.setLine(self.lin) scene.addItem(self.line1)
For setting a line in a QGraphicsScene , it is better to have a QLineF set in a QGraphicsLineItem , so that it becomes
easier to update , and the QLineF , takes as parameters , the starting and ending point.
So the basic interface is set. Now to add the function , the button sets off when clicked.
def revolve(self): theta = 10 i = 0 while 1: i = i + 1 time.sleep(0.01) self.lin.setAngle(theta * i) self.line1.setLine(self.lin)
This should make the radius revolve right? But it wouldn’t. It would start to hang. The way to rectify is to create
a seperate thread for the time computation and passing it on to a function , instead of letting the GUI function do the
time computation itself. And for people who ask why , theta * i , just theta wouldn’t do because theta is with respect to
the position of the initial line.
So for the threading part , we need to inherit the QtCore.QThread class , and rewrite the run method.
class RevolveThread(QtCore.QThread): def __init__(self): super(RevolveThread , self).__init__() def run(self): i = 0 while 1: i = i + 1 time.sleep(0.01) self.emit(QtCore.SIGNAL('update(QString)') + str(i))
So every 0.01 seconds this runs , it emits a signal. which is caught by the function it is connected to.
Now write another function , change , which implements the rotation.
#Inside a function change self.lin.setAngle(theta * int(i)) self.line1.setLine(self.lin)
Remove other lines in the function revolve , just add lines that initialises the thread , connects it to the function ,
change , and starts the thread
#Inside revolve thread = RevolveThread() self.connect(thread , QtCore.SIGNAL('update(QString)') , self.change) thread.start()
And as for managing threads , its better to create a list of them , and then call them one by one , as and when the
button is clicked.
So when you click on the Revolve Button , you will see a rotating circle.
Thanks for reading..