I want to write a QT program in Python and it is supposed to continuously look for updates. Just like
while(True):
doSomething()
would do in a console based program.
Is there a specific slot which I can connect to for this purpose?
It depends from what you want to achieve.
QThread is one solution.
You also can solve this by using a QTimer with a timeout of zero. Such a timer executes
the connected slot whenever nothing other needs to be done by the event loop (like some background task).
Depending from what you do also a QTimer with a decent timeout can be the solution (like polling for an event).
As I said, it depends from what you want to do.
Use QThread to create loop what your want. Your can find example in here, here and a lot of in google search result. QThread i subclass in QObject so your can connect just like QWidget old-style or new-style signal.
Related
When I use the function time.sleep() in the terminal, it is no problem.
When I use PyQt and want to use a label, it crashes and/or only shows the last number.
By the way: I want a function, that counts e.g. a year from 2020 to 2030 in various speed, that the user can change and the year should be shown in a label.
Thanks a lot for your help.
# timer that counts in the future with various speed // still crashing
def timer(self):
x=datetime.datetime.now()
z=x.ctime()
self.ui.labelDateTime.setText(z)
var=x.year
while True:
if var==2030:
break
else:
var+=1
y=x.replace(year=var)
z=y.ctime()
self.ui.labelDateTime.setText(z)
time.sleep(0.5)
print("You are dead")
You should call QtCore.QCoreApplication.processEvents() within your for loop to make the Qt's event loop proceed the incoming event (from keyboard or mouse or sleep).
Although calling QtCore.QCoreApplication.processEvents() works , I have read in many places on the web that it should be a last resort. Unfortunately none of the sources clearly explain why -- but see for example
How to make Qt work when main thread is busy?
Should I use QCoreApplication::processEvents() or QApplication::processEvents()?
How to implement a QThread that runs forever{} with a QWaitCondition but still needs to catch another Slot while doing that
http://qt-project.org/forums/viewthread/22967
So it does seem allowed, but in general, it seems to be better design to use QTimer or QThread.
I want to show a loading gif until a function is completed.
The code I have is
self.LoadingGif = QtGui.QLabel(MainWindow)
movie = QtGui.QMovie("hashUpdate.gif")
self.LoadingGif.setMovie(movie)
self.LoadingGif.setAlignment(QtCore.Qt.AlignCenter)
self.gridLayout_2.addWidget(self.LoadingGif, 4, 1, 1, 1)
movie.start()
self.MYFUNCTION()
The problem is that the gif shows but it is not playing. It starts to play only when the function is completed.
How can I make the gif play while the function is executing ?
The GIF stops playing because your function self.MYFUNCTION is blocking the Qt Event loop. The Event loop is the part of Qt which (among other things) processes mouse/keyboard events, handles redrawing of widgets (like buttons when you hover over them or click on them) and updating the current frame displayed when playing an animation.
So the Qt event loop is responsible for executing your code in response to various things that happen in your program, but while it is executing your code, it can't do anything else.
So you need to change your code. There are several solutions to this:
Run MYFUNCTION in a secondary thread so it doesn't block the Qt event loop. However, this is not an option if your function interacts with the Qt GUI in any way. If you call any Qt GUI methods in MYFUNCTION (like updating a label, or whatever), this must never be done from a secondary thread (if you try, your program will randomly crash). It is recommended to use a QThread with Qt rather than a Python thread, but a Python thread will work fine if you don't ever need to communicate back to the main thread from your function.
If MYFUNCTION runs for a long time because you have a for/while loop, you could consider using a QTimer to periodically call the code in the loop. Control is returned to the Qt event loop after a QTimer executes so it can deal with other things (like updating your animation) between iterations of your loop.
Periodically call QApplication.instance().processEvents() during your function. This also returns control to the Qt event loop, but you may get unexpected behaviour if your function is also doing things with Qt.
You'll need to move self.your_function to another thread, letting Qt update the GUI and so your GIF!
I have written a little python utility that monitors my typing speed, using pyxhook to hook keyboard events, and a thread timer to update my words per minute number.
Right now it just prints to the terminal every 2 seconds.
How can I make this appear in a little always-on-top gui box?
I tried playing around with tkinter, but the mainloop() function doesn't like my key listener and timer. It seems I can only run the gui OR my event handlers, but not both.
Unfortunately I don't think I can use the keyhandler in tkinter, since I am wanting to capture events from other windows.
Any suggestions?
I don't know how to go about doing this in tk, but I've been using PySide lately and I know you could use that.
One way to do it in pyside would be with two classes running in separate threads that communicate using the Qt signal & slot mechanism available in pyside. One class would subclass QThread & get methods that run your existing code & pass the data via signals to the Ui class. The 2nd class would be the one for your gui elements. it would call for an instance of the first class, connect the signals & slots, then start it & begin drawing the display.
resources if you go the pyside route:
http://www.matteomattei.com/pyside-signals-and-slots-with-qthread-example/
search 'pyside dock widget' on this site
search for github's pyside examples
https://pyside.github.io/docs/pyside/PySide/QtCore/QThread.html?highlight=qthread
Say I have a QListView and each item in this list is meant to be refreshed with the output of a certain system process (such as some intensive file I/O-ing) which is triggered in a thread (using threading.Thread). The problem I have is that the main window's application freezes shortly after I start a new thread and halts the application. Is there a more effective way to achieve this?
It sounds like you should be using QThread rather than threading.Thread.
This question has a lot of useful discussion about how to use threads correctly in PyQt applications.
How can I get a Progressbar to "pulse" while another function is run?
There is an example of how to do this here.
Push that another function into a separate thread. As long as your main thread runs any code, GUI is frozen. This is not a problem for short code pieces, but obviously a problem in your case.
Also read what PyGTK FAQ has to say about using threads in PyGTK program.
If your function runs in many iterations that don't take too long by themselves, then you don't necessarily need to mess around with separate threads. You can also cause the GUI to update itself during your long calculation:
def long_function(some_args):
while task_is_not_finished():
do_some_stuff_that_doesnt_take_too_long()
progress_bar.pulse()
while gtk.events_pending():
gtk.main_iteration()