I believe that, with version 4, Qt is available under a free software license on all platforms, including Windows. - Yes, it is, but it'll take some time till pyQt4 will be available (and it'll start with Qt 4.1 support, 4.0 isn't planned). See Pyqt homepage. Qt is GPL, as is PyQt, as will be your app if you use it (and plan to actually distribute it ;-)). If you don't want to go GPL, you can buy commercial licenses for Qt and PyQt.
With Qt 3, you can develop under linux and your program will run on windows too, so you won't need Qt3 for Win, only your users; there are free and cheap versions of Qt3 for Windows, but I never went there.
I've used wxPy a lot (several medium-to-large programs), and PyQt only a little (one program, 500 lines), but these are my initial impressions:
Some things seem more intuitive in PyQt, some more so in wxPy. I'd say overall wxPy seems slightly nicer, but the difference isn't that great. Both are *far* ahead of Tkinter in this aspect. (I wouldn't want to write a non-trivial program with Tkinter, but I'd be fine with writing a large PyQt program.)
With wxPy, I can avoid C++ entirely (especially with the nice new docs on wxpython.org). With PyQt, you can't avoid it: to connect a signal ("bind an event", in wxPy terminology), you specify the C++ method signature. For example: self.connect(self.tree, SIGNAL('rightButtonPressed(QListViewItem *, const QPoint &, int)'), self.show_popup). This feels like a kluge to me, and I had to keep hitting my brain-clutch when shifting to C++ and back.
With wxPy, you generally "import wx", and then use classes like wx.App; with PyQt, you generally "from qt import *", and then use classes like QApplication. I guess this is a really minor point, but wxPy seems more Pythonic to me: it feels like wxPy *uses* Python namespaces, while Qt lets the C++ naming overflow into the actual class names.
wxPy's documentation seems to be better. The wxWidgets API says what's different in Python (or Perl). In Qt, Python feels very much like a second-class citizen. The main Qt documentation is very C++-specific, and there's another webpage that says what's different (or missing) in Python. There didn't seem to be any "one-stop-shopping" for the PyQt API.
All this applies to PyQt 3.x I don't want to be anti-Qt, so if anything here is incorrect or misleading, please add a note!
Also, since I've been using wxPy for a while, I surely did things using a wxPy approach, and missed out completely on some things that PyQt does better. PyQt programmers, please enlighten me.
I (TRauMa) used pyQt and it's some time since I ventured into wx, but now, with missing Qt4 support (see above) I think I'll give wx another shot. So here's my 0.02:
- The C++ kludge above: It most of the time looks more like app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")), you only have to type the method signature if you actually want to use the arguments, and if the SIGNAL is written in C++. In my apps, that happened roughly 3 times/app. YMMV.
With PyQt you use the Qt Designer to create the ui, then the pyuic compiler to create python classes. But, Designer allows you to write additional slots and connections, saved in an .ui.h-file, and with pyqt you naturally have to write them in python, with an C++-Editor. Ugly. PyQt4 will remedy this situation, as Trolltech realized the folly of their ways and made Designer 4 less IDE-like.
- Beauty Contest: At least for me (I use gnome and a beautiful gtk2 theme), wxApps still look alien somehow. I'll have to test it with the latest version and my own programs, but the GTK+2 backend for wx seems to have its sharp edges. pyQt apps just look like any Qt app, that is native under windows and dull under gnome (per default, can be changed) and KDE-like on KDE. Qt4 has an Carbon backend for Mac, but I dunno if it is satisfying for you Macheads ;-).
Qt vs wxWidgets: Qt definately is more stable (as in stable API and in crashes less), and it has a competent company behind it, which gives it quite a lot development momentum. With wxWidgets 2.4 -> 2.6 and the incompatible GTK1 and GTK2 backends (with incompatible libs with unicode and without), I had distribution woes on and on. "No, you can't use the wxWidgets your distribution has. No, sorry. Yes, it's quite a big download...". You get the idea. I certainly hope that's better now.
With PyQt, python is a second class citizien, as you can deduce from the fact that we have Qt4.1, but no PyQt4. Personally I had no trouble applying the Qt docs to python, using the few conversion rules PyQt gives you, but I have a C++ background, so YMMV.
Prehaps I'll post here when I made some progress with wx, and tell you what you it did to me ;-).
NB: I'm no expert in both toolkits, my GUI's tend to be easy containers for OpenGL apps. I'm writing an application with multiple interfaces (Qt so far, wx comming now), and that keeps me from using to much from the special dishes both toolkits serve. Caveat emptor.
I have been experimenting with PyQt4 and wxPython for a few (albeit relatively small) projects recently and I found this page with it's comparison but noticed that it was a long way out of date and hence cast PyQt in an inaccurately unfavourable light. I therefore thought it was worth updating it with a few comments. Note that I use both wxPython and PyQt4, but I probably prefer PyQt4 for my purposes, so bear in mind that this is a bit biased the other way.
wxPython is still far more flexible in terms of licensing than PyQt will ever be. However, Nokia are currently working on the PySide project, which aims to produce something roughly equivalent to PyQt4 but with an LGPL licence.
Qt (C++) documentation is far superior to the WxWidgets (C++) documentation: there are many more examples, screenshots and background 'topic' discussions in the Qt documentation.
That said, the wxpython documentation does bring the (limited) wxwidgets documentation and python differences together nicely: last time I checked, the PyQt documentation wasn't as nice. As a programmer with a C/C++ background, I tend to just use the main Qt documentation when programming PyQt4 and this is absolutely fine for me. I believe that there is now some auto-generated PyQt4 documentation on the Riverbank side, so this may go some way to address the difference; I've not had to use it yet.
In wx, you generally "import wx" and use "wx.Button" etc. In PyQt4, you generally "from PyQt4 import QtCore, QtGui" and use "QtGui.QPushButton". Much nicer than the previous versions when they encouraged "from qt import *"
In PyQt4, you have Qt Creator, which generates "ui" files that get compiled into Python code. All user interface objects become available as "self.ui.*", e.g. self.ui.myPushButton. wxPython has things like wxFormBuilder which can generate xrc files. It's not too hard to emulate the self.ui.* operation. Interactive GUI design is definitely improving in wxpython, but it isn't a patch on Qt Creator.
In recent versions of PyQt4, you can pretty much throw away C++, much like wxPython, so it's nice that they've finally caught up. In fact, the PyQt4 signal/slot connections are now very Pythonic and I tend to find it easier to work out the appropriate 'event' ('clicked' for a button press) in Qt than in wx (EVT_BUTTON for a button press). All the relevant signals are listed on the Qt documentation page for the class; finding the right wx.EVT* in the wx documentation can be a challenge all of itself.
Manually emitting a signal/event seems much easier in PyQt4 than in wxpython (there may be easier ways to do this in wxpython, I've always struggled with it and found this on stackoverflow):
Inherent in the PyQt4 design is a simple event model with which there's only one name you need to remember for a signal/event. Creating a new signal/event in wxpython involves something like this:
1 # wxpython
2 import wx
3 import wx.lib.newevent
4
5 MyNewEvent, EVT_MYNEWEVENT = wx.lib.newevent.NewEvent()
6
7 class MyClass():
8 def __init__(self, parent):
9 self.parent = parent
10
11 def DoStuff(self):
12 event = MyNewEvent(result={'Data': [0,1,2]})
13 wx.PostEvent(self.parent.GetEventHandler(), event)
14
15 class ParentClass(wx.Window):
16 def __init__(self):
17 self.instance = MyClass(self)
18 self.Bind(EVT_MYNEWEVENT, self.OnEvent, self.instance)
19 self.instance.DoStuff()
20
21 def OnEvent(self, event):
22 DoSomething(event.result)
you have to use MyNewEvent in some places and EVT_MYNEWEVENT in others. In Qt, you create a signal like this:
1 from PyQt4 import QtCore, QtGui
2
3 class MyClass():
4 MyNewEvent = QtCore.pyqtSignal(dict)
5
6 def __init__(self, parent):
7 pass
8
9 def DoStuff():
10 self.MyNewEvent.emit({'Data': [0,1,2]})
11
12 class ParentClass(QtGui.QMainWindow):
13 def __init__(self):
14 self.instance = MyClass(self)
15 self.instance.MyNewEvent.connect(self.OnEvent)
16
17 def OnEvent(self, data):
18 DoSomething(data)
I'd be very interested in an updated view from someone more experienced with wxpython as I realised this is biased towards PyQt4. At the moment, I use wxpython when I need to do tools that can't be open source and PyQt4 for everything else. When PySide reaches revision 1, I expect to use PySide all the time.