I'm trying to speed test my code for a tkinter GUI. Naturally, requiring humans to hit buttons would make speed testing inconsistent. I was thinking that I could just have a timed script run each callback sequentially, but some callbacks like image displays wouldn't be able to run without the GUI open. Now I'm looking for ways to run a script on a GUI that's already in its main loop. Is there a way to do this?
Python has a few modules for handling GUI automation but here is a pretty nice tutorial https://automatetheboringstuff.com/chapter18/.
Also with windows you should be able to simulate keystrokes and mouse movements using the win32 api https://sourceforge.net/projects/pywin32/.
Related
So I'm very new to Python so I'm not sure of the correct way to do what I need.
Basically I am creating a laser tag game. The whole game is controlled by some python code that runs on a PC, the hardware is basically just inputs and outputs for this code.
I want to have game files that are simple files with just the code for the game itself, that way it is fairly easy for anyone to make their own game modes.
Then there needs to be a main program with a GUI (Probably Tkinter) and code to handle sending/receiving information from the hardware (Laser tag guns). I need some way to select a game file from the GUI and run it, but I still need the main server code to be running (to take care of sending and receiving information from the guns, displaying live scores on the GUI, etc).
What would be the best (preferably fairly simple) way to go about doing something like this? Thanks!
Cool project! Generally you let TkInter run in the main thread, and have the other tasks executed in other threads or processes. Brace for some hacking, parallelism is unfortunately pretty difficult to do right.
I am trying to embed a chat system (that is a gui) within another gui I have already created. I have tested the chat application separately (it uses socket programming) and it works fine, but when I copy and paste that code into the original gui application (so that when I press a button it opens the chat application), it stops working.
I don't know why this is happening, so any insight would be helpful. I have a feeling it has something to do with the fact that I am trying to run a gui within a gui, but I am not sure, as this is the first time I'm working with python gui's.
Use the Tkinter Toplevel window instead of Tk window. You should never have two Tk windows.
I've got the following problem:
I've written a script which is running up to four processes at the same time. Works like a charm when using it via command line.
Then I made the decision to write a GUI with wxPython and I was quickly figuring out that the GUI and the script need to run in different processes so both stay usable while the other is doing something. (i.e. being able to press a stop button while the script is running) This is also working perfectly.
Now the problem:
I just cannot communicate with the GUI while the script is running or at least I have no idea how. I'm trying to write output in a text window by passing "self" (the gui) to the script and in the script I try to do things like "self.outputWindow.WriteText('the script is doing bla 1 of bla 10')"
I even figured out why this won't work: self (the gui object) is not pickable and that's mandatory for multiprocessing, but I don't know how else I should do it.
You can use my tutorial on wxPython and threads, although I'm not sure if Python spreads those threads evenly to all the cores. I suspect it doesn't.
Fortunately, there are examples of using the multiprocessing module with wxPython. See the following links:
http://wiki.wxpython.org/MultiProcessing
wxPython non-blocking GUI threading AND multiprocessing?
wxpython GUI and multiprocessing - how to send data back from the long running process
http://www.blog.pythonlibrary.org/2012/08/03/python-concurrency-porting-from-a-queue-to-multiprocessing/
I hope those are helpful!
I have looked at similar questions that may answer my question but I am still very unclear on how to go about the following:
I can create programs to run in the Python Shell in Idle and I can also set up windows with widgets in Tkinter, but whatever I create in Tkinter is pointless because I cannot figure out how to take my Python Shell code and "wrap" it in the Tkinter GUI.
I have assumed that it cannot be done, and that entirely new code must be written to assist the language that is specific to Tkinter. I am very confused on how to create a well-rounded program without being left with just a GUI "skeleton" with random buttons, labels, entries, etc. and a Python program that is very unappealing and can only run in the ugly little Shell.
What you create with Tkinter is not pointless. It sounds to me like you're trying to compile a stand-alone program in Python, using the Tkinter library to provide the GUI. Once you have a script working, you can use a program to compile into a standalone program. Look into using py2app on a mac, or py2exe on Windows. Google them and see if that's what you're looking for.
Porting an application from command line to GUI might require some rework (depending on degree of interactivity you want to achieve).
Basically, in a GUI application, you build a few widgets (buttons...) at startup, and then perfom all your actions "on reaction" of user input. You typically do this by binding callbacks onto your widgets (button, input field), and then enter a mainloop (or eventloop).
You might read this chapter about events and binding.
If your application is mainly computing oriented, providing a gui with a "launch" button, and an output field is straightforward. If you perform some command line input, you can switch to widget input at low cost. More interactive apps will require to be architectured toward interaction capabilities.
I've seen a lot of stuff about running code in subprocesses or threads, and using the multiprocessing and threading modules it's been really easy. However, doing this in a GUI adds an extra layer of complication.
From what I understand, the GUI classes don't like it if you try and manipulate them from multiple threads (or processes). The workaround is to send the data from whatever thread you created it in to the thread responsible for the graphics and then render it there.
Unfortunately, for the scenario I have in mind this is not an option: The gui I've created allows users to write their own plotting code which is then executed. This means I have no control over how they plot exactly, nor do I want to have it. (Update: these plots are displayed in separate windows and don't need to be embedded anywhere in the main GUI. What I want is for them to exist separated from the main GUI, without sharing any of the underlying stack of graphics libraries.)
So what I'm wondering now is
Is there some clean(ish) way of executing a string of python code in a whole new interpreter instance with its own ties to the windowing system?
In response to the comments:
The current application is set up as follows: A simple python script loads a wxPython gui (a wx.App). Using this gui users can set up a simulation, part of which involves creating a script in plain python that runs the simulation and post-processes the results (which usually involves making plots and displaying them). At the moment I'm doing this by simply calling exec() on the script code. This works fine, but the gui freezes while the simulation is running. I've experimented with running the embedded script in a subprocess, which also works fine, right up until you try to display the created graphs (usually using matplotlib's show()). At this point some library deep down in the stack of wxPython, wx, gtk etc starts complaining because you cannot manipulate it from multiple threads.
The set-up I would like to have is roughly the same, but instead of the embedded script sharing a GUI with the main application, I would like it to show graphics in an environment of its own.
And just to clarify:
This is not a question about "how do I do multithreading/multiprocessing" or even "how do I do multithreading/multiprocessing within a single wxpython gui". The question is how I can start a script from a gui that loads an entirely new gui. How do I get the window manager to see this script as an entirely separate application?
The easiest way would be to generate it in a temporary folder somewhere and then make a non-blocking call to the python interpreter, but this makes communication more difficult and it'd be quite hard to know when I could delete the temp files again. I was hoping there was a cleaner, dynamical way of doing this.
Can you simply use subprocess to run 'python.exe' and pipe the script in?
Alternatively, the multiprocessing package should suffice if you want to move some (pickle-able) data over to the new process in which you run the script. Just create a function/callable that runs the script, and create a Process object with the callable as target. That way, you should be able to pass some data over, without having GUI issues.
Capturing text with either is easy, subprocess allows that and no more. With multiprocess, you can pass python objects back and forth more easily.
On Windows, you can create window with a parent window from another process, and draw to that.
See the hWndParent argument to CreateWindowEx.
If wxWindows supports getting/setting that explicitly, then you should be good to go.
Depending on your platform, something similar might be possible in any windows system.
So, just giving your users the ability to find the handle of your apps window should give them the option to plot away at views embedded in your app, while running in their own processes.
I don't no much about wx, I work with jython(python implemented in java and you can use java) and swing. Swing has its own worker thread, and if you do gui updates you wrap your code into a runnable and invoke it with swing.invokelater.
You could see if wx has something like that, if you however are only allowed to manipulate the gui from the thread in which you created it try something similar. create a proxy object for your gui, which forwards all your calls to your thread which forwards them to the gui.
But proxying like this gets messy. how about you let them define classes, with an 'updateGui' function, that they should hand back to you over a queue and that you will execute in your gui thread.
In wxPython land when you use threads, you have to use its thread-safe methods to communicate with the GUI: wx.CallAfter, wx.CallLater or wx.PostEvent. In your case, I would run any long running code in a separate thread/process and when it's done its processing, send the result to the GUI. The GUI can instantiate a new frame and use matplotlib or PyPlot to show the plot, depending on which way you want to go. I've heard you can draw the plot using FloatCanvas too.
Anyway, if you instantiate the new frame correctly, then you can instantiate N frames and show them and be fine. See the wxPython wiki for a few examples of using Threads with wx: http://wiki.wxpython.org/LongRunningTasks