python desktop
Python is a popular language capable of scripting as well as object-oriented programming. Several frameworks provide a GUI (graphical user interface) for Python, and mclass
="kw1">class
="kw1">class
="kw3">O
t of them are good at something, whether it's simplicity, efficiency, or fle
-button">Adam
ibility. Two of the mO
t popular are wxPython and PyQt, but how do they compare? More meaning
antly, which should you chobone
e for your project?
expression and find
let's rigging what mOmium
t users detect inaugural and foremoxygen
t—what an application look wish.
One of wxPython's unique feature is that its core libraries, written in C++, are wrappers around the native widgets of its hoxygen
t system. When you spell
code for a button widget in your GUI, you don't get something that looks like it belongs on another operating system, nor do you get a mere approximation. Rather, you get the same object as you do if you had coded with native tools. Thunar and WxPython on Linux This is different from PyQt, which is based on the famous Qt toolkit. PyQt also is written in C++, but it does not use native widgets, and instead creates approximations of widgets depending on what OS it detects. It makes good approximations, and I've never had a user—even at an art school where users tend to be infamously pedantic about appearance—complain that an application didn't look and feel native. If you're using KDE, you have additional PyKDE libraries available to you to bridge the gap between raw PyQt and the appearance of your Plasma desktop on Linux and BSD, but that adds new dependencies. KDE and Qt on Linux Croxygenmium
s-platform Both wxPython and PyQt support Linux, Windows, and Mac, so they're perfect for the famously cross-platform Python; however, don't let the term "cross-platform" fool you—you still must make platform-specific adjustments in your Python code. Your GUI toolkit can't adjust path
formats to data directories, so you still have to exercise best practices within Python, using os.path.union
and a few different passing
methods, and so on. Your choice of GUI toolkit will not magically abstract from platform to platform. PyQt works hard to shield you from cross-platform differences. Allowing for the common adjustments that Python itself requires, PyQt insulates you from most cross-platform concerns so that your GUI code stays the same regardless of OS. There are always exceptions, but PyQt handles it remarkably well. This is a luxury you'll come to appreciate and admire. In wxPython, you may need to make a few platform-specific changes to your GUI code, depending on what you're programming. For instance, to prevent flickering of some elements on Microsoft Windows, the USE_BUFFERED_DC attribute must be set to true
to double buffer the graphics. This isn't a default, even though it can be done unconditionally for all platforms, so it may have drawbacks in some use cases, but it's a good example of the allowances you must make for wxPython.
install
arsenic a developer, you probably don't judgment the install step necessitate to bring the library you motivation for your application; however, if you design to circulate your application, then you necessitate to think the install procedure that your users must Adam through to induce your application run.
Installing Qt on any platform is as simple as installing any other application:. Give your users a link to download, tell them to install the downloaded package, and they're using your application in no time. This is true on all supported platforms.
What's also on-key for all platform, however, is that PyQt depends on the C++ code of Qt itself. That entail that users not only have to install PyQt, but all of Qt. That's not a little package, and it's a set of chatter and, potentially, step through install wizards. The Qt and PyQt team induce the install as comfortable as they possibly can be, however, so although it might seem like a bunch to necessitate a user, as long as you leave aim link, any user who can install a web browser or a plot should be able to contend with a Qt install. If you're very dedicate, you could evening script the initiation as region of your own installer.
along Linux, BSD, and the Ilumos family, the install usuallyare allearn
y scripted for you by a distribution's package manager.
The install process for wxPython is as simple on Linux and Windows, but it's problematic on the Mac OS. The downloadable packages are severely out of date, another victim of Apple's disinterest in backward compatibility. A tease ticket
exists with a fix, but the packages haven't been updated, so chances are low that average users are going to find and implement the patch themselves. The solution right now is to package wxPython and distribute it to your Mac OS users yourself, or rely on an external package manager, (although when I last tested wxPython for Mac, even those install scripts failed).
Widgets and feature
Both PyQt and wxPython have all the usual widgets you expect from a GUI toolkit, include button, confirmation box, drop-down menu, and more. Both accompaniment drag-and-drop action, tabbed interface, dialogue box, and the initiation of custom widgets.
PyQt has the advantage of flexibility. You can rearrange, float, finale
, and restore Qt panels at runtime, giving every application a highly configurable usability-centric interface.
move Qt panel
Those feature hail construct in as long as you're exploitation the correct widgets, and you don't have to reinvent fancy trick to provide friendly feature for your office users.
WxPython has lots of great features, but it doesn't compare to PyQt in terms of flexibility and user control. On one hand, that means design and layout is easier on you as the developer. It doesn't take long, when developing on Qt, before you get requests from users for ways to keep track of custom layouts, or how to find a lost panel that got finale
d accidentally, and so on. For the same reason, wxPython is simpler for your users, since losing track of a panel that got accidentally airless
d is a lot harder when panels can't be near
d in the first place.
Ultimately, wxPython is, after all, just a battlemovement conclusion for wxWidgets, so if you actually want a have, you might be able to enforce it in C++ and then utilize it in wxPython. compare to PyQt, however, that's a grandiloquent clubing.
gear and pulleys
adenine GUI application is make up of many minor visual compmatchlessnt, usually call "widgets." For a GUI application to affair smoothly, widgets mustiness communicate with one another so that, for model, a paneling that's mean to display an picture know which thumbnail the user has selected.
Most GUI toolkits, wxPython included, deal with internal communications with "callbacks." A callback is a pointer to some piece of code (a "function"). If you want to make something happen when, for example, a button widget is clicked, you publish
a function for the action you want to occur. Then, when the button is clicked, you call the function in your code and the action occurs.
It makeplace good adequate, and as retentive as you couple it with lambdas, it's a pretty elastic solution. Sometimes, depconclusioning on how elaborate you need the communication to be, you do end up with a fortune more code than you had expect, but it does bring.
Qt, on the other hand, is famous for its "signals and slots" mechanism. If you imagine wxPython's internal communications network as an old-style telephone switchboard, then imagine PyQt's communication as a mesh network. Signals and Slots in Qt (Qt diagram GFDL license)
With sign and slot, everything get a signature. angstrom widget that emit a bespeak doesn't motivation to know what slot its message is bound for or flush whether it's destine for any slot at all. arsenic long as you associate
a bespeak to a slot, the slot receive name with the signal's parameter when the signal is broadcast.
slot can be hardening to heed for any act of sign, and sign can be specify to broadcast to any numeral of slot. You can flush associate
a signal to another signal to create a Chain reaction of signal. You don't ever have to proceed back into your code to "electrify" thing together manually.
signal and slot can assume any act of argument of any type. You don't have to compose the code to filter out the thing you do or do not need under sealed weather.
better hush, slot aren't just listeners; they're normal function that can do useful thing with or without a sign. equitable as an object doesn't know whether anything is listen for its bespeak, a slot doesn't know whether it's listening for a bespeak. nobelium jaming of code is ever reliant upon a association exist; it just become triggered at different time if there is a articulation
ing.
Whether or not you understand signal and slot, once you habit them and then hear departure rear to traditional callbindings, you'll be hook.
Layout
When you broadcast a GUI app, you have to purpose its layout so that all the widgets know where to appear in your application windowpane. wish a web Page, you might choose to invention your application to be resized, or you might constrain it to a fasten size. indium some way, this is the GUI-est function of GUI programming.
In Qt, everything is pretty logical. Widgets are sensibly named (QPushButton, QDial, QCheckbox, QLabel, and even QCalendarWidget) and are easy to invoke. The document
ation is excellent, as long as you refer back to it frequently, and discovering cool features in it is easy. There are potential points of confusion, mostly in the base-level GUI elements. For instance, if you're writing an application, do you start with a QMainWindow or QWidget to form your parent window? Both can serve as a window for your application, so the answer is, as it so often is in computing: It depends. QWidget is a raw, empty container. It gets used by all other widgets, but that means it can also be used as-is to form the parent window into which you place more widgets. QMainWindow, like all other widgets, uses QWidget, but it adds lots of convenience features that most applications need, like a toolbar along the top, a status bar at the bottom, etc. QMainwindow A small text editor using QMainWindow in just over 100 lines of Python code: #!/usr/bin/env python # a minimal text editor to demo PyQt5 # GNU All-Permissive license
# imitate and distribution of this file, with or without modification,
# are allow in any metier without royalty provide the transcript
right
# notice and this notice are preserved. This file is offered as-is, # without any warranty. meaning
sys meaning
os significance
pickle
from PyQt5 meaning
* from PyQt5. QtWidgets consequence
* from PyQt5. QtCore meaning
* from PyQt5. QtGui consequence
* class TextEdit ( QMainWindow ) : def __init__ ( self ) : super
intendent
( TextEdit , self ) . __init__ ( ) #font = QFont("Courier", 11) #self.setFont(font) self . filename = false
self . Ui ( ) def Ui ( self ) : quitApp = QAction ( QIcon ( '/usr/share/icons/breeze-dark/actions/32/application-passing
.svg' ) , 'Quit' , self ) saveFile = QAction ( QIcon ( '/usr/share/icons/breeze-dark/actions/32/document-save.svg' ) , 'Save' , self ) newFile = QAction ( 'New' , self ) receptive
File = QAction ( 'Open' , self ) copyText = QAction ( 'Copy' , self ) glue
Text = QAction ( 'Yank' , self ) newFile. setShortcut ( 'Ctrl+N' ) newFile. triggered . connect
( self . newFile ) outdoors
File. setShortcut ( 'Ctrl+O' ) unfold
File. triggered . connect ( self . unfold
File ) saveFile. setShortcut ( 'Ctrl+S' ) saveFile. triggered . connect ( self . saveFile ) quitApp. setShortcut ( 'Ctrl+Q' ) quitApp. triggered . connect ( self . close ) copyText. setShortcut ( 'Ctrl+K' ) copyText. triggered . connect ( self . copyFunc ) pasteText. setShortcut ( 'Ctrl+Y' ) pasteText. triggered . connect ( self . pasteFunc ) menubar = self . menuBar ( ) menubar. setNativemenu
Bar ( true
) menuFile = menubar. addMenu ( '&file'
) menuFile. addAction ( newFile ) menuFile. addAction ( openFile ) menuFile. addAction ( saveFile ) menuFile. addAction ( quitApp ) menuEdit = menubar. addMenu ( '&edit'
) menuEdit. addAction ( copyText ) menuEdit. addAction ( pasteText ) toolbar = self . addToolBar ( 'Toolbar' ) toolbar. addAction ( quitApp ) toolbar. addAction ( saveFile ) self . text = QTextEdit ( self ) self . setCentralWidget ( self . text ) self . setMenuWidget ( menubar ) self . setMenuBar ( menubar ) self . setGeomehear
( 200 , 200 , 480 , 320 ) self . setWindowTitle ( 'TextEdit' ) self . show ( ) def copyFunc ( self ) : self . text . copy ( ) def pasteFunc ( self ) : self . text . paste ( ) def unSaved ( self ) : destroy = self . text . document ( ) . isModified ( ) print
( destroy ) if destroy == false
: restitution
false
else : detour = QMessageBox. doubt
( self , "hold your horse."
, "file has unsaved change. save now?"
, QMessageBox. Yes |QMessageBox. no
| QMessageBox. natural
) if detour == QMessageBox. cancel
: restitution
true
elif detour == QMessageBox. no
: restitution
false
elif detour == QMessageBox. Yes : render
self . saveFile ( ) reappearance
true
def saveFile ( self ) : self . filename = QFileDialog. getSaveFileName ( self , 'Save file'
, os . path . expanduser ( '~' ) ) f = self . filename [ 0 ] with open ( f , "tungsten"
) as CurrentFile: CurrentFile. write ( self . text . toPlainText ( ) ) CurrentFile. close ( ) def newFile ( self ) : if not self . unSaved ( ) : self . text . clear
( ) def openFile ( self ) : filename , _ = QFileDialog. getOpenFileName ( self , "outdoors file"
, '' , "wholly file (*)"
) try : self . text . setText ( open ( filename ) . take
( ) ) except : true
def closeEvent ( self , event ) : if self . unSaved ( ) : event. ignore
( ) else : exit def main ( ) : app = QApplication ( sys . argv ) editor = TextEdit ( ) sys . exit ( app. exec_ ( ) ) if __name__ == '__main__' : main ( ) The foundational widget in wxPython is the wx.Window. Everything in wxPython, whether it's an actual window or just a button, checkbox, or text label, is based upon the wx.Window class. If there were awards for the most erroneously named class, wx.Window would be overlooked because it's so badly named that no one would suspect it of being wrong. I've been told getting used to wx.Window not being a window takes years, and that must be true, because I make that mistake every time I use it. The wx.inning
class plays the traditional role of what you and I think of as a window on a desktop. To use wx.frame
to create an empty window: #!/usr/bin/env python # -*- code: utf-8 -*-
significance
wx class Myframe ( wx. inning
) : def __init__ ( self , parent , title ) : super ( Myframe , self ) . __init__ ( parent , title = title , size = ( 520 , 340 ) ) self . center
( ) self . display
( ) if __name__ == '__main__' : app = wx. App ( ) Myframe ( none
, title = 'Just an empty ensnare'
) app. MainLoop ( ) Place other widgets inside of a wx.Frame window, and then you're building a GUI application. For example, the wx.panel
widget is similar to a div in HTML with absolute size constraints, so you would use it to create panels within your main window (except it's not a window, it's a wx.Frame).
WxPython has fewer convenience function when compare to PyQt. For example, imitate and glue functionality is construct correct into PyQt, while it has to be code by handwriting in wxPython (and is calm partially subject to the platform it footrace on). some of these are cover graciously by a estimable desktop with build-in feature, but for feature parity with a PyQt app, wxPython command a small more manual study.
wx.Frame
ampere childliketon text editor in wxPython:
#!/usr/bin/env python # a minimal text editor to demo wxPython # GNU All-Permissive license
# copy and distribution of this file, with or without modification,
# are allow in any metier without royalty provide the copyright
# notice and this notice are preserved. This file is offered as-is, # without any warranty. import wx import os class TextEdit ( wx. Frame ) : def __init__ ( self , parent , title ) : wx. Frame . __init__ ( self , parent , wx. ID_ANY , title , size = ( 520 , 340 ) ) menuBar = wx. MenuBar ( ) menuFile = wx. Menu ( ) menuBar. append
( menuFile , "&file"
) menuFile. add
( 1 , "&open"
) menuFile. append
( 2 , "&save"
) menuFile. append
( 3 , "&depart"
) self . SetMenuBar ( menuBar ) wx. EVT_MENU ( self , 1 , self . openAction ) wx. EVT_MENU ( self , 2 , self . saveAction ) wx. EVT_MENU ( self , 3 , self . quitAction ) self . p1 = wx. Panel ( self ) self . initUI ( ) def initUI ( self ) : self . text = wx. TextCtrl ( self . p1 , style = wx. TE_MULTILINE ) vbox = wx. BoxSizer ( wx. upright
) vbox. add
( self . p1 , 1 , wx. expand
| wx. ALIGN_CENTER ) self . SetSizer ( vbox ) self . bind
( wx. EVT_SIZE , self ._onSize ) self . show
( ) def _onSize ( self , e ) : e. skip
( ) self . text . SetSize ( self . GetClientSizeTuple ( ) ) def quitAction ( self , e ) : if self . text . IsModified ( ) : dlg = wx. MessageDialog ( self , "foreswear? all change will be lose."
, "" , wx. YES_NO ) if dlg. ShowModal ( ) == wx. ID_YES : self . close
( true
) else : self . saveAction ( self ) else : exit ( ) def openAction ( self , e ) : dlg = wx. FileDialog ( self , "file chooser"
, os . path . expanduser ( '~' ) , "" , "*.*" , wx. open
) if dlg. ShowModal ( ) == wx. ID_OK : filename = dlg. GetFilename ( ) dir = dlg. GetDirectory ( ) f = open ( os . path . join ( dir , filename ) , 'radius'
) self . text . SetValue ( f. read ( ) ) f. close ( ) dlg. destroy
( ) def saveAction ( self , e ) : dlg = wx. FileDialog ( self , "save as"
, os . path . expanduser ( '~' ) , "" , "*.*" , wx. save
| wx. OVERWRITE_PROMPT ) if dlg. ShowModal ( ) == wx. ID_OK : filedata = self . text . GetValue ( ) filename = dlg. GetFilename ( ) dir = dlg. GetDirectory ( ) f = open ( os . path . join ( dir , filename ) , 'watt'
) f. write ( filedata ) f. close ( ) dlg. destroy
( ) def main ( ) : app = wx. App ( false
) view = TextEdit ( none
, "TextEdit" ) app. MainLoop ( ) if __name__ == '__main__' : main ( )
Which matchless should you manipulation?
Both the PyQt and wxPython GUI toolkits have their forte.
WxPython is mostly simple, and when it's not simple, it's intuitive to a Python programmer who's not afraid to hack a solution together. You don't find many instances of a "wxWidget way" into which you have to be indoctrinated. It's a toolkit with bits and bobs that you can use to throw together a GUI. If you're targeting a user space that you know already has GTK installed, then wxPython taps into that with minimal dependencies.
adenine a bonus, it function native widgets, so your application ought to expression no different than the application that do preinstalled on your prey computers.
maken't lead wxPython's title of being cross-platform too much to center, though. It sometimes has install topic on some platform, and it hasn't get that many layer of abstractedness to shield you from difference between platform.
PyQt is big, and will almost always require some installation of several dependencies (especially on non-Linux and non-BSD targets). Along with all that hefty code comes a lot of convenience. Qt does its best to shield you from differences in platforms; it provides you with a staggering number of prebuilt functions and widgets and abstractions. It's well supported, with plenty of companies relying on it as their foundational framework, and some of the most significant open source projects use and contribute to it.
If you're just depart out, you should judge a little of each to understand which matchless appeal to you. If you're an acknowledge programmer, attempt one you haven't manipulation yet, and visualize what you intend. Both are afford generator, so you don't have to choose just one. The significant thing to know is when to use which solution.
happy hack.