I am writing a small application in Qt (with PySide in Python), which makes extensive use of QGraphicsView and displays animations (sort of). There are a few buttons to start/stop/pause and a few other widgets.
At first, I thought I should use QThread to handle the graphics and send signals to the main thread to QGraphicsScene etc., so I began implementing it. It worked, but I was not very satisfied with it - I tried a few different ways, but I think I overcomplicated it too much and the signal/slot mechanism and locking QMutexes was not even that fast.
Then (I am new to PySide), I found the processEvents() method in the docs. I tried implementing it and it works just the way I want, it's fast and simple.
Right now I am using it and everything is done on the main thread, and the GUI is responsive.
My questions are: Is it wrong to use that method in that way? Should I just stick to QThreads?
These questions are related to these...
How to make Qt work when main thread is busy?
Should I use QCoreApplication::processEvents() or QApplication::processEvents()?
... where others say it should not be used.
Related
I'm wondering how difficult it will be to use invoke matplotlib from a Tcl interpreter and plot to a Tk canvas created on the Tcl side.
I'm wondering what the best way to do this is.
I'm guessing I'll have to create a python interpreter, pass the canvas handle from the Tcl side to python and make use of the C API in both languages. Or is there a more elegant way?
Getting this integration right won't be easy. However, here's what I'm thinking about:
Connecting Python and Tcl
You can run Python inferior to Tcl apparently. According to this wiki page, there's a package called tclpython which can do the basic integration work for you, and the page linked to appears live. The code appears to be here, though it might need some work to make it build. (I've never tried.)
Connecting matplotlib and Tk
You can make matplotlib draw on a Tkinter window, and as long as you can make that Tkinter window with the right options, it will show up. The key is that the underlying system window IDs can be found out from Tk with winfo id $nameOfTheWindow. If you create a frame with the -container option set to true (which turns off some things and turns on a few others; you'll need to set the size explicitly) then that particular frame will be suitable for use with TkAgg on the python/matplotlib side. The key will be to make a toplevel on that side that has the -use option set to the ID retrieved from winfo id. You probably need to make sure that the python side is running its rendering in a separate thread to the outer Tcl/Tk to make the event handling work right (unless you're keen on doing deep event loop hacking; the situation is that you're actually going to have Tcl/Tk inside Python inside Tcl/Tk, as Tkinter works by delegating to a subordinate Tcl/Tk, and getting all this glued together right will be “a bit tricky”).
If that doesn't work, get matplotlib to render as an image (GIF or PNG; the latter is preferred if you've got Tk 8.6) as you can just show that easily via a photo image. This is definitely going to be possible to do without thread games; it's just passing around pure data. Probably slower and not interactive, but that might not matter for what you're doing, and it is easier in the simple case.
You will probably need the second approach if you're on Windows or OSX, as Tk there doesn't actually use X11. (Unless you're using one of the more perverse configuration options, of course.)
I'm writing some test functions for a form I made. There are a couple of QMessageBox that are invoked(one through QMessageBox.question method and one through the QMessageBox.information method. While my custom widget is not shown on screen, these two actually show up on screen.
I tried dismissing them by looping through widgets I get in QApplication.topLevelWidgets() and dismissing the right one, however, it seems my code only continues executing after I manually dismiss the MessageBox.
So my question is two-fold:
1) How do I keep the QMessageBox (or any widget really) from showing on screen during testing.
2) How can I programmatically accept/reject/dismiss this widget.
You can set up a timer to automatically accept the dialog. If the timeout is long, the dialog will still display for a while:
w = QtGui.QDialog(None)
t = QtCore.QTimer(None)
t.timeout.connect(w.accept)
t.start(1)
w.exec_()
For your specific case, if you don't want to touch the code being testes, you can have the timer run a function to accept all current modal widgets, as you were suggesting:
def accept_all():
for wid in app.topLevelWidgets():
if wid.__class__ == QtGui.QDialog: #or QMessageBox, etc:
wid.accept()
t = QtCore.QTimer(None)
t.timeout.connect(accept_all)
t.start(10)
I decided to use the mock module instead. It seemed better since the other solution would actually draw on screen, which is not optimal for testing.
If you have the same problem and would like to mock a question QMessageBox you can something like this:
#patch.object(path.QMessageBox, "question", return_value=QtGui.QMessageBox.Yes)
Would simulate a MessageBox in which the Yes button was clicked.
I think it makes sense with Qt testing (including PySide/PyQt) to mock your GUI interaction and do dedicated GUI testing separately as necessary.
For mocking GUI interaction, I'd use the mock library, as I myself do regularly. The drawback of this is that you have to depend on mock definitions, which may drift out of sync with respect to your production application. On the other hand, your tests will be speedier than involving the actual GUI.
For testing the GUI itself, I'd write a separate layer of tests using a GUI testing tool such as Froglogic Squish. It'll typically lead to more involved/slower tests, but you'll test your application directly, and not merely simulate the GUI layer. My approach in this regard is invest in such a tool if the budget allows, and run these tests as necessary keeping in mind they'll be relatively slow.
I'm using Qt Designer to create UI designs which I'm then converting into python code. Since I'm quite new to Qt I'd like to ask: is there a way I could implement a multi-screen application? I.e. having a next button clicked and getting a new set of options/widgets etc within the same window.
To be honest, I was developing using Kivy, and as slick as that is (especially with multiple screens) it depends on PyGame, which proves to be an enormous portability headache, so I had to switch to something else, and PyQt was the next feasible option (or so it seems).
It's called a QWizard. It is not called a multi screen application, but if you search for wizard instead, you find lots of information.
Links
Example with C++ code
[PyQt QWizard documentation] http://pyqt.sourceforge.net/Docs/PyQt4/qwizard.html
I'm a new in Python.
I would like to know can I create good interface on python, something like WPF?
I didn't find any glass effect with PyQt. It's really important for my decision.
Thanks.
I'm sorry that I didn't give a lot of details. I need to port WPF app to python. The main goal I still need a good UI. Can I make something like this
http://www.codeproject.com/KB/silverlight/SilverlightGlassOrbButton.aspx?msg=3170079
on python? Can I use different styles for mouseover and normal state?
Glass effect is probably a Qt skin and has nothing to do with Python in particular. People say that there's a tutorial for Qt skinning. I failed to quickly google a ready-made glass-like skin, though.
Also, in the new QT RC there is a new support system for GUI related stuff. QML it is called, and examples can be found here. I do not know if it alreade wrapped in PyQT but I suppose it is possible to use it in combination with PyQT.
If glass effect = transparency, then Qt supports this, but it requires a special flag set on the window. See http://doc.qt.nokia.com/qq/qq16-background.html for some examples.
If you want a blurred background, then I doubt it can be done as easily, since not many GUI-frameworks that Qt supports do compositing like Vista & Win7, so it's probably hard to abstract into a cross-platform toolkit.
But simpler things might be possible, and with QGraphicsScene, you can do a lot of these things yourself (but not w.r.t. the window's background, IIUC).
If you have no luck with Qt, wxPython can do it. See How to draw a transparent frame in wxpython.
You can check out the fluent app library
I am attempting to create my first OS-level GUI using wxPython. I have the book wxPython in Action and have looked at the code demos. I have no experience with event-driven programming (aside from some Javascript), sizers, and all of the typical GUI elements. The book is organized a little strangely and assumes I know far more about OS GUI programming than I actually do. I'm fairly recent to object-oriented programming, as well. I'm aware that I am clearly out of my depth.
My application, on the GUI side, is simple: mostly a set of reminder screens ("Turn on the scanner," "Turn on the printer," etc) and background actions in Python either in the filesystem or from hitting a web service, but it is just complex enough that the Wizard class does not quite seem to cover it. I have to change the names on the "Back" and "Next" buttons, disable them at times, and so forth.
What is the standard process for an application such as mine?
1) Create a single wxFrame, then put all of my wxPanels inside of it, hiding all but one, then performing a sequence of hides and shows as the "Next" button (or the current equivalent) are triggered?
2) Create multiple wxFrames, with one wxPanel in each, then switch between them?
3) Some non-obvious fashion of changing the names of the buttons in wxWizard and disabling them?
4) Something I have not anticipated in the three categories above.
I don't have a good understanding of your application, but trying to force wxWizard to suit your needs sounds like a bad idea.
I suggest checking out the Demos available from the wxPython website. Go through each demo and I bet you'll find one that suits your needs.
I've personally never used wxWizard as I find it too cumbersome. Instead, I create a sequence of dialogs that do what I need.