|
Level: elementary Boudewijn rempt (boud@valdyas.org), developer, tryllian David Mertz, mertz@gnosis.cx promoter, Gnosis software, Inc. March 09, 2004
Qt toolkit is a widely used cross-platform GUI toolkit for Windows, Linux, Mac OSX, and many handheld platforms. Qt has a well-structured (but flexible) Object-oriented structure, clear documentation, and intuitive APIs. In this article, David Mertz and Boudewijn rempt discuss the QT library and focus on pyqt binding that allows Python programmers to access the QT function.
In general, selecting a GUI toolbox for an application is tricky. Programmers using Python (the same for many languages) have a wide variety of GUI toolboxes, each of which has its own advantages and disadvantages. Some are faster and smaller than other toolboxes, some are easy to install, and some are more suitable for cross-platform use (for this purpose, we should also note that there are some specific features that support your needs ). Of course, various databases have various licenses. For Python programmers, the default GUI option is Tk (bound through tkinter)-The reason is obvious. Tkinter and idle IDE are compiled by the python founder and appear as the default choice for most Python distributions. The standard Python document discusses tkinter, but does not involve any other GUI bindings. This is intentional! At least so, if TK and tkinter are not so bad, programmers have no reason to look for alternatives. To induce a Python programmer to give up the default option, the toolbox must provide additional information. Pyqt is such a toolbox. Pyqt has many advantages over tkinter (it also has several disadvantages ). QT and pyqt are fast. The design of QT and pyqt is completely object-oriented. QT provides a well-designed set of window components, which is much larger than that provided by TK. In terms of its disadvantages, QT licenses are limited by more than many toolboxes (at least on non-Linux platforms); correct installation of QT and pyqt is often complicated; in addition, QT is a very large library. Users of the pyqt application will need to try to install QT and pyqt, which makes distribution very difficult. (Read the QT binding for other languages later in this article .) Pyqt strictly follows the licensing of QT. In particular, it can be used for GPL on UNIX/X11 platforms and for Qt palmtop environment on zaurus, there are also free (free-as-in-free-beer) Windows software packages for older QT versions. Pyqt commercial licenses can be used for Windows. For this article, pyqt is better than many other toolboxes and deserves our special attention. QT is calledSignal/slots (signals/slots)Transfer events and messages between window components (and other objects. This mechanism is totally different from the callback mechanism used by most toolboxes, including tkinter. It is much easier to control communication between objects using signal/slot in a flexible and maintenance manner than to use a fragile callback style. The larger the application, the more important this advantage of QT is. Boudewijn rempt, one of the authors of this article, has published a book on application development using pyqt.Gui programming with Python: QT Edition(See references) shows how to design and develop a complete GUI application, including the entire process from initial conception to distribution. Sample Application To display the contrast between the signal/slot and the callback, we provide an application that is written and played, which uses tkinter and pyqt. Although the pyqt version is not simple for this basic program, it has demonstrated the better controllability and maintainability of the pyqt application. The application includes four window components:
- "Quit" button (used to communicate with the entire application)
- "Log timestamp" button (used for messages between window components)
- Text area to display the time stamp list of the rolling logs
- Message window component that displays the time stamps of logged logs
In tkinter, we can implement the application as follows:Listing 1. Logger. py tkinter Application
#!/usr/bin/python import sys, time from Tkinter import * class Logger(Frame): def __init__(self): Frame.__init__(self) self.pack(expand=YES, fill=BOTH) self.master.title("Timestamp logging application") self.tslist = [] self.tsdisp = Text(height=6, width=25) self.count = StringVar() self.cntdisp = Message(font=('Sans',24), textvariable=self.count) self.log = Button(text="Log Timestamp", command=self.log_timestamp) self.quit = Button(text="Quit", command=sys.exit) self.tsdisp.pack(side=LEFT) self.cntdisp.pack() self.log.pack(side=TOP, expand=YES, fill=BOTH) self.quit.pack(side=BOTTOM, fill=BOTH) def log_timestamp(self): stamp = time.ctime() self.tsdisp.insert(END, stamp+"\n") self.tsdisp.see(END) self.tslist.append(stamp) self.count.set("% 3d" % len(self.tslist)) if __name__=='__main__': Logger().mainloop() |
This TK version useslog_timestamp() Method as buttoncommand= Parameters. In this method, all the window components to be affected must be operated independently. If we want to change the effect of the button press (for example, to record the time stamp), this style is very fragile. You can achieve this through inheritance: Listing 2. stdoutlogger. py tkinter Enhancement
class StdOutLogger(Logger): def log_timestamp(self): Logger.log_timestamp(self) print self.tslist[-1] |
However, the author of this subclass needs to understand it quite accurately.Logger.log_timestamp() What has been done; and unless it is completely overwritten in the subclass.log_timestamp() Method and does not call the parent method, otherwise there is no wayRemoveMessage. A very basic pyqt application always has some sample code, which is the same everywhere, as does tkinter code. However, when we further study the Code required to set up the application and display the code of the window component, the difference is displayed. Listing 3. logger-qt.py pyqt Application
#!/usr/bin/env python import sys, time from qt import * # Generally advertised as safe class Logger(QWidget): def __init__(self, *args): QWidget.__init__(self, *args) self.setCaption("Timestamp logging application") self.layout = QGridLayout(self, 3, 2, 5, 10) self.tsdisp = QTextEdit(self) self.tsdisp.setMinimumSize(250, 300) self.tsdisp.setTextFormat(Qt.PlainText) self.tscount = QLabel("", self) self.tscount.setFont(QFont("Sans", 24)) self.log = QPushButton("&Log Timestamp", self) self.quit = QPushButton("&Quit", self) self.layout.addMultiCellWidget(self.tsdisp, 0, 2, 0, 0) self.layout.addWidget(self.tscount, 0, 1) self.layout.addWidget(self.log, 1, 1) self.layout.addWidget(self.quit, 2, 1) self.connect(self.log, SIGNAL("clicked()"), self.log_timestamp) self.connect(self.quit, SIGNAL("clicked()"), self.close) def log_timestamp(self): stamp = time.ctime() self.tsdisp.append(stamp) self.tscount.setText(str(self.tsdisp.lines())) if __name__ == "__main__": app = QApplication(sys.argv) app.connect(app, SIGNAL('lastWindowClosed()'), app, SLOT('quit()')) logger = Logger() logger.show() app.setMainWidget(logger) app.exec_loop() |
By creating a layout manager,Logger Class started to work. The layout manager is a complex topic in any GUI system, but the implementation of QT makes it easy. In most cases, you will use QT designer to create a general GUI Design, which can then be used to generate Python or C ++ code. Then you can generate a subclass of the generated code to add functions. However, in this example, we choose to manually create the layout manager. The window component is placed in each unit of the grid, or can be placed across multiple units. Pyqt does not allow tkinter to name parameters. This is a very important difference. It often makes people who work in two environments at a loss. All QT window components can work with the qstring object naturally, but cannot work with the python string or Unicode object. Fortunately, the conversion is automatic. If you use a string or Unicode parameter in the QT method, it is automatically converted to a qstring. Reverse conversion is not allowed: If you call a method to return qstring, you obtain qstring. The most interesting part of the application isclicked Position of the signal connection function. A button is connectedlog_timestamp Method; the other is connected to the qwidget classclose Method. Figure 1. logger-QT screen snapshot
Now we want to add the log records to the standard output of this application. This is very easy. We can makeLogger Class to generate a subclass, or create a simple independent function for Demonstration: Listing 4. logger-qt.py pyqt Enhancement
def logwrite(): print(time.ctime()) if __name__ == "__main__": app = QApplication(sys.argv) app.connect(app, SIGNAL('lastWindowClosed()'), app, SLOT('quit()')) logger = Logger() QObject.connect(logger.log, SIGNAL("clicked()"), logwrite) logger.show() app.setMainWidget(logger) app.exec_loop() |
From the code above, we can see thatlog Qpushbutton'sclicked() Signal connection to the new function. Note: signals can also transmit any data to the slots they connect to, even though this example is not shown here. If you do not want to call the original method, you candisconnect For examplelogger.show() Add the following lines before the row: Listing 5. logger-qt.py pyqt Enhancement
QObject.disconnect(logger.log, SIGNAL("clicked()"), logger.log_timestamp) |
The GUI will not be updated now.
Other GUI Bindings for python Pyqt may not be very useful in a given instance, it may be a license status issue, or it may be a platform availability issue (or, it may be due to the difficulty of redistribution, for example, a large size ). For this reason (also for comparison), we would like to point out some other popular GUI toolboxes for python.
- Anygui
Anygui is not actually a GUI toolbox, but an abstract package that acts on a large number of toolboxes (even amazing toolboxes like curses and Java/Jython swing. In terms of programming style, the use of anygui is similar to the use of tkinter, but you need to select this underlying toolbox, either automatically or configuration call. Anygui is useful because it allows applications to run on a very different platform without modification (but therefore it supports the "lowest level public feature" of the supported Toolbox ").
- Pygtk
Pygtk is bound to the GTK toolbox used in GPL. It is the basis of the popular GNOME environment. GTK is basically the X Window toolbox, but it also has beta support for Win32 and Alpha support for BEOs. In the general example, pygtk uses callback for the window component. Binding exists in GTK andLargeBetween programming languages, not just QT, or even TK.
- Fxpy
Python-bound fxpy encapsulates the fox toolbox. The fox toolkit has been transplanted to most UNIX-like platforms and Win32. Similar to most toolboxes, both Fox and fxpy Use callback examples. Fox is licensed by lgpl.
- Wxpython
This binding wraps the wxwindows toolbox. Similar to fox or GTK, wxwindows is transplanted to Win32 and Unix-like platforms (but not to MacOS, OS/2, BEOs, or other "secondary" platforms-although its support for MacOSX is alpha-level ). In terms of examples, wxpython is close to the callback style. Wxpython pays more attention to the inherited structure than most other toolboxes, and uses "events" instead of callback. But in essence, the event is still connected to a single method, and then it may need to act on various window components.
- Win32ui
Win32ui is a win32all software package that encapsulates the MFC class. Obviously, this toolbox is a Win32 library. MFC is not just a GUI toolbox, but also a mixture of various examples. For users who want to create a Windows application, win32ui will bring you closer to the essence than other toolboxes ".
Use QT from other languages Like python, it is possible to use the QT toolkit from a large number of other programming languages. If you have the freedom to choose, we will first choose python, rather than other languages. External constraints such as company policies and connections to other code libraries can determine the choice of programming languages. The original QT language is C ++, but it is also used for binding C, Java, Perl, and Ruby. In comparison with the python example, let's discuss the applications that use Ruby and Java to write and play. Ruby/Qt The usage is very similar to pyqt. These two languages have similar dynamics and conciseness, so apart from spelling differences, their code is similar:
Listing 6. helloworld. RB qt2 Application
#!/usr/local/bin/ruby require 'qt2' include Qt2 a = QApplication.new([$0] + ARGV) hello = QPushButton.new('Hello world!') hello.resize(100, 30) a.connect( hello, QSIGNAL('clicked()'), a, QSLOT('quit()')) a.setMainWidget(hello) hello.show a.exec |
Java is always a little longer than the scripting language, but the basic parts are the same. The smallest qtjava application with the same functions is similar: Listing 7. helloworld. Java qt2 Application
import org.kde.qt.*; public class HelloWorld { public static void main(String[] args) { QApplication myapp = new QApplication(args); QPushButton hello = new QPushButton("Hello World", null); hello.resize(100,30); myapp.connect(hello, SIGNAL("clicked"), this, SLOT("quit()")); myapp.setMainWidget(hello); hello.show(); myapp.exec(); return; } static { System.loadLibrary("qtjava"); try { Class c = Class.forName("org.kde.qt.qtjava"); } catch (Exception e) { System.out.println("Can't load qtjava class"); } } } |
Pyqt is an attractive and fast interface that integrates the QT toolkit with the python programming language. In addition to the wide variety of window components provided by the toolbox, the signal/slot programming style used by QT is superior to the callback style used by most other GUI toolboxes in terms of production capability and maintainability. References
- For more information, see the original article on the developerworks global site.
- Access the pyqt page from riverbank.
- Gui programming with Python(Opendocs; November 2001) the page contains information about books written by Boudewijn rempt and more about pyqt.
- According to python.org, tkinter is the actual standard GUI of Python. Written by DavidDeveloperworksIn the article "Cute Python: TK programming in Python", you can also learn more about it.
- Generally, you do not need to download idle (because it is currently bundled with each Python distribution version) unless you want to use an experiment version or other non-standard version. If so, you can find this version on the idle page of python.org.
- At SourceForge, you will findDeveloperworksThe article "Cute Python: [anygui] project preview" outlines it.
- You will find Cameron Laird's personal notes on Python guis interesting.
- Python Bindings for the GTK widget set provides an object-oriented interface for the popular GKT widget set.
- Fxpy is an extension module that provides interfaces to the fox GUI library.
- If you must use the wxwindows C ++ class library, you will find wxpython very helpful.
- The win32ui module encapsulates Microsoft Foundation Class. It is distributed, and it and pythonwin both belong to the win32all installation package.
- InDeveloperworksFor more information about Linux developers, see Linux.
Author Profile
|
|
|
Boudewijn rempt has compiled a book on pyqt, which has been published by opendocs and is namedGui programming with Python: QT Edition. In printed documents, the book's practicality has elevated pyqt to the same position as tkinter. You can contact Boudewijn through a boud@valdyas.org. |
|
|
|
David Mertz hopes to see the flowers bloom. You can contact David via mertz@gnosis.cx; http://gnosis.cx/publish/introduce his life. You are welcome to give your comments and suggestions on the past, this or future column. Please visit his upcoming booksText processing in Python. |
TkinterHello world! -- TK TkinterThe module ("TK interface") is the interface of Python's standard tk gui toolkit. TK and tkinter can be used on most UNIX platforms. They can also be used in windows and Macintosh systems ., later versions of tk8.0 can implement the local window style and run well on most platforms. Tkinter contains several modules. the TK interface is encapsulated in a binary module named _ tkinter (an earlier version of tkinter ). this module contains the low-level interface of TK, so it will not be directly applied by programmers. it is usually represented as a shared library (or DLL file), but in some versions it is combined with the python interpreter. In the additional modules of the TK interface, tkinter contains some Python modules and stores them in a sub-directory of the standard library, called tkinter. There are two important modules: tkinter itself and tkconstants: the former is automatically imported to the latter, so if you use tkinter, You can import only one module. Import tkinter Or more commonly used: From tkinter import * The first tkinter Program # File: hello1.py From tkinter import * Root = TK () W = label (root, text = "Hello, world! ") W. Pack () Root. mainloop () Run the command in the following way: The window below $ Python hello1.py will be displayed: |