⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 index.lxp@lxpwrap=c1267_252ehtm.htm

📁 GUI Programming with Python
💻 HTM
📖 第 1 页 / 共 2 页
字号:
>Example 7-3. A central registry of connected widgets</B></P><PRECLASS="PROGRAMLISTING">## registry.py &#8212; a central registry of connected widgets#class Registry:    def __init__(self):        self.connections={}                                <IMGSRC="images/callouts/1.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(1)"></A>    def add(self, occasion, function):                     <IMGSRC="images/callouts/2.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(2)"></A>        if self.connections.has_key(occasion) == 0:            self.connections[occasion]=[function]        else:            self.connections[occasion].append(function)    def remove(self, occasion, function):                  <IMGSRC="images/callouts/3.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(3)"></A>        if self.connections.has_key(occasion):            self.connections[occasion].remove(function)    def execute(self, occasion):        if self.connections.has_key(occasion):             <IMGSRC="images/callouts/4.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(4)"></A>            for function in self.connections[occasion]:                apply(function)registry=Registry()                                                           <IMGSRC="images/callouts/5.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(5)"></A>class Button:                                                           <IMGSRC="images/callouts/6.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(6)"></A>    def clicked(self):        registry.execute("clicked")class Application:    def __init__(self):        self.button=Button()        registry.add("clicked", self.doAppSpecificFunction)        registry.add("clicked", self.doSecondFunction)     <IMGSRC="images/callouts/7.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(7)"></A>    def doAppSpecificFunction(self):        print "Function called"    def doSecondFunction(self):        print "A second function is called."app=Application()app.button.clicked()        </PRE><DIVCLASS="CALLOUTLIST"><DLCOMPACT="COMPACT"><DT><A href="index.lxp@lxpwrap=c1267_252ehtm.htm#CH6REGISTRYCONNECTIONS"><IMGSRC="images/callouts/1.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(1)"></A></DT><DD>The actual registry is a Python dictionary with                the name <TTCLASS="VARNAME">connections</TT>. Here,                each <TTCLASS="VARNAME">occasion</TT> is used as a key to                find the actual function object that should be called.</DD><DT><A href="index.lxp@lxpwrap=c1267_252ehtm.htm#CH6REGISTRYADD"><IMGSRC="images/callouts/2.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(2)"></A></DT><DD>If the &#8216;occasion' is already registered, we simply                add a new entry to the list; otherwise a new entry                is created in the registry.</DD><DT><A href="index.lxp@lxpwrap=c1267_252ehtm.htm#CH6REGISTRYREMOVE"><IMGSRC="images/callouts/3.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(3)"></A></DT><DD>If the &#8216;occasion' exists, then we remove the                relevant function entry from its list of                functions.</DD><DT><A href="index.lxp@lxpwrap=c1267_252ehtm.htm#CH6REGISTRYEXECUTE"><IMGSRC="images/callouts/4.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(4)"></A></DT><DD>We loop over all functions that belong to this                &#8216;occasion' and simply execute them by calling                <TTCLASS="FUNCTION">apply()</TT> on them.</DD><DT><A href="index.lxp@lxpwrap=c1267_252ehtm.htm#CH6REGISTRYCREATE"><IMGSRC="images/callouts/5.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(5)"></A></DT><DD>A registry is a unique object to an application:                there should only be one, so we create it globally.</DD><DT><A href="index.lxp@lxpwrap=c1267_252ehtm.htm#CH6REGISTRYBUTTON"><IMGSRC="images/callouts/6.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(6)"></A></DT><DD>This is the &#8216;button' class.                Whenever the button is &#8216;clicked', it calls the                <TTCLASS="FUNCTION">execute()</TT> function in the                registry with the &#8216;clicked' occasion.</DD><DT><A href="index.lxp@lxpwrap=c1267_252ehtm.htm#CH6REGISTRYAPPLICATION"><IMGSRC="images/callouts/7.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(7)"></A></DT><DD>The application creates one button and binds two                of its functions to the button. This looks a                lot like the way connections are made in Qt!</DD><DT><A href="index.lxp@lxpwrap=c1267_252ehtm.htm#CH6REGISTRYSIMULATE"><IMGSRC="images/callouts/8.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(8)"></A></DT><DD>Here we simulate a button click by directly                calling the <TTCLASS="FUNCTION">clicked()</TT> function on                the button.</DD></DL></DIV></DIV><P>This is one step up from the previous example, which was        an extremely crude implementation of the well known Observer        design pattern, in that there is now a &#8216;neutral' object that        mediates between the button and the application. However, it        is still not particularly sophisticated. It certainly wouldn't do        for a real application &#8212; where there might be many        objects with the same &#8216;occasion'.</P><P>It is quite possible to implement a solution like this in        pure Python, especially with the weak references module that        debuted in Python 2.1. Bernhard Herzog has done so in his fine        Python application <SPANCLASS="APPLICATION">Sketch</SPAN>        (http://sketch.sourceforge.net). He had to do it himself        &#8212; because he was working in PyGTK, not PyQt.        Fortunately, PyQt has already solved the whole problem for        us.</P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2">Signals and slots</A></H2><P>We've just outlined the problem which the        developers of Qt at Trolltech have solved in a unique and        flexible manner. They created the concept of signals and        slots. <SPAN><ICLASS="EMPHASIS">signals</I></SPAN> are sent by an object that        wants to tell the world something interesting has happened,        and by <SPAN><ICLASS="EMPHASIS">connecting</I></SPAN> the "signals to the        slots", those signals arrive at the <SPAN><ICLASS="EMPHASIS">slots</I></SPAN>        of the objects that are interested.</P><P>On the whole the concept is really neat        and clean and the implementation well-executed. What's more,        the concept is even better suited to Python than it is to C++.        If you want to use signals and slots in C++, you have to work        with a preprocessor, called <BCLASS="COMMAND">moc</B>, and        indicate with special macros which function can be called as a        slot, and which function is a signal. All that is completely        unnecessary in Python, where a signal is a string, and any        function can be a slot.</P><P>Signals and slots are not magic, of        course. As with our simple Python registry, there has to be a        registry of objects that are interested in signals. This        registry is updated by the <TTCLASS="FUNCTION">connect</TT> and        <TTCLASS="FUNCTION">disconnect</TT> functions; both are member        functions of the <TTCLASS="CLASSNAME">QObject</TT> class. The        registry, as far as Python signals and slots is concerned, is        kept by the sip library. Signals and slots that are defined in        the underlying C++ library are maintained by the        <TTCLASS="CLASSNAME">QObject</TT> class itself.</P><P>In a nutshell, signals and slots are the        solution Qt provides for situations in which you want two        objects to interact, while keeping that fact hidden from        them.</P><DIVCLASS="NOTE"><BLOCKQUOTECLASS="NOTE"><P><B>Signals, messages, events: </B>This is one area where there is a          perfect Babel of tongues. Even really knowledgeable people          like Dr Dobbs' Al Stevens get confused when confronted with          terms like &#8216;message', &#8216;event' or          &#8216;signal'.</P><P>In PyQt programming, the term          '&#8216;message' is quite irrelevant &#8212; it is used in          Windows programming to indicate function calls made from          your application to the Windows GUI libraries.</P><P>Events and signals, on the other hand,          are central to PyQt. Signals and slots are used to connect          one object to another. An example is the perennial          pushbutton, whose <TTCLASS="FUNCTION">clicked()</TT> signal gets          connected to the <TTCLASS="FUNCTION">accept()</TT> slot function          of a dialog box. Signals are used to connect entities          internal to the application.</P><P>Events are more often generated          directly by user input, such as moving or clicking with the          mouse, or typing at the keyboard. As such, they don't          connect two class instances, but rather a physical object,          such as a keyboard, with an application. Events are          encapsulated by the <TTCLASS="CLASSNAME">QEvent</TT> class, and          are mostly delivered to <TTCLASS="CLASSNAME">QWidget</TT> and          its descendants. Events are used to communication with          external entities.</P></BLOCKQUOTE></DIV></DIV></DIV></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=x1263_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=x1408_252ehtm.htm">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Conclusion</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="U" href="index.lxp@lxpwrap=p1032_252ehtm.htm">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Connecting with signals and slots</TD></TR></TABLE></DIV></BODY></HTML>      </td>      </tr>      </table>      </td>    </tr>  </table>      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -