PyQt Label not changing text - python

I have this code running on a PyQt window on windows:
try:
self.actorUser.findIdfFiles(pathToFolder)
msg = "Processando arquivos..."
self.processingLabel.setText(msg)
self.actorUser.runSimulation(pathToFolder, pathToEpw)
Inside the "runSimulation" code I start a subprocess using the method "call". This blocks my GUI and at the title of the window appears "Python stopping responding", but if I wait a little bit the subprocess finishes normally, and the label is finally changed. But what I want is that the label have is text really changed before the subprocess started. What can I do??

Qt (and most UI frameworks) don't update the display as soon as values are set, only when they are told to repaint.
What you need to do is add a call
QtGui.QApplication.processEvents()
before your long-running subprocess, to make it process all pending events.

Joe P 's answer is quite right.
But this method is change to
QtCore.QCoreApplication.processEvents()
in pyqt5
link: https://doc.qt.io/qt-5/qcoreapplication.html#processEvents

Related

How to execute a command with a button and delete it before the command ends ? Python / Tkinter

I've got an interface where there is a 'Start' button. It runs a 'main' command where it starts a loop to run some measurements on a powermeter. I want to be able to click on an 'OK' button every time the measure is ready to be done. This button would replace the 'Start' button.
But when I try to destroy the button (buttonStart.destroy()) and then run the command main()
, the command executes but doesn't delete the button until the very end.
I've tried using threads from threading package, but it doesn't really work.
If there is a way to both destroy the button and run a command, I would be very interested !
Thanks a lot
The event loop must be given the opportunity to process events in order for the window to be removed from the screen.
There are a couple of ways to make that happen. The first is to call the update_idletasks method on any widget. That is usually enough to process the event related to the destruction of the widget, though it may be necessary to call update instead. Calling update should be avoided if at all possible. My rule of thumb is to start with update_idletasks. If that doesn't work, switch to update or switch to using after.
def my_custom_function():
startButton.destroy()
root.upddate_idletasks()
main()
The second method is to run your main function via after or after_idle. This will let tkinter naturally process all pending events before starting main. I would argue that this is the best approach. I recommend trying after_idle first, and if that doesn't work, switch to after with a small delay.
def my_custom_function():
startButton.destroy()
root.after_idle(main)

Tkinter window only showing after the process

I wrote a script to download file. I tinker it using tkinter. My idea is to show a new window when download button is clicked and show the progress of the download in it. I create new window but problem is it will not show the window until the download is complete..
b2 = Button(text = "Image Download",font=("Raleway", 10),command = lambda: download('Image','.jpg'), width=20)
b2.pack()
when this execute the download() executes in download():
window = Toplevel(root)
window.geometry('600x350+305+220')
window.wm_title(TYPE + ' Download')
this is for creating new window. But it only shows when the download() finish executes
What should i do? Help me
You have not shown the code that downloads the data but it is clearly using a synchronous method. All windowing systems operate by processing events. When a window is created and event is generated to map it onto the screen and another to get it to draw on screen. If you do not allow the thread to process events then apparently nothing happens until you stop being busy.
To work around this you either need to use an asynchronous method of downloading the data or you can use a synchronous method but you must do this on another thread. The UI thread (the one you create your windows on) MUST keep processing events. This basically means never do anything that will take a long time. The Tkinter after() method is a common scheme to break up a long job into lots of small pieces that are posted as events to keep things working. In this case its probably simplest to create a worker thread to do the download and post progress updates to the UI thread regularly.

Main window doesnt closes after caling new script from it

I am learning python and for GUI model using wxpython, as I am new to programing get stuck every time.
My issue is I have a GUI (main window)with two buttons,when user clicks button1 it opens sub window (seperate python script), I want to close or destroy main window before opening sub window.
self.Destroy()
subprocess.call("python newframe.py",shell=True)
#It will not close main window
What will be the wrong i am trying to do , and please explain what is proper method.
Looking for suggestions thanks .
Sorry for my english .
subprocess.call() wait subprocess to exit. -> button callback will never return until subprogram exit. This keep main window to close. Use subprocess.Popen() which does not wait subprocess.
self.Destroy()
subprocess.Popen('python newframe.py', shell=True)
You shouldn't close the main frame or you'll actually exit the application. Instead you should Hide the main frame and just Show the sub-frame. Then when you close the sub-frame, you can re-show the main frame. I personally think using Pubsub is the easiest way to accomplish this. Here's a link to a tutorial that shows how to do it:
http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/
You could also pass a reference to the main frame when you instantiate the sub-frame or call something like GetTopWindow() or GetParent(), but I really recommend Pubsub for this.

thread getting stuck (python w/ GTK)

Basically I have a program that starts a new thread, then tries to do stuff in this new thread. However, the new thread seems to get stuck until the main thread reaches the end of the program.
here is a working example of the problem I'm experiencing. it seems that gtk.main() has to be there for this problem to occur. if I use something like input() instead, the problem doesn't appear.
import threading,sys
class MyThread(threading.Thread):
def run(self):
import time
print('before')
time.sleep(3)
print('after')
MyThread().start()
from gi.repository import Gtk as gtk
class My_window:
def __init__(self):
self.window = gtk.Window()
self.window.connect("delete_event", gtk.main_quit)
self.button = gtk.Button("Hello World")
self.window.add(self.button)
self.button.show()
self.window.show()
My_window()
gtk.main()
What should happens: The window appears, the word before appears, and 3 seconds later the word after appears
What really happens: The window appears, the word before appears, then nothing happens. When you close the window, the word after appears. (As if somehow reaching the end of the program makes all the running threads that were frozen before, running again)
Things I've tried:
Replaced time.sleep with other functions, like a terminal command, or a busy loop. I get the same results
I tried recreating the problem without the window and other extra stuff, but couldn't. so I don't know where this problem resides, so I gave all the background info that I could.
I tried using sys.stdout.flush() to make sure that the text was actually showing up in the command line when it should. It was.
Does anyone have any suggestions as to what the problem might be?
I'm using python 3 (and gtk for the window), and would prefer my program to be compatible on all major os's
edit:
I tried putting a print('starting') right before gtk.main(). the output showed before then starting then after. I'm thinking that calling gtk.main freezes all threads, and when gtk.main ends, then the threads resume.
edit 2:
never-mind, in my original program, the thread was created while gtk.main is running, but there could still be something in gtk.main that is freezing the threads, that is being called every once in a while.
I managed to reproduce this, and spent ages trying to work out why it was failing, until I came across this FAQ entry, which suggested putting...
import gobject
gobject.threads_init()
...at the top of the code, which seems to fix the problem.
My guess is that after calling gtk.main(), GTK is holding on to Python's Global Interpreter Lock, which is a bit naughty for default behavior, but at least there's a way to prevent it.
Note that background threads are not able to manipulate GTK objects directly, so you'll have to have them pass messages to the main thread to do that instead.
if th is the thread object you created, you should th.setDaemon(1) before starting it, otherwise the main thread won't exit without the thread you started exit first.

PyQt restarts shell

If I'm trying to create a window or prompt a file dialog in the IDLE shell, nothing opens and the shell restarts. Is this a bug of some kind? I can't find anything about it. I'm new to PyQt (and Python in general) but had been able to get tutorials to work correctly. The last day or so, if I open IDLE and import PyQt4, QtGui, etc and then run something simple like QFileDialog.getOpenFileName, the shell just restarts. Any ideas?
You need to have a QApplication before you can use anything else from PyQt. Try rereading some of the tutorials you followed, or do a few more. This one for example.
In the first code sample of the above tutorial, pay special attention to these lines (I've included the comments from the tutorial for convenience):
app = QtGui.QApplication(sys.argv)
Every PyQt4 application must create an application object. The
application object is located in the QtGui module. The sys.argv
parameter is a list of arguments from the command line. Python scripts
can be run from the shell. It is a way, how we can control the startup
of our scripts.
and
sys.exit(app.exec_())
Finally, we enter the mainloop of the application. The event handling
starts from this point. The mainloop receives events from the window
system and dispatches them to the application widgets. The mainloop
ends, if we call the exit() method or the main widget is destroyed.
The sys.exit() method ensures a clean exit. The environment will be
informed, how the application ended.
The exec_() method has an underscore. It is because the exec is a
Python keyword. And thus, exec_() was used instead.
It appears you might have forgotten about these. Or maybe you haven't realized that this means that you normally can't use PyQt with a running event loop in the interactive shell. However, there is a trick for that, see here.

Categories

Resources