hey i heard that there is something called qt signals you can use it to change the GUI out side the main thread coz when i try to change it i get an error that i cant change the gui out of the main thread but i need it to edit the progressbar value so if anyone had a way to do it plz tell me
nabla2
Hi,
Try something like this:
my_form.py:
# -*- coding: utf-8 -*-
from PyQt4 import QtGui, QtCore
from main_window import Ui_MainWindow
from outside import Outside
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyForm, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
outside = Outside()
self.connect(outside, QtCore.SIGNAL("progress(int, int)"), self.progress)
def progress(self, value, max_value):
self.ui.progressBar.setMinimum(0)
self.ui.progressBar.setMaximum(max_value)
self.ui.progressBar.setValue(value)
outside.py:
# -*- coding: utf-8 -*-
from PyQt4 import QtCore
class Outside(QtCore.QThread):
def __init__(self, parent=None):
super(Outside, self).__init__(parent)
self.start()
def run(self):
self.emit(QtCore.SIGNAL("progress(int, int)"), i + 1, len(something_iterable))
def __del__(self):
self.exiting = True
self.wait()
memomk 0 Newbie Poster
why there is
i + 1, len(something_iterable)
in the line 12 in the out side module?
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague
This code is a simulation (hint) that drives your progress bar for testing purposes..
You have to replace it with code you want to move the progress bar with.
Edited by vegaseat
nabla2
Badly copied piece of code. It should be:
def run(self):
for i, item in enumerate(something_iterable):
self.emit(QtCore.SIGNAL("progress(int, int)"), i + 1, len(something_iterable))
memomk 0 Newbie Poster
yeah but am using python threading module not QtThread
example :
#after importing all modules and set the GUi.....
def progress(self,X):
self.progress.setProperty("value",x)
def main(self):
print "value is 0"
self.progress(0)
print "now it is 100"
self.progress(100)
t=threading.Thread(target=main)
t.start()
nabla2
I propose to use the QThread
instead threading.Thread
in this case.
It's mostly the same. The main difference is that QThreads are better integrated with Qt (asynchrnous signals/slots, event loop, etc.). Also, you can't use Qt from a Python thread (you can't for instance post event to the main thread through QApplication.postEvent): you need a QThread for that to work.
A general rule of thumb might be to use QThreads if you're going to interact somehow with Qt, and use Python threads otherwise.
Edited by nabla2
memomk 0 Newbie Poster
hmmm so it is a deadend....
is there a way to syc a var between a thread and the main GUI thread?
and what about pywx,pygtk,pytk?? can't i change the gui from a thread?
nabla2
Of course, you can. Read this example carefully. You need a class that inherits from QThread
and implements the run
method, which is triggered by start()
. For communication between the thread and the GUI use the signals and slots.
At first it may be complicated. Writing multithreaded programs requires a bit more knowledge, regardless of whether you are using PyGTK, wxPython, etc.
PyQt is probably the best choice (in my opinion). Slightly modified example (with snippet for more pythonic API 2):
import sys
import math
import random
import sip
API_NAMES = ["QDate", "QDateTime", "QString","QTextStream", "QTime", "QUrl", "QVariant"]
API_VERSION = 2
for name in API_NAMES:
sip.setapi(name, API_VERSION)
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Window(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.thread = Worker()
label = QLabel("Number of stars:")
self.spinBox = QSpinBox()
self.spinBox.setMaximum(10000)
self.spinBox.setValue(100)
self.startButton = QPushButton("&Start")
self.viewer = QLabel()
self.viewer.setFixedSize(300, 300)
self.connect(self.thread, SIGNAL("finished()"), self.updateUi)
self.connect(self.thread, SIGNAL("terminated()"), self.updateUi)
self.connect(self.thread, SIGNAL("output(QRect, QImage)"), self.addImage)
self.connect(self.startButton, SIGNAL("clicked()"), self.makePicture)
layout = QGridLayout()
layout.addWidget(label, 0, 0)
layout.addWidget(self.spinBox, 0, 1)
layout.addWidget(self.startButton, 0, 2)
layout.addWidget(self.viewer, 1, 0, 1, 3)
self.setLayout(layout)
self.setWindowTitle("Simple Threading Example")
def makePicture(self):
self.spinBox.setReadOnly(True)
self.startButton.setEnabled(False)
pixmap = QPixmap(self.viewer.size())
pixmap.fill(Qt.black)
self.viewer.setPixmap(pixmap)
self.thread.render(self.viewer.size(), self.spinBox.value())
def addImage(self, rect, image):
pixmap = self.viewer.pixmap()
painter = QPainter()
painter.begin(pixmap)
painter.drawImage(rect, image)
painter.end()
self.viewer.update(rect)
def updateUi(self):
self.spinBox.setReadOnly(False)
self.startButton.setEnabled(True)
class Worker(QThread):
def __init__(self, parent=None):
QThread.__init__(self, parent)
self.exiting = False
self.size = QSize(0, 0)
self.stars = 0
self.path = QPainterPath()
angle = 2*math.pi/5
self.outerRadius = 20
self.innerRadius = 8
self.path.moveTo(self.outerRadius, 0)
for step in range(1, 6):
self.path.lineTo(
self.innerRadius * math.cos((step - 0.5) * angle),
self.innerRadius * math.sin((step - 0.5) * angle)
)
self.path.lineTo(
self.outerRadius * math.cos(step * angle),
self.outerRadius * math.sin(step * angle)
)
self.path.closeSubpath()
def __del__(self):
self.exiting = True
self.wait()
def render(self, size, stars):
self.size = size
self.stars = stars
self.start()
def run(self):
# Note: This is never called directly. It is called by Qt once the
# thread environment has been set up.
random.seed()
n = self.stars
width = self.size.width()
height = self.size.height()
while not self.exiting and n > 0:
image = QImage(self.outerRadius * 2, self.outerRadius * 2,
QImage.Format_ARGB32)
image.fill(qRgba(0, 0, 0, 0))
x = random.randrange(0, width)
y = random.randrange(0, height)
angle = random.randrange(0, 360)
red = random.randrange(0, 256)
green = random.randrange(0, 256)
blue = random.randrange(0, 256)
alpha = random.randrange(0, 256)
painter = QPainter()
painter.begin(image)
painter.setRenderHint(QPainter.Antialiasing)
painter.setPen(Qt.NoPen)
painter.setBrush(QColor(red, green, blue, alpha))
painter.translate(self.outerRadius, self.outerRadius)
painter.rotate(angle)
painter.drawPath(self.path)
painter.end()
self.emit(SIGNAL("output(QRect, QImage)"),
QRect(x - self.outerRadius, y - self.outerRadius,
self.outerRadius * 2, self.outerRadius * 2), image)
n -= 1
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
app.exec_()
Edited by nabla2
memomk 0 Newbie Poster
hmmmm i guess i need a good tutorial for Qt anyway thanx this question should be marked as solved :)
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.