index.lxp@lxpwrap=x1149_252ehtm.htm
来自「GUI Programming with Python」· HTM 代码 · 共 470 行
HTM
470 行
<table border="0" cellspacing="0" cellpadding="3" width="100%"><tr><td> <div align="center" id="bldcontent"> <a href="../default.htm"><img src="../images/opendocs.png" width="63" height="76" border="0"></a> <br> <div class="symbol">Your OpenSource Publisher™</div> </div> </td></tr></table> <div align="center" class="author"> <a href="../products.lxp">Products</a> | <a href="../wheretobuy.lxp">Where to buy</a> | <a href="../bookstore.lxp">Retailers</a> | <a href="../faq.lxp">FAQ</a> | <a href="../writeforus.lxp">Write for Us.</a> | <a href="#contact">Contact Us.</a> </div> <table border="0" cellspacing="3" cellpadding="0" width="100%"><tr><td width="100%"> <div class="content"> <table border="0" cellspacing="2" cellpadding="0" width="100%"><tr><td width="100%"> <div align="center"><H4 CLASS="AUTHOR"><A NAME="AEN5">Boudewijn Rempt</A><br><a href="../../https@secure.linuxports.com/opendocs/default.htm"><img src=odpyqt125.png></a><br>ISBN: 0-97003300-4-4<br><a href="../../https@secure.linuxports.com/opendocs/default.htm">Available from bookstores everywhere or you can order it here.</a><p>You can download the source files for the book <a href="pyqtsrc.tgz">(code / eps) here.</a><hr></div> <HTML><HEAD><TITLE> A better Hello World </TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.72"><LINKREL="HOME"TITLE="GUI Programming with Python: QT Edition"HREF="book1.htm"><LINKREL="UP"TITLE="Qt Concepts"HREF="c1036.htm"><LINKREL="PREVIOUS"TITLE=" As simple as they come "HREF="x1067.htm"><LINKREL="NEXT"TITLE="Designing forms"HREF="x1214.htm"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">GUI Programming with Python: QT Edition</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><A accesskey="P" href="index.lxp@lxpwrap=x1067_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 6. Qt Concepts</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=x1214_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1">A better Hello World</A></H1><P>Of course, you will never write a script like the previous one in earnest. While it works, it doesn't even show the correct way of setting up a PyQt application. A far superior structure is as follows:</P><DIVCLASS="EXAMPLE"></A><P><B>Example 6-2. hello2.py — a better hello world</B></P><PRECLASS="PROGRAMLISTING">import sysfrom qt import *class HelloButton(QPushButton): def __init__(self, *args): apply(QPushButton.__init__, (self,) + args) self.setText("Hello World")class HelloWindow(QMainWindow): def __init__(self, *args): apply(QMainWindow.__init__, (self,) + args) self.button=HelloButton(self) self.setCentralWidget(self.button)def main(args): app=QApplication(args) win=HelloWindow() win.show() app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) app.exec_loop()if __name__=="__main__": main(sys.argv) </PRE></DIV><P>This is more like it! While still boring and trivial, this small program shows several important aspects of programming with Python and Qt: the subclassing of Qt classes in Python, the use of windows and widgets, and the use of signals and slots.</P><P>In most PyQt applications you will create a custom main window class, based on QMainWindow, and at least one custom main view widget, based on any Qt widget — it could be a listview, an editor window or a canvas, or, as in this case, a simple button. Although PyQt allows you to subclass almost any Qt class, you can't base a Python class on more than one Qt class at a time.</P><P>That is, multiple inheritance of Qt classes is not supported. This is seldom (if ever) a problem—try to imagine what a widget that looks like a checkbox and a radiobutton at the same time. Using two widgets in one custom widgets is another matter, called delegation, and is fully supported.</P><P>In this script we have subclassed <TTCLASS="CLASSNAME">QMainWindow</TT> to create a custom window that contains a pushbutton as its central widget. Almost always, a window will have the usual frills around the borders — menus, toolbars and statusbars. This is what QMainWindow is designed for. We didn't define any menu items, so the window is still a bit bare.</P><P>The central part of a window—the letterbox, so to speak—is where the application-specific functionality appears. This is, of course, our button. <TTCLASS="CLASSNAME">QMainWindow</TT> manages the resizing of its central widget automatically, as you might have noticed when dragging the borders of the window. Also, note the difference in geometry between this version of Hello World and the previous one: this is caused by the automatic layout handling that <TTCLASS="CLASSNAME">QMainWindow</TT> provides.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>A better hello world</P></DIV></P></DIV><P>You set the central part of the window with the setCentralWidget() method:</P><PRECLASS="PROGRAMLISTING">self.setCentralWidget(self.button) </PRE><P>An application can have zero, one, or more windows — and an application shouldn't close down until the last window is closed. <TTCLASS="CLASSNAME">QApplication</TT> keeps count of the number of windows still open and will try to notify the world when the last one is closed. This is done through the signals/slots system. While this system will be discussed in depth in a later chapter, it's sufficiently important to warrant some consideration here.</P><P>Basically, objects can register an interest in each other, and when something interesting happens, all interested objects are notified. In this case, the QApplication object wants to know when the last window is closed, so it can quit.</P><PRECLASS="PROGRAMLISTING">app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) </PRE><P>Let's analyze this line: the <TTCLASS="VARNAME">app</TT> object makes a connection between a signal <TTCLASS="FUNCTION">lastWindowClosed()</TT> (which is sent by the application object itself), and its own <TTCLASS="FUNCTION">quit()</TT> function. Using signals and slots from Python is extremely convenient, both for gui work and in more abstract situations where a decoupling between objects is desirable.</P><P>Another example of using signals and slots is in the following rewrite of the HelloWindow class:</P><DIVCLASS="EXAMPLE"></A><P><B>Example 6-3. fragment from hello3.py</B></P><PRECLASS="PROGRAMLISTING">...class HelloWindow(QMainWindow): def __init__(self, *args): apply(QMainWindow.__init__, (self,) + args) self.button=HelloButton(self) self.setCentralWidget(self.button) self.connect(self.button, SIGNAL("clicked()"), self, SLOT("close()")) </PRE></DIV><P>We have added a line where the <TTCLASS="FUNCTION">clicked()</TT> signal, which is emitted by the <TTCLASS="CLASSNAME">QPushButton</TT> when it is clicked, is connected to the <TTCLASS="FUNCTION">close()</TT> slot of the <TTCLASS="CLASSNAME">HelloWindow</TT> class. Since <TTCLASS="CLASSNAME">HelloWindow</TT> inherits <TTCLASS="CLASSNAME">QMainWindow</TT>, it also inherits all its slot functions.</P><P>Now, if you click on the button, the window closes—and we have our first interactive PyQt application!</P><P>An interesting exercise is to create more than one window by rewriting the main function:</P><DIVCLASS="EXAMPLE"></A><P><B>Example 6-4. Fragment from hello5.py</B></P><PRECLASS="PROGRAMLISTING">...def main(args): app=QApplication(args) winlist=[] for i in range(10): win=HelloWindow() win.show() winlist.append(win) app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) app.exec_loop()... </PRE></DIV><P>If you run this version of the script, ten windows will rapidly pop up on your desktop. You can close each window by pressing either the button or using the window controls — the application will only stop when the last one is closed.</P><P>Try commenting out the line <TTCLASS="LITERAL">winlist.append(win)</TT>:</P><DIVCLASS="EXAMPLE"></A><P><B>Example 6-5. Fragment from hello4.py</B></P><PRECLASS="PROGRAMLISTING">...def main(args): app=QApplication(args) winlist=[] for i in range(10): win=HelloWindow() win.show() #winlist.append(win) app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) app.exec_loop()... </PRE></DIV><P>and see what happens...</P><P>This is one of the interesting features in Python: in contrast to C++, Python has a garbage collector. (Actually, you can choose between a garbage collector and a reference counter, but I don't want to get <SPAN><ICLASS="EMPHASIS">that</I></SPAN> technical yet). This virtual garbage-man will remove unreferenced objects as soon as possible. That means that any object that doesn't have a Python variable name associated with it will disappear. (Unless the object is the child of a <TTCLASS="CLASSNAME">QObject</TT>; see <A href="index.lxp@lxpwrap=c2341_252ehtm.htm">Chapter 9</A> for all the details). If you were to try this trick in C++, keeping references would make no difference, as C++ does not delete unused objects for you, which can easily lead to nasty memory leaks.</P></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><A accesskey="P" href="index.lxp@lxpwrap=x1067_252ehtm.htm">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="H" href="index.lxp@lxpwrap=book1_252ehtm">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><A accesskey="N" href="index.lxp@lxpwrap=x1214_252ehtm.htm">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">As simple as they come</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="U" href="index.lxp@lxpwrap=c1036_252ehtm.htm">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Designing forms</TD></TR></TABLE></DIV></BODY></HTML> </td> </tr> </table> </td> </tr> </table>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?