How to imbricate a QApplication inside a main QApplication - python

I'm currently working on a GUI interface that runs a GNU Radio script rendering some Qt windows (plotting real time histogramm, waterfall graph, or other nice gui...). I control its parameters and launch it from my first main windows. I'd like to integrate the QApp created by launching the GNU Radio script inside a widget of my first main windows (which is another QApp).
I already tried to run a second QApp in the same time of my first one, for some reasons, I get errors like QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread.
I did not work around this error because a nicer idea would be to have a kind of container whom I would give a PyQt4.QtGui.QApplication object to make him execute and display it without creating a second windows.
Does that kind of container exist ?
Thanks a lot !

Related

Why are my definitions gone when using exec() with pyqt?

i am facing some understanding problems since i am trying do dive into pyqt´s gui programming.
I use
exec(open("./regression.py").read())
inside my pyqt gui program to call a script where my calculations are made after the user has pushed some buttons (these define some variables in regression.py)
so if i run this in an empty script all my definitions are callable (and i see them in the variable explorer).
if i try to run this in my gui program - the script executes but if i wanted to reuse one variable or a method i defined in the regression.py in another action of my gui it is not possible.
Everything is gone after execution.
...
self.connect(self.buttonOK,
QtCore.SIGNAL("clicked()"), self.onOK)
def onOK(self):
if self.button1.checkState():
a=3
if self.button2.checkState():
a=1
exec(open("./regression.py").read())# this scripts takes the value of "a" to run
# it prints some calculations - but everything is gone after pressing "OK" button
app = QtGui.QApplication(sys.argv)
dialog = MeinDialog()
dialog.show()
Why is that the case? how can i find a solution? is my method of spitting gui and actual calculations using modules like numpy and so on right?
exec is a python call. In PyQt you need to use exec_().
[edit] I read the question too quickly. I thought the problem was starting the eventloop, not getting variables from another process. Can you import your regression module and run it in process, instead of using exec?

How can I add a simple non-interactive gui to my python application?

I have written a little python utility that monitors my typing speed, using pyxhook to hook keyboard events, and a thread timer to update my words per minute number.
Right now it just prints to the terminal every 2 seconds.
How can I make this appear in a little always-on-top gui box?
I tried playing around with tkinter, but the mainloop() function doesn't like my key listener and timer. It seems I can only run the gui OR my event handlers, but not both.
Unfortunately I don't think I can use the keyhandler in tkinter, since I am wanting to capture events from other windows.
Any suggestions?
I don't know how to go about doing this in tk, but I've been using PySide lately and I know you could use that.
One way to do it in pyside would be with two classes running in separate threads that communicate using the Qt signal & slot mechanism available in pyside. One class would subclass QThread & get methods that run your existing code & pass the data via signals to the Ui class. The 2nd class would be the one for your gui elements. it would call for an instance of the first class, connect the signals & slots, then start it & begin drawing the display.
resources if you go the pyside route:
http://www.matteomattei.com/pyside-signals-and-slots-with-qthread-example/
search 'pyside dock widget' on this site
search for github's pyside examples
https://pyside.github.io/docs/pyside/PySide/QtCore/QThread.html?highlight=qthread

Executing a python script in a subprocess - with graphics

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

PyQt restarts shell

If I'm trying to create a window or prompt a file dialog in the IDLE shell, nothing opens and the shell restarts. Is this a bug of some kind? I can't find anything about it. I'm new to PyQt (and Python in general) but had been able to get tutorials to work correctly. The last day or so, if I open IDLE and import PyQt4, QtGui, etc and then run something simple like QFileDialog.getOpenFileName, the shell just restarts. Any ideas?
You need to have a QApplication before you can use anything else from PyQt. Try rereading some of the tutorials you followed, or do a few more. This one for example.
In the first code sample of the above tutorial, pay special attention to these lines (I've included the comments from the tutorial for convenience):
app = QtGui.QApplication(sys.argv)
Every PyQt4 application must create an application object. The
application object is located in the QtGui module. The sys.argv
parameter is a list of arguments from the command line. Python scripts
can be run from the shell. It is a way, how we can control the startup
of our scripts.
and
sys.exit(app.exec_())
Finally, we enter the mainloop of the application. The event handling
starts from this point. The mainloop receives events from the window
system and dispatches them to the application widgets. The mainloop
ends, if we call the exit() method or the main widget is destroyed.
The sys.exit() method ensures a clean exit. The environment will be
informed, how the application ended.
The exec_() method has an underscore. It is because the exec is a
Python keyword. And thus, exec_() was used instead.
It appears you might have forgotten about these. Or maybe you haven't realized that this means that you normally can't use PyQt with a running event loop in the interactive shell. However, there is a trick for that, see here.

Using wxSpellCheckerDialog in Django is causing a C++ "wxThread::IsMain()" assertion failure

Continued from How to use wxSpellCheckerDialog in Django?
I have added spell checking to Django application using pyenchant.
It works correctly when first run. But when I call it again (or after several runs) it gives following error.
PyAssertionError at /quiz/submit/
C++ assertion "wxThread::IsMain()"
failed at ....\src\msw\evtloop.cpp(244) in wxEventLoop::Dispatch():
only the main thread can process Windows messages
How to fix this?
You don't need wxPython to use pyEnchant. And you certainly shouldn't be using wx stuff with django. wxPython is for desktop GUIs, while django is a web app framework. As "uhz" pointed out, you can't call wxPython methods outside the main thread that wxPython runs in unless you use its threadsafe methods, such as wx.CallAfter. I don't know why you'd call wxPython from Django though.
It seems you are trying to use wx controls from inside Django code, is that correct? If so you are doing a very weird thing :)
When you write a GUI application with wxPython there is one main thread which can process Window messages - the main thread is defined as the one where wx.App was created. You are trying to do a UI thing from a non-UI thread. So probably at first run everything works (everything is performed in the GUI thread) but on second attempt a different python thread (spawned by django?) is performing some illegal GUI actions. You could try using wx.CallAfter which would execute a function from the argument in GUI thread but this is non-blocking. Also I've found something you might consider: wxAnyThread wxAnyThread. But I didn't use it and I don't know if it applies in your case.

Categories

Resources