📄 index.lxp@lxpwrap=x2420_252ehtm.htm
字号:
<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>References and ownership</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="Python Objects and Qt Objects"HREF="c2341.htm"><LINKREL="PREVIOUS"TITLE="Qt objects, Python objects and shadow objects"HREF="x2393.htm"><LINKREL="NEXT"TITLE="Other C++ objects"HREF="x2540.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=x2393_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 9. Python Objects and Qt Objects</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=x2540_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1">References and ownership</A></H1><P>Let's investigate the actual creation and deletion of object - both Python and Qt have a role to play here - a role they mostly perform without surprising the programmer. Still, there are circumstances you should be aware of.</P><DIVCLASS="EXAMPLE"></A><P><B>Example 9-3. qtrefs1.py — about Qt reference counting</B></P><PRECLASS="PROGRAMLISTING">## qtrefs1.py#import sysfrom qt import *class MainWindow(QMainWindow): def __init__(self, *args): apply(QMainWindow.__init__, (self, ) + args) topbutton=QPushButton("A swiftly disappearing button", None) topbutton.show()def main(args): app=QApplication(args) win=MainWindow() win.show() app.connect(app, SIGNAL("lastWindowClosed()") , app , SLOT("quit()") ) app.exec_loop()if __name__=="__main__": main(sys.argv) </PRE></DIV><P>Here, we create a window, and in the constructor (the <TTCLASS="FUNCTION">__init__</TT> method), we create a QPushButton. That button really should appear as a second toplevel window - but it doesn't. The reason is that the only reference to the object is the variable <TTCLASS="VARNAME">topbutton</TT>, and that variable goes out of scope once the constructor method finishes. The reference ceases to exist, and so the object is deleted.</P><P>If we want to keep the button alive, we should keep the reference alive. The easiest way to do that is to associate the button more closely with the containing window object. It is customary to refer to the containing object with the variable <TTCLASS="VARNAME">self</TT>. Python passes a reference to an object as the first argument to any instance method. This reference is usually named self.</P><P>So, if we adapt the preceding example as follows, we keep the object:</P><DIVCLASS="EXAMPLE"></A><P><B>Example 9-4. qtrefs2.py - keeping a Qt widget alive</B></P><PRECLASS="PROGRAMLISTING">## qtrefs2.py#import sysfrom qt import *class MainWindow(QMainWindow): def __init__(self, *args): apply(QMainWindow.__init__, (self, ) + args) self.topbutton=QPushButton("A nice and steady button", None) self.topbutton.show()def main(args): app=QApplication(args) win=MainWindow() win.show() app.connect(app, SIGNAL("lastWindowClosed()") , app , SLOT("quit()") ) app.exec_loop()if __name__=="__main__": main(sys.argv) </PRE></DIV><P>Does this mean that you always need to keep a reference to all Qt objects yourself? This would make creating complex applications quite a drag! Fortunately, sip is more clever than it seems. <TTCLASS="CLASSNAME">QObject</TT> derived objects stand in a owner-ownee (or parent-child) relation to each other. Sip knows this, and creates references to child objects on the fly, and decreases those references if the parents are deleted. (The Qt library does something similar if you program in C++. This gives a kind of Java-like flavor to C++ which is not appreciated by everyone).</P><P>To keep a widget's child alive, enter the parent object in the <TTCLASS="VARNAME">parent</TT> argument of the child constructor, in this case, this is the second argument to the <TTCLASS="CLASSNAME">QPushButton</TT> constructor:</P><DIVCLASS="EXAMPLE"></A><P><B>Example 9-5. qtrefs3.py - Qt parents and children</B></P><PRECLASS="PROGRAMLISTING">## qtrefs3.py#import sysfrom qt import *class MainWindow(QMainWindow): def __init__(self, *args): apply(QMainWindow.__init__, (self, ) + args) parentedButton=QPushButton("A nice and steady button " + "that knows its place", self) parentedButton.resize(parentedButton.sizeHint())def main(args): app=QApplication(args) win=MainWindow() win.show() app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) app.exec_loop()if __name__=="__main__": main(sys.argv) </PRE></DIV><P>Note however these two important side-effects: The first is that this button, now that it is owned by the main window, appears <SPAN><ICLASS="EMPHASIS">inside</I></SPAN> the main window. The second is that you no longer need to explicitly call the function <TTCLASS="FUNCTION">show()</TT> on the button.</P><P>As another side-effect of explicitly parenting objects, you need to be aware of who owns an object before you can be sure that it will be deleted: your Python application or another Qt object.</P><P>The trick is to determine who exactly owns the widget in question. Everything that is derived from <TTCLASS="CLASSNAME">QObject</TT> has the function <TTCLASS="FUNCTION">parent()</TT>, which can be used to determine the owner of a widget. You can use the function <TTCLASS="FUNCTION">removeChild</TT> to remove the widget itself. Using <TTCLASS="FUNCTION">parent()</TT> is often easier than remembering who exactly owned the widget you want to get rid of.</P><PRECLASS="PROGRAMLISTING">self.parent().removeChild(self) </PRE><P>If you execute this incantation, the poor widget will be orphaned, and a Python <TTCLASS="FUNCTION">del</TT> statement on the Python reference will definitively remove the child.</P><DIVCLASS="EXAMPLE"></A><P><B>Example 9-6. Eradicating a widget</B></P><PRECLASS="PROGRAMLISTING">## qtrefs4.py - removing a widget#import sysfrom qt import *class MainWindow(QMainWindow): def __init__(self, *args): apply(QMainWindow.__init__, (self, ) + args) self.parentedButton=QPushButton("A nice and steady button " + "that knows its place", self) self.parentedButton.resize(self.parentedButton.sizeHint()) self.connect(self.parentedButton, SIGNAL("clicked()"), self.removeButton) def removeButton(self): self.removeChild(self.parentedButton) del self.parentedButtondef main(args): app=QApplication(args) win=MainWindow() win.show() app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) app.exec_loop()if __name__=="__main__": main(sys.argv) </PRE></DIV><P>Pressing the button will remove it, first by removing the ownership relation between <TTCLASS="VARNAME">win</TT> and <TTCLASS="VARNAME">self.parentedButton</TT> and then removing the Python reference to the object.</P><P>It is possible to retrieve the children of a certain QObject object by calling <TT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -