index.lxp@lxpwrap=x5469_252ehtm.htm

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

HTM
855
字号
><P>The next section is concerned with the      implementation of the slots called by the      <TTCLASS="CLASSNAME">QAction</TT> objects that we just      created:</P><PRECLASS="PROGRAMLISTING">    #    # Slot implementations    #    def slotFileNew(self):        document = self.docManager.createDocument(MDIDoc, MDIView)    </PRE><P>Creating a document is now simply a matter      of asking the document manager to do it &#8212; just as we did      in the test script.</P><PRECLASS="PROGRAMLISTING">    def slotFileOpen(self):        fileName = QFileDialog.getOpenFileName(None, None, self)        if not fileName.isEmpty():            document=MDIDoc()            document.open(fileName)            view = self.docManager.addDocument(document, MDIView)            view.setFocus()    </PRE><P>Opening a file is slightly more      complicated; we need to be sure that the user actually selected      a file before a file can be opened. Remember that all Qt classes      return <TTCLASS="CLASSNAME">QString</TT> objects, not Python      <TTCLASS="CLASSNAME">string</TT> objects. As a result, we have to      use <TTCLASS="FUNCTION">isEmpty()</TT> instead of comparing with      <TTCLASS="CLASSNAME">None</TT>.</P><P>If the filename is not empty, we create an      empty document, ask that document to open the file, and then add      the document to the document manager. Of course, this complexity      can also be removed to the document manager, by adding an      <TTCLASS="FUNCTION">openDocument(self, fileName, documentClass,        viewClass)</TT> function to      <TTCLASS="CLASSNAME">DocManager</TT>.</P><PRECLASS="PROGRAMLISTING">    def slotFileSave(self, document=None):        if document == None:            document = self.docManager.activeDocument()        if document.pathName() == None:            self.slotFileSaveAs()        else:            try:                document.save()            except Exception, e:                QMessageBox.critical(self,                                     "Error",                                     "Could not save the current document")    def slotFileSaveAs(self, doc=None):        fileName = QFileDialog.getSaveFileName(None, None, self)        if not fileName.isEmpty():            if doc == None:                doc = self.docManager.activeDocument()            try:                doc.save(str(fileName))            except:                QMessageBox.critical(self,                                     "Error",                                     "Could not save the current document")    </PRE><P>Saving a document entails some complexity:      the document may or may not have a filename; if not, the user      should supply one. Saving could fail for a variety of reasons.      Nothing is so frustrating as losing your data because you simply      wanted to save it. An application should handle save errors very      carefully to ensure no data is lost.</P><PRECLASS="PROGRAMLISTING">    def slotFileClose(self):        doc=self.docManager.activeDocument()        self.docManager.closeDocument(doc)    def slotFileQuit(self):        try:            self.docManager.closeAllDocuments()        except:            return        qApp.quit()    </PRE><P>Closing a document and quitting the      application are closely related processes. Note the call to      <TTCLASS="FUNCTION">qApp.quit()</TT> &#8212; this is only reached      when closing all documents succeeds.</P><PRECLASS="PROGRAMLISTING">    def slotEditDoc(self):        doc = self.docManager.activeDocument()        doc.slotModify()    def slotWindowCloseWindow(self):        self.workspace.activeWindow().close()    </PRE><P>Closing a single window might mean that      the document will be closed, too &#8212; if it is the last or      only view the document has. By retrieving the active window from      the workspace, and calling the <TTCLASS="FUNCTION">close()</TT>      function on it, a <TTCLASS="FUNCTION">closeEvent</TT> will be      generated. This will be caught by the event filter defined      below, which calls the appropriate functions in the document      manager.</P><PRECLASS="PROGRAMLISTING">    def slotWindowNewWindow(self):        doc = self.docManager.activeDocument()        self.docManager.addView(doc, MDIView)    def slotHelpAbout(self):        QMessageBox.about(self,                          "About...",                          "MDI Framework\n" +                          "Inspired by the KDevelop templates.\n" +                          "(c) 2001 by Boudewijn Rempt")    </PRE><P>Adding a new window is very simple: retrieve the    currently active document, and ask the document manager to add a    view for that document.</P><PRECLASS="PROGRAMLISTING">    def slotWindowMenuAboutToShow(self):        self.windowMenu.clear()        self.actions["windowNewWindow"].addTo(self.windowMenu)        self.actions["windowCascade"].addTo(self.windowMenu)	self.actions["windowTile"].addTo(self.windowMenu)        self.windowMenu.insertSeparator()        self.actions["windowCloseWindow"].addTo(self.windowMenu)        if self.workspace.windowList()==[]:            self.actions["windowAction"].setEnabled(FALSE)        else:            self.actions["windowAction"].setEnabled(TRUE)        self.windowMenu.insertSeparator()        i=0 # window numbering        self.menuToWindowMap={}        for window in self.workspace.windowList():            i+=1            index=self.windowMenu.insertItem(("&#38;%i " % i) +                                             str(window.caption()),                                             self.slotWindowMenuActivated)            self.menuToWindowMap[index]=window            if self.workspace.activeWindow()==window:                self.windowMenu.setItemChecked(index, TRUE)    def slotWindowMenuActivated(self, index):        self.menuToWindowMap[index].setFocus()    </PRE><P>Here, we dynamically create the window      menu just before it is shown. The four menu options&#8212;new      window, cascade, tile and close&#8212;are part of a single      <TTCLASS="CLASSNAME">QActionGroup</TT>, and can be enabled or      disabled together. Of course, the same could be done with the      other actions that are only enabled when there are actually      documents in existence. Note also that we add accelerators by      numbering the views (this will, of course, stop being sensible      once we have more than nine open windows).</P><PRECLASS="PROGRAMLISTING">    #    # Toplevel event filter    #    def eventFilter(self, object, event):        if (event.type() == QEvent.Close):            if (object != self):                if self.docManager.closeView(object):                    event.accept()                else:                    event.ignore()            else:                try:                    self.docManager.closeAllDocuments()                    event.accept()                except Exception, e:                    return TRUE        return QWidget.eventFilter(self, object, event)    </PRE><P>Qt events contrast with Qt signals in that      they are typically created by user actions, such as key presses      or mouse actions. Signals are mostly emitted by objects on      themselves.</P><P>An event filter is an object that receives      all events for the object to which it applies. You can install      eventfilters that are created for one object in other objects.      In this case, all views share the same event filter as the      application object. An eventfilter must return either true or      false&#8212;true if the event should not be propagated further,      and false if someone should handle the event.</P><P>Here, we check whether the event is of the      type <TTCLASS="VARNAME">QEvent.close</TT> &#8212; if that is so, we      check whether it is meant for the main application window      (that's us&#8212; the <TTCLASS="VARNAME">self</TT>). In that case,      all documents must be closed. This event is generated when the      user closes the application.</P><P>If the event is meant for one of the      sub-windows, the document manager is asked to close the view. If      that is successful, the event is      <TTCLASS="FUNCTION">accept()</TT>-ed, and will not be propagated any      further.</P><PRECLASS="PROGRAMLISTING">    #    # Functions called from the document manager    #def queryCloseDocument(self, document):        r = QMessageBox.information(self,                                    str(self.caption()),                                    "Do you want to close %s?" %                                    document.title(),                                    "Yes",                                    "No",                                    None,                                    0, 1)        if r == 0:            return QMessageBox.Yes        else:            return QMessageBox.No    def querySaveDocument(self, document):        r = QMessageBox.information(self,                                    str(self.caption()),                                    "Do you want to save your changes to " +                                    "%s?" %                                    document.title(),                                    "Yes",                                    "No",                                    "Cancel",                                    0, 2)        if r == 0:            return QMessageBox.Yes        elif r == 1:            return QMessageBox.No        else:            return QMessageBox.Cancel    def queryDiscardDocument(self, document):        r = QMessageBox.warning(self,                                str(self.caption()),                                "Could not save %s.\n" % document.title() +                                "Do you want to discard your changes?",                                "Yes",                                "No",                                None,                                0, 1)        if r == 0:            return QMessageBox.Yes        else:            return QMessageBox.No    def queryFileName (self, document=None):        fileName = QFileDialog.getSaveFileName(None, None, self)        if not fileName.isEmpty():            return str(fileName)        else:            return "untitled"    </PRE><P>These calls to      <TTCLASS="CLASSNAME">QMessageBox</TT> and the standard file dialog      <TTCLASS="CLASSNAME">QFileDialog</TT> are made from the document      manager. This makes sure that the document manager can also work      without a GUI.</P><P>The <TTCLASS="CLASSNAME">QMessageBox</TT>      class is a bit messy, by Qt standards. There are two ways of      specifying buttons: by string, or by identity. These identities,      like <TTCLASS="VARNAME">QMessageBox.Yes</TT> are defined in the      class. If you use these constants in your calls to      <TTCLASS="FUNCTION">QMessageBox.warning()</TT>, for instance, then      the return value will be the identity of the button      pressed.</P><P>However, if you want the added flexibility      of translatable strings, you cannot use the identities. You can      call functions like <TTCLASS="FUNCTION">QMessageBox.warning()</TT>      with strings, but the return value will be the position of the      key pressed, starting with 0 and going from left to      right.</P><P>I want to use the identities in the      document manager &#8212; this makes the code a lot clearer. But      I wanted to use strings in the actual message boxes. That's why      I translate the position of the button pressed to the correct      identity.</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=x5458_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=x5581_252ehtm.htm">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">View</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="U" href="index.lxp@lxpwrap=c5288_252ehtm.htm">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Conclusion</TD></TR></TABLE></DIV></BODY></HTML>      </td>      </tr>      </table>      </td>    </tr>  </table>      

⌨️ 快捷键说明

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