index.lxp@lxpwrap=c4631_252ehtm.htm

来自「GUI Programming with Python」· HTM 代码 · 共 794 行 · 第 1/2 页

HTM
794
字号
></TR><TR><TDALIGN="LEFT"><P>I mentioned earlier, in          <A href="index.lxp@lxpwrap=x2765_252ehtm.htm#CH2QCOLOR">the Section called <I>QColor</I> in Chapter 10</A>, that the nice people at          Trolltech changed the name of the function that is          used to set background colors from          <TTCLASS="FUNCTION">setBackgroundColor</TT> to          <TTCLASS="FUNCTION">setEraseColor</TT>. This means of course          that you, if you want to run this example with PyQt 3,          will have to adapt the relevant calls.</P></TD></TR></TABLE></DIV><PRECLASS="PROGRAMLISTING">class DocviewView(QWidget):    def __init__(self, doc, *args):        apply(QWidget.__init__, (self, ) + args)        self.doc = doc        self.connect(self.doc, PYSIGNAL("sigDocModified"),                     self.slotDocModified)        self.slotDocModified(self.doc.isModified())    def slotDocModified(self, value):        if value:            self.setBackgroundColor(QColor("red"))        else:            self.setBackgroundColor(QColor("green"))      </PRE><P>The document has to notify the view of        changes. This means that the view has to have slots        corresponding to all the document signals the view is        interested in. A view can thus show changes to the document        selectively, and you can create more than one view, each with        a specialized function.</P><P>The <TTCLASS="CLASSNAME">DocviewApp</TT>        is the controller component. It controls both view and        document.</P><PRECLASS="PROGRAMLISTING">class DocviewApp(QMainWindow):    def __init__(self, *args):        apply(QMainWindow.__init__,(self, ) + args)        self.initActions()        self.initMenuBar()        self.initToolBar()        self.initStatusBar()        self.initDoc()        self.initView()      </PRE><P>The controller keeps a dictionary of        actions, making it easier to refer to those actions when        populating the menu and toolbars. The dictionary can also be        used to export functionality for a macro language, by calling        the        <TTCLASS="CLASSNAME">QAction</TT>.<TTCLASS="FUNCTION">activated()</TT>         slot, which is connected to the relevant slots in the        controller. The pixmap is in the form of an inline XPM image,        which is not shown here.</P><PRECLASS="PROGRAMLISTING">    def initActions(self):        fileQuitIcon=QIconSet(QPixmap(filequit))        self.actions = {}        self.actions["fileQuit"] = QAction("Exit",                                           fileQuitIcon,                                           "E&#38;xit",                                           QAccel.stringToKey("CTRL+Q"),                                           self)        self.connect(self.actions["fileQuit"],                     SIGNAL("activated()"),                     self.slotFileQuit)        self.actions["editDoc"] = QAction("Edit",                                           fileQuitIcon,                                           "&#38;Edit",                                           QAccel.stringToKey("CTRL+E"),                                           self)        self.connect(self.actions["editDoc"],                     SIGNAL("activated()"),                     self.slotEditDoc)      </PRE><P>Populating toolbars, menubars and        statusbars are always a bit tedious. When BlackAdder is        integrated with  Qt 3.0, it will be possible to design not        only dialogs and widgets, but also menu's and toolbars using a        very comfortable action editor. I will discuss the various        aspects of creating toolbars and menubars later in <A href="index.lxp@lxpwrap=c4807_252ehtm.htm">Chapter 13</A>.</P><PRECLASS="PROGRAMLISTING">    def initMenuBar(self):        self.fileMenu = QPopupMenu()        self.actions["fileQuit"].addTo(self.fileMenu)        self.menuBar().insertItem("&#38;File", self.fileMenu)        self.editMenu = QPopupMenu()        self.actions["editDoc"].addTo(self.editMenu)        self.menuBar().insertItem("&#38;Edit", self.editMenu)    def initToolBar(self):        self.fileToolbar = QToolBar(self, "file operations")        self.actions["fileQuit"].addTo(self.fileToolbar)        QWhatsThis.whatsThisButton(self.fileToolbar)    def initStatusBar(self):        self.statusBar().message("Ready...")        </PRE><P>Here the document, or application model, is          initialized.</P><PRECLASS="PROGRAMLISTING">    def initDoc(self):        self.doc=DocviewDoc()        </PRE><P>The view is created after the document,        and then made into the central application widget.</P><PRECLASS="PROGRAMLISTING">    def initView(self):        self.view = DocviewView( self.doc, self)        self.setCentralWidget(self.view)        </PRE><P>This function is called in the          <TTCLASS="FUNCTION">slotFileQuit()</TT> slot when the document          has been modified. Note that we're using a class function,          <TTCLASS="FUNCTION">information</TT>, from          <TTCLASS="CLASSNAME">QMessageBox</TT>. By passing an empty          string after the button labels for "Ok" and "Cancel", the          messagebox is created with only two buttons, instead of          three.</P><PRECLASS="PROGRAMLISTING">    def queryExit(self):        exit = QMessageBox.information(self,                                       "Quit...",                                       "Do you really want to quit?",                                       "&#38;Ok",                                        "&#38;Cancel",                                        "", 0, 1)        if exit==0:            return TRUE        else:            return FALSE        </PRE><P>The slot functions are called whenever        one of the <TTCLASS="CLASSNAME">QAction</TT>s is        <TTCLASS="FUNCTION">activated()</TT>. Note how the statusbar        message is set, before calling the document functions        directly. </P><PRECLASS="PROGRAMLISTING">    #    # Slot implementations    #    def slotFileQuit(self):        self.statusBar().message("Exiting application...")        if self.doc.isModified():            if self.queryExit():                qApp.quit()        else:            qApp.quit()        self.statusBar().message("Ready...")    def slotEditDoc(self):        self.doc.slotModify()def main(args):    app=QApplication(args)    docview = DocviewApp()    app.setMainWidget(docview)    docview.show()    app.exec_loop()    if __name__=="__main__":    main(sys.argv)        </PRE><P>This is the stub that starts the        application. In contrast with the examples from Part I, such        as <TTCLASS="FILENAME">hello5.py</TT>, this framework doesn't        check if all windows are closed with:</P><PRECLASS="PROGRAMLISTING">  app.connect(app, SIGNAL("lastWindowClosed()")                 , app, SLOT("quit()"))          </PRE><P>This is because the framework supports        only <SPAN><ICLASS="EMPHASIS">one</I></SPAN> window, and quitting the app is        integrated in the <TTCLASS="CLASSNAME">DocviewApp</TT>        class.</P><P>Now the startup bit is done, we can see        what <TTCLASS="FILENAME">docview.py</TT> produces when it is        run:</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>A very simple document-view framework            application</P></DIV></P></DIV><P>This framework only supports one window        with one view and one document. Another omission is that there        is no interaction between view and document. Usually, you will        also allow the view component to receive user actions, like        mouse clicks. These mostly arrive in the form of events. You        can handle these in various ways. The first is to directly        call the relevant slot functions in the document. Try adding        the following method to the <TTCLASS="CLASSNAME">DocviewView</TT>        class:</P><PRECLASS="PROGRAMLISTING">    def mouseDoubleClickEvent(self, ev):        self.doc.slotModify()      </PRE><P>This bypasses the controlling application        (<TTCLASS="CLASSNAME">DocviewApp</TT>) and leads to an        uncomfortably tight coupling between view and document.        Another way        to notify the document of the double-click is to let the view        emit a signal, which can be        caught by the application object and connected to the document        slot. Replace the previous function with the following        function in the <TTCLASS="CLASSNAME">DocviewView</TT> class         instead:</P><PRECLASS="PROGRAMLISTING">    def mouseDoubleClickEvent(self, ev):        self.emit(PYSIGNAL("sigViewDoubleClick"),())      </PRE><P>And to the        <TTCLASS="CLASSNAME">DocviewApp</TT>:</P><PRECLASS="PROGRAMLISTING">    def initView(self):        self.view = DocviewView( self.doc, self)        self.setCentralWidget(self.view)        self.connect(self.view, PYSIGNAL("sigViewDoubleClick"),                     self.slotEditDoc)      </PRE><P>As you can see, you can either call the        document directly from the view, or via the application        controller. The approach you choose depends on the complexity        of your application. In the rest of this part we will extend        this simple framework to include MDI (multiple document        interface) and MTI (multiple top-level windows interface)        applications.</P></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=p4627_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=x4760_252ehtm.htm">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Creating real applications with PyQt</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="U" href="index.lxp@lxpwrap=p4627_252ehtm.htm">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Macro languages</TD></TR></TABLE></DIV></BODY></HTML>      </td>      </tr>      </table>      </td>    </tr>  </table>      

⌨️ 快捷键说明

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