Instantiating a new WX Python GUI from spawn thread - multithreading

I have main thread that runs a WX Python GUI. The main GUI gives a user a graphical interface to select scripts (which are mapped to python functions) and a 'Start' button, which spawns a second thread (Thread #2) to execute the selected scripts. The problem I am having is I cannot get a new WX GUI (GUI2) to popup and give the user the ability to enter data.
# Function that gets invoked by Thread #2
def scriptFunction():
# Code to instantiate GUI2; GUI2 contains wx.TextCtrl fields and a 'Done' button;
# When 'Done' button is clicked, data entered in fields are process and second GUI is destroyed
gui2Frame = Gui2Frame(None, "Enter Data Gui")
gui2Frame.Show(True)
# This is where I need help. Cannot figure out how to pend for user input;
# In this example; my 'Done' button sets the Event flag
verifyEvent = threading.Event()
verifyEvent.wait(10)
# Process entered data time
processData()
Currently, this approach locks up the GUI2 for 10sec. Which makes sense, because the spawned thread is locked up. Implementing a while-loop with a time.sleep(), does the same. I looked into spawning a third thread, just to handle GUI2, but again, I get back into not knowing how to hold GUI2 active. Any suggestions? Also, please no recommendations about changing the multithreading architecture into one thread; Thank you.

You can't have two wxPython mainloops in one program. You really do have to use just the first wxPython program's main thread. If you want to spawn another application, then use subprocess. Something like this should work:
import subprocess
subprocess.Popen("python path/to/myscript.py")

Related

Groovy lanaguge - How to destroy/switch to an application

I'm using the groovy language in robotic application (RPA Express). I can not figure out how to do two things in the groovy language.
I start an application with these command:
def proc = new ProcessBuilder( args )
Process process = proc.start()
My questions are:
How do I close this application? (I want to close the application at the end of the script)?
How do I switch to this application window? (I want to be sure the application window is always focused)?
Both depend on the OS.
You need to invoke a kill task command to kill the process by its pid (e.g. kill on Linux). As Joachim mentions in the comments, Process has destroy() and destroyForcibly().
You need to use the window manager API to focus the window of the given pid you want.

What is the best method to tell a function in a tkinter GUI to wait until a system call made by shutils resolves before proceeding?

I have a tkinter GUI that at some point prompts the user for a folder, checks if it exists, and then, if it does and the user consents, deletes and recreates it. I am doing this via the following code:
try:
self.status_string.set('Cleaning up output directory to be overwritten')
shutil.rmtree(output_folder)
while os.path.exists(output_folder):
time.sleep(1)
os.makedirs(output_folder + '/events')
except OSError:
self.status_string.set('Failed to create directory {0}, verify that you have permission to do so'.format(output_folder + '/events'))
I am currently calling time.sleep in order to force it to wait until the directory has been completely removed before trying to recreate it, because the contents can be large and it may take a while and I want to avoid the race condition. But it seems wrong to me to be using sleep during the mainloop of tkinter, and I am not certain that checking for existence after calling rmtree is valid. It seems to work in testing, but that could be luck. What is the proper way to wait for the system call to resolve before proceeding?

How can I use win32gui in order to have an app run in the background?

I was able to find a great piece of code from here on how to create a Tray app using the win32gui module.
However, that app runs based on a function called notify which only runs when the mouse is moving over the icon.
How can I make the app do something constantly in a loop, regardless of what the user does?
(In other words, I want to use win32gui in a non-event-based way.)
Instead of using win32gui.PumpMessages (which runs its own loop) in the code, replace it with the following loop:
while True:
your_function()
win32gui.PumpWaitingMessages()
This will allow you to run your own functions in the program loop.

How to Launch a function using threads in Perl

I have tried to call a function using threads using perl in my windows system.
But, during the execution, when i click the button to create a thread process, Microsoft error message is displayed as shown below,
"Perl Command Line Interpreter.
Please tell Microsoft about this problem."
Code Snippet i used in Perl:
use threads;
##### Creation of a dialog box using Tkx Module #####
$Run = $MainFrame -> new_ttk__button(
-text => TEXT,
-width => 15,
-command => sub
{
threads -> create({"stack_size" => 64*4096,
"exit" => "thread_only"},
\&CALLING_FUNCTION);
}
);
It looks like Tk having difficulties with threads: Perl Update UI on Long Thread
You need to create your thread before the Tk objects, maybe it is going to work this way.
However, using threads with Tkx may be dicey. I was getting segfaults
when I tried to join the thread rather than detach it, and I get a
segfault with the code below if I move my $t inside startWork(). This
discussion suggests that you may need to start the thread before
creating any Tk widgets for it to work reliably.
Your problem comes because you are letting Tk code get copied into
your thread, by starting it late in the script. When a thread gets
launched, a copy of the main thread is made, so if there are Tk
widgets already in existence, they get copied in. Even if you don't
use the Tk code in the thread, it can cause problems, and will be
unreliable. So...... create your thread first, before starting any Tk
widget code.

wxpython threading textctrl disappears until files are processed

Appropriate code provided below. I had this working once but have since messed up due to having to change some of the other code. Can't figure out what I've done. The encrypt function creates a thread and makes a call to function EncryptProc to process one or more files. Once each file is completed it should print the name to a textctrl. In the codes current state it waits until all threads/files are processed before printing. It then prints evrything in one go. During processing the textctrl also completely disappears. Any help would be much appreciated as its starting to drive me nuts, lol.
---EDIT---
CODE REMOVED
There should be no GUI access from within threads - in your case EncryptProc is writing to the text control directly - you need to either:
Use CallAfter in the thread to update the text control after the thread exits or
Raise custom event an event in the thread that carries the file name information
and have a hander in the main thread that updates the text control
on receiving the event.

Resources