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.
Related
I am creating a game using Python and tkinter, and when I tried to add some music, the function making the music stopped the rest of the script (and also the window).
So I need to create a new thread I think to play the audio and keep the window working...
I tried some things making errors, not running, or stopping the window, I currently have :
window.after(2000,showText,"Text 1")
window.after(2000,playSound,"Sound 1.wav")
window.after(7000,showText,"Text 2")
Important detail : the playSound function returns nothing, so nothing needs to wait for it.
I also don't know much about programming in Python, I prefer using LUAU.
Try using the module threading. I found this article very useful for understanding the core concepts and setting up my first multithreaded program
I found another article telling exactly how to make it work and it now works.
The article is probably in french, but I give the link : http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_parallelisation/thread.html
I built a small GUI using Tkinter. The GUI features, among some other elements, three buttons. These buttons serve to open a dystem dialog and select certain data-files etc. One of the three buttons is a 'Go' button that runs the underlying data-processing.
When running the .py script the GUI works fine. However, after creating a developer app in alias mode using Py2App the buttons have become invisible! They're still there and usable, but invisible until interacted with.
How can I prevent this from happening?
I was stuck in your exact situation for quite some time. When I ran my tkinter script, it worked perfectly and all the buttons showed up, but once I packaged it, the buttons stopped showing up (They were still there but you couldn't see them). After a long time of trying random things, I found out how to make the buttons and their text show up again. Simply resize the window. Even a difference of 1 or 2 pixels does the trick. I have not yet found a way to PREVENT this issue, but at least this makes the app look right.
Please reply if you figure out a solution to prevent this!
Good Luck!
Looking for help on where to start with this, not too good with Python. What I trying to do is use tkinter for a gui interface but i need to be able to process recieved data and update labels widgets as information changes. I all ready have the communication portion of my program working fine in the shell but when I try to tie it to tkinter it will stop processing as soon as the interface is generated. Anyone have a simple code for me to modify to my needs or point me to a reference example somewhere. Spent days so far trying different options and I still have yet to find something that works.
Thanks for any help
Convert your working program into functions that you can register as callbacks in the tkinter UI (say buttons, or other widgets), that is, make it event-driven, and then, for background processing register some of the functions with the after widget method. The root.mainloop() will never return (only on UI close), use it as the last instruction.
So you can't just write your logic in a top-down structure, and hope that it will work well with the UI. The mainloop will be permanently looping, and will call specific funtions in your code, as appropriate to the received events from the user, or to callbacks you registered to run after some time with after.
See here for the after part
Take a look here for structuring tkinter programs. It should have enough info and links for you to study and learn how to do it in a right way.
I have a GUI program built using Tkinter in python 2.7.10.
It works flawlessly, for it's root cause anyways.
Unfortunately, it briefly goes into windows dreaded "Not Responding" state when being interacted with.
Here's the layout in short:
Launch script launches Main script.
Main script reads settings file and boots GUI script.
GUI script starts GUI.
User enters a term to search for in a series of files.
GUI script goes into a side script to process files and retrieve results.
Side script inherits certain aspects of GUI script.
Side script attempts to update user while working using the inherited elements; the GUI has none of it.
GUI goes non-responsive briefly before returning to the GUI script and displaying the results.
Here's how I need it to go in short:
Launch script launches Main script.
Main script reads settings file and boots GUI script.
GUI script starts GUI.
User enters a term to search for in a series of files.
GUI script goes into a side script to process files and retrieve results.
Side script inherits certain aspects of GUI script.
Side script updates the user with a progress bar and imagery while working, using the GUI elements.
GUI returns to the GUI script and displays the results.
I have the progress bar built, but the imagery is not yet, but if the progress bar will not work, I will not waste my time on the imagery.
Sample impossible, not-being-used-but-shows-the-point code;
GUI;
import Tkinter, PIL, SideScript1
Tkinter()
ShowText()
ShowStuff()
input = GetInput()
ShowProgressBar()
SideScript1.processfilesbasedoninput(input, progressbarcontrolvar)
DisplayResults()
SideScript1
def proccessfilesbasedoninput(input, pbcv):
DoStuff()
pbcv.gofurther(5)
DoMoreStuff()
pbcv.goevenfurther(10)
a1sauce = RandomMathsStuffs()
for all the data in every file in that one directory:
ReadData()
pbcv.goabitfurther(a1sauce)
if data is what I want:
break
pbcv.step(-100)
return data
I guess my question is, How would I get the GUI to update those elements instead of going unconscious?
We are talking 100 000 files and 1.5 seconds its done in.
UPDATE: This question has been marked as a duplicate of another. Is it? Yep. but that's both because I was ((and still am)) unsure of how to search for this kind of question, and that the three solutions there; multithreading, multiprocessing, and smaller tasks. Unfortunately, the program was built to run on a single thread and process, and without a complete rewrite, getting the intended GUI response would cause a massive slowdown, if it worked at all.
I do see the issue, being TKinter is a blocking module. Unfortunately, I am fresh out of ideas on how I would un-block it without causing mass errors, and or a total rewrite.
The linked duplicate question held an answer. A bad one - but an answer none the less.
update_idletasks.
I tried that, and, it Worked! Well. Sort of.
It worked at first, then the same result came about. The GUI temporarily froze.
Then an idea popped in my head. Why not try update instead?
I did so, and it worked as I needed it to, however, it had a massive performance hit - nearly identical to update_idletasks.
To tackle this new problem, I added a bit more math to cause updates to happen, in my case, every 300 files, instead of every single file-balancing the performance hit and users not instantly deleting my program, because yes, it takes a toll on your resources. No, I did not initially heed that advice. Shoot first, ask questions later, right?
How did I use it? Glad I asked! Here's an example;
#GUI Code
DoStuff()
SideScript1.proccessdata(arg, kwarg, debate)
DoMoreStuff()
#File Management Code
DoStuff()
filenumber = 0
maxfilenumber = 0
for every file I need to search:
SearchFile()
filenumber +=1
if filenumber == maxfilenumber:
tkinter.update() #in my case, it was tkinst, or "TkInter Instance", since it was inherited from the GUI attributes.
filenumber = 0
if data is what I want:
break
return data
I'm not sure about all the backend and hard facts, but update() seemed a lot more user friendly and quicker than update_idletasks(), and a lot less prone to errors and slowdowns as well.
My shenanigans are now back in order, running in 60 ((30? 120? 250 million??)) frames a seconds, smoothly and efficiently - and Tk doesn't have a sit-down strike every time I ask it for info anymore!
Thanks #Rawing for the attempt to help!
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.