📄 index.lxp@lxpwrap=x2420_252ehtm.htm
字号:
CLASS="FUNCTION">children</TT> on QObject. Sip is clever enough to return the Python wrapper object associated with that instance (rather than the actual C++ object instance).</P><DIVCLASS="EXAMPLE"></A><P><B>Example 9-7. children.py - getting the children from a single parent</B></P><PRECLASS="PROGRAMLISTING">## children.py#import sysfrom qt import *def printChildren(obj, indent): children=obj.children() if children==None: return for child in children: print indent, child.name(), child.__class__ printChildren(child, indent + " ")class PyPushButton(QPushButton): passclass MainWindow(QMainWindow): def __init__(self, *args): apply(QMainWindow.__init__, (self, ) + args) mainwidget=QWidget(self, "mainwidget") layout=QVBoxLayout(mainwidget, 2, 2, "layout") button1=QPushButton("button1", mainwidget, "button1") button2=PyPushButton("button2", mainwidget, "button2") layout.addWidget(button1) layout.addWidget(button2) self.setCentralWidget(mainwidget) printChildren(self, " ")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>Running children.py will give the following output:</P><PRECLASS="SCREEN">boudewijn@maldar:~/doc/opendoc > python children.py hide-dock qt.QObject mainwidget qt.QWidget layout qt.QVBoxLayout button1 qt.QPushButton button2 __main__.PyPushButton unnamed qt.QObject unnamed qt.QObject unnamed qt.QObject unnamed qt.QObject unnamed qt.QObject unnamed qt.QObject</PRE><P>What you cannot see here is the parallel structure of <TTCLASS="CLASSNAME">QLayoutItems</TT> that proxy for the widgets. For that you need to use the <TTCLASS="CLASSNAME">QLayoutIterator</TT> that is provided by the <TTCLASS="FUNCTION">iterator()</TT> method of <TTCLASS="CLASSNAME">QListViewItem</TT>. Here, <TTCLASS="FUNCTION">next()</TT>, both returns the next item, and moves the iterator onwards.</P><DIVCLASS="EXAMPLE"></A><P><B>Example 9-8. Iterating over children</B></P><PRECLASS="PROGRAMLISTING">## children.py#import sysfrom qt import *def printChildren(obj, indent): iter = obj.iterator() while iter.current(): print "current:", iter.current() print "next:", iter.next()class PyPushButton(QPushButton): passclass MainWindow(QMainWindow): def __init__(self, *args): apply(QMainWindow.__init__, (self, ) + args) mainwidget=QWidget(self, "mainwidget") layout=QVBoxLayout(mainwidget, 2, 2, "layout") button1=QPushButton("button1", mainwidget, "button1") button2=PyPushButton("button2", mainwidget, "button2") button3=PyPushButton("button3", mainwidget, "button3") layout.addWidget(button1) layout.addWidget(button2) layout.addWidget(button3) self.setCentralWidget(mainwidget) printChildren(layout, " ") 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><PRECLASS="SCREEN">boud@calcifer:~/doc/pyqt/src/qt2/ch3 > python layoutchildren.pycurrent: <qt.QLayoutItem instance at 0x82ba8b4> next: <qt.QLayoutItem instance at 0x82ba9dc>current: <qt.QLayoutItem instance at 0x82ba9dc> next: <qt.QLayoutItem instance at 0x82baa8c>current: <qt.QLayoutItem instance at 0x82baa8c> next: None </PRE><P>Finally, let's test the ownership rules of Qt and Python objects using the interactive Python interpreter. In the following example, we create an object <TTCLASS="VARNAME">self.o</TT>, owned by PyQt, and then a child object is created, not owned by the instance of class <TTCLASS="CLASSNAME">A</TT>, but as a Qt child of object <TTCLASS="VARNAME">self.o</TT>. Thus, PyQt owns <TTCLASS="VARNAME">a</TT> and <TTCLASS="VARNAME">self.o</TT>, and Qt owns <TTCLASS="VARNAME">child</TT>, and <TTCLASS="VARNAME">child</TT> doesn't get deleted, even when the Python reference goes out of scope.</P><PRECLASS="SCREEN">>>> from qt import QObject>>> class A:... def __init__(self):... self.o=QObject()... child = QObject(self.o)... >>> a=A()>>> print a<__main__.A instance at 0x821cdac>>>> print a.o<qt.QObject instance at 0x821ce04>>>> print a.o.children()[<qt.QObject instance at 0x821cf54>]>>> </PRE><P>On the other hand, the following won't work, because as soon as the execution flow leaves the constructor, <TTCLASS="VARNAME">o</TT> is garbage collected, and <TTCLASS="VARNAME">child</TT>, is then garbage-collected, too, since it isn't owned by a Qt object, and Python doesn't have a reference to it anymore, either.</P><PRECLASS="SCREEN"> >>> class B:... def ___init__(self):... o=QObject()... child = QObject(o)... >>> b=B()>>> b.oTraceback (most recent call last): File "<stdin>", line 1, in ?AttributeError: o </PRE><P>On the other hand, it isn't necessary to keep a Python reference to all created objects: as long as the ultimate parent object is owned by PyQt, everything will go well:</P><PRECLASS="SCREEN">>>> class C:... def __init__(self):... self.o = QObject()... self.child = QObject(self.o)... >>> c = C()>>> c.o<qt.QObject instance at 0x8263f54>>>> c.o.children()[<qt.QObject instance at 0x821d334>]>>> c.child<qt.QObject instance at 0x821d334>>>> </PRE><P>As you see, it isn't necessary to keep a reference to <TTCLASS="VARNAME">child</TT>,- because PyQt is the owner of the first object (because it has no Qt parent but a reference to a Python object) but Qt is the owner of the second widget (because it <SPAN><ICLASS="EMPHASIS">does</I></SPAN> have a parent) and so the C++ instance (qt.QObject instance at 0x821d334) is not deleted when the corresponding Python object goes out of scope.</P><P>What if your Python class were a subclass of <TTCLASS="CLASSNAME">QObject</TT>?:</P><PRECLASS="SCREEN">>>> class D(QObject):... def __init__(self):... QObject.__init__(self)... o=QObject(self)... child = QObject(o)... >>> d=D()>>> d.children()[<qt.QObject instance at 0x821d614>]>>> d.children()[0].children()[<qt.QObject instance at 0x821d7c4>]>>> </PRE><P>As you can see, <TTCLASS="VARNAME">o</TT> doesn't get deleted, nor <TTCLASS="VARNAME">child</TT> - both are owned by Qt and will be deleted as soon as object <TTCLASS="VARNAME">d</TT> is deleted. You can still reach these objects by using the <TTCLASS="FUNCTION">children()</TT> function <TTCLASS="CLASSNAME">QObject</TT> provides.</P><P>This layer between Python and Qt is implemented in the <SPAN><ICLASS="EMPHASIS">sip</I></SPAN> library — sip not only generates the wrapper code, but is a library in its own right, containing functionality for the passing of object references between C++ and Python.</P><P>Sip is also responsible for the reference counting mechanisms. In most cases, Sip is clever enough to closely simulate Python behavior for C++ Qt objects. As you saw in the previous example, contrary to what happens in C++, when you remove the last reference to a C++ object, it will be automatically deleted by Sip.</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=x2393_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=x2540_252ehtm.htm">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Qt objects, Python objects and shadow objects</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="U" href="index.lxp@lxpwrap=c2341_252ehtm.htm">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Other C++ objects</TD></TR></TABLE></DIV></BODY></HTML> </td> </tr> </table> </td> </tr> </table>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -