I'm a (relatively) novice programmer working in Python and Tkinter. The GUI app I'm building has many input fields, and all the data ultimately needs to end up in a file.
I'm wondering about the wisdom of trying to build this without a "save" button, so that it would operate like, say, Google Docs, in which the saving seems to happen more-or-less continuously. I'm worried about my (relatively computer-phobic) users assuming things are being saved to the file as they change various menu entries.
Specifically: is that just done via a background process saving every few seconds, with a save forced if the user tries to close between the auto-saves? Does one try to trigger the saves more intelligently than that? What are the issues?
Related
I want to make it impossible for a user to copy data to the clipboard as long as my program is running. How would I go about to do that in Python ?
You could simply render the text as a graphic.
This way selecting text would not be possible.
I have to point out, that stuff like this is always a bad idea, and if the user wants to get the text, he will.
In the past I used screenshots with OCR to get texts.
It's not worth the effort, and in most cases doing stuff like this will just result in the user not wanting to use your program.
My engine is written in GO and I already use SQLITE because I generate some plots that I want to display in a GUI. So far, I think that GO does not have a mature GUI package, so I am building my GUI in Python, with Tkinter that I am familiar with.
When I run my engine in GO with a certain flag, it calls the Python script for the GUI and it generates the content on the background continuously. There are certain modes that the GO engine runs and normally I have to change them by going back to the terminal that runs GO (different plots etc).
What I want, is to create action buttons in my Python GUI that they will change those flags/variables values and the GO script will generate different plots for example, without me going back to the terminal that runs the GO engine and manually do it.
So far, the only implementation from my side, was to create another SQLITE database and save my settings there. Then, when I press an action button at my GUI, it changes the value at my Settings Database and GO reads this value from there all the time, instead of waiting me to input it.
Is there any better way of doing it, passing a variable value(flag etc) from one programming language to the other(Python-GO) without using a database?
The variables that I am changing from the GUI are strings in general and I am asking this question because I think that it is a waste of resources to do it the way I do it.
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!
Say I have been using a GUI where I need to click a few buttons and type in a few fields here and there, was wondering if:
Will it be hard to hard-code to still toggle/"touch" such buttons or fields but without the user input? Sort of like a one script does all..
Also the GUI was already done by some other developer and it is coded in PyQt and some other local modules... And I am still pretty much a noob...
I have a wxPython application with a multi-stage GUI. First a simple form pops for selecting from one of many (> 100) options (it's a part number list with a search box). Once the user has made their selection it builds the appropriate form and shows it, hiding the initial selection dialog. Due to the nature of this project, each secondary form has several matplotlib figures in a Notebook, around 7 or 8 figures each with 2-5 axes each. Because of this, the form takes several seconds between initialization and when it can be shown on the screen.
Does wxPython have a way to build a frame in the background? I don't mind forcing the user to wait a short while before it can be shown, but as it is right now building the form hogs the event loop and everything becomes unresponsive. If I use a thread to build the form, it completes successfully but when I call .Show() nothing happens and there's no error message.
As you can imagine, such a GUI has fairly complex code so it would be difficult to show a SSCCE (and it's not open source). If needed I can try to hack together something that would approximate my problem.
I have used BusyInfo before to tell the user that something is happening. You would put that in your frame's init() BEFORE you actually start creating the matplotlib figures. You can read about it here:
http://wiki.wxpython.org/BusyInfo
Another idea would be to create a second frame with a progressbar in it and a message. The progressbar would be set to just bounce back and forth and when you got done creating the matplot stuff, you would close the second frame.
Mike's idea of using wxBusyInfo is useful when something takes a long time, but it's possible you could make it take less time instead (or at least as well).
First, when inserting many (although I wouldn't say that 100 is that many, 1000 however definitely is) items into a wxChoice, freeze it before adding them -- and thaw it afterwards. This should cut down the time needed for the insertion drastically.
Second, creating all controls of a multi-page wxNotebook (or another wxBookCtrl) can be long, even in C++. So the idea is to not do it immediately but only create the controls of the page you are going to initially show to the user. And then create the other pages controls only when the user is about to select them, i.e. in your wxEVT_BOOKCTRL_PAGE_CHANGING event handler.
If you put this in place, you might not need wxBusyInfo any longer...