PyQT force rendering some widget before calling other function - python

I am designing a GUI for a Python project that manages some simulations. As the simulations take some time, I want to have a window that tells the user to wait, popping up when the simulation is started.
Currently, the code is like
def start_simulation(self):
self.calculation_running_dialog.show()
heavy_function_call(self)
self.calculation_running_dialog.hide()
However, I face the following problem: When the simulation is started the window does appear, but it is rendered with a transparent body in Ubuntu and with an empty (white) body in Windows. Only after the heavy function call has terminated, the window is rendered properly. How can I force the window to be displayed properly before the simulation starts?
Recently, I have asked a similar question here: PyQT force update textEdit before calling other function.
For that purpose, the repaint() function turned out to be the solution. But for the current problem, neither self.calculation_running_dialog.repaint() nor self.calculation_running_dialog.update() or self.calculation_running_dialog.textLabel.repaint() does the trick.
Any suggestions?

Related

Python PyQt Close Hidden Window

I create my main window as hidden because I just need it to do something in the background. I don't call self.show(), then when it's done, I call self.close(), but it looks like the close() function doesn't work on a window that isn't visible. I'm probably missing something obvious, but I can't seem to find any answers in my Google searches. I'm using PyQt6 and running Python 3.10.5.
I know that I can call show() first and close() immediately after, but that makes the window appear for a flash and takes focus away from the main view. I also know that I can call QApplication.instance().quit() to completely close the app (as this background task is all the app is doing), but I want to make sure there's not a better solution.

Python : How to deal with threads priority in Gtk3

I am building an user interface using Python, Gtk3 and Glade. I want to change several things on the UI at the same time (i.e start an animation and display a new text) which leads to the application freezing.
I have read that Gtk wasn't thread safe so I didn't used the Thread module.
Instead, I used Glib.idle_add and Gdk.threads_add_idle functions. I am tryig to update a treeview, display some text and show an animated logo at the same time. The application works but it freezes a few seconds and then everything appears at the same time. I try to set different priorities to the threads but it does'nt seem to fix it.
Gtk.threads_add_idle(Glib.PRIORITY_DEFAULT, label.set_text, "text_to_set")
Gtk.threads_add_igle(GLib.PRIORITY_DEFAULT, function_to_display_logo)
I expect the different texts and the treeview and the logo to be displayed without any freeze. Does anyone know how I can fix that ?
Please have a look here at a script example in https://github.com/f4iteightiz/UWR_scoreboard : a GTK window is updated all 0,2s for example (countdowns of several timers appearing in labels; I think anything else could be updated) and it stay reactiv the whole time. No freezing noticeable.
I found out what my error was. I was using the GLib.idle_add function too many times even in some cases where I had no use for it.
For example in the main code I had :
Glib.idle_add(my_function,buffer)
but my_function looked like this :
def myfuntion(buffer):
GLib.idle_add(buffer.set_text,"text")
I deleted the GLib.idle_add call in the main code and now it works perfectly.

Getting screenshot via printwindow not redrawing if laptop screen off

My goal is to take screenshots off an application while the laptop screen is off, but instead the screenshot will always be the same as just before turning off the screen. It does not redraw itself once the screen is off, and remains frozen.
I'm obtaining a screenshot using printwindow from Python (using method described here: Python Screenshot of inactive window PrintWindow + win32gui
This method works nicely as long as I have my laptop screen on, but if I turn it off, it simply returns the last image before the screen turned off. I've tried using win32gui.RedrawWindow, hoping that this would force a redraw, but I haven't gotten it to work, even trying all the different flags. I've also tried getting screenshots via pyautogui, but this also has the same problem. Is there any way to redraw the application while the laptop screen is off?
It would be nice if there were a straightforward way to do what you want to do, but unfortunately it's just not possible without some convoluted low-level work.
In the underlying WinAPI, native windows redraw themselves only when they receive WM_PAINT messages, and they only receive WM_PAINT messages if they are visible. They don't get the messages if they're behind another window, or if they're dragged off screen, or minimized, or their visibility is set to False. They also aren't visible when the screen is off. Since they aren't visible, they simply never get told to redraw themselves. That's why the screen capture image doesn't change after the screen is turned off.
There is no command you can issue that will override this -- it is implemented as a fundamental part of the windowing paradigm.
One solution is to have the application paint itself in something that's not a window (e.g., a dialog box) and capture that rather than capturing the screen. You could also modify the application by overriding OnPaint and using a timer to invalidate and call your OnPaint function periodically (since WM_PAINT messages won't be received).
If it were me I'd override OnPaint, make my application draw itself to a background context bitmap rather than the normal window, then use a timer to invalidate and redraw periodically and just take the bitmap of the background context whenever I wanted to capture the output.
If you don't own the code for the applications that are running, you may still be able to get applications to redraw themselves by running everything in a virtual machine. I've done that successfully for headless computing in the past, but it was many OS versions ago and things may be different now, so YMMV...
Information on manual screenshots under VMWare is here.
Information on programmatic screenshots under Hyper-V is here.

Functions acting strange when run as thread in Kivy/Python

I am building an app that, when the user hits a 'run' button, generates a table of buttons.
Because this process takes a while, I want to add a popup or progress bar to alert the user that the function is running and not frozen. To do this I decided to create a popup and call my function using threading so that the screen will be updated when the function starts (as opposed to once it is done).
mythread = threading.Thread(target=run_function)
mythread.start()
The trouble is that when I call my function from the above code it works very strangely: the columns of my table are the wrong width, some of my buttons are arbitrarily empty, and others have the wrong fill color. To fix this, all I need to do is to remove the threading operation and simply call run_function()
Any idea why this is happening?
I am new to Python, so it is likely some dumb mistake, but I have no idea. What is different between a process running as a thread and its default operation?
Disclaimer: I haven't worked with Kivy.
Not every framework works well with multithreading.
But most of the GUI frameworks have an event loop which is responsible for managing user events (mouse clicks, keyboard) and queued drawing operations (widgets).
In your case if don't want the UI to be freezed, you should regularly give control to your framework's event loop.
I guess kivy.base.EventLoopBase.dispatch_input is what you need to call to show an added widget or to handle user events.

Force update GUI in kivy

I am writing an app in kivy which does cpu-heavy calculations at launch. I want the app to display what it's doing at the moment along with the progress, however, since the main loop is not reached yet, it just displays empty white screen until it finishes working. Can I force kivy to update the interface?
Basically I'm looking for kivy's equivalent of Tkinter's root.update()
I could create a workaround by defining a series of functions with each calling the next one through Clock.schedule_once(nextFunction, 1), but that would be very sloppy.
Thanks in advance.
Leaving aside the question of whether you should be using threading or something instead (which possibly you should), the answer is just that you should move your cpu calculations to somewhere else. Display something simple initially (i.e. returning a simple widget from your build method), then do the calculations after that, such as by clock scheduling them.
Your calculations will still block the gui in this case. You can work around this by doing them in a thread or by manually breaking them up into small pieces that can be sequentially scheduled.
It might be possible to update the gui by manually calling something like Clock.tick(), but I'm not sure if this will work right, and even if so it won't be able to display graphics before they have been initialised.

Categories

Resources