📄 index.lxp@lxpwrap=x6734_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>Non-modal: Search and replace</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="Using Dialog Windows"HREF="c6351.htm"><LINKREL="PREVIOUS"TITLE="Using Dialog Windows"HREF="c6351.htm"><LINKREL="NEXT"TITLE="Conclusion"HREF="x6992.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=c6351_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 19. Using Dialog Windows</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=x6992_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1">Non-modal: Search and replace</A></H1><P>In the previous section we constructed a deviously complex (at least, it felt that way) modal dialog box. Now we will attempt something comparable for a non-modal dialog box.</P><DIVCLASS="SECT2"><H2CLASS="SECT2">Design</A></H2><P>What we are aiming for is a combined "search" and "search and replace" dialog box. It should conform to the following requirements:</P><P></P><UL><LI><P>Two kinds of search: plain text and regular expressions.</P></LI><LI><P>Search forward and backward</P></LI><LI><P>Case sensitive or insensitive search</P></LI><LI><P>Search from the beginning of the text or the current cursor position</P></LI><LI><P>Search on a selection or the whole text.</P></LI><LI><P>Choice between replace one occurrence after another, or or all occurrences.</P></LI></UL><P>A tall order? Certainly, but also quite probably very instructive. A few minutes with the Designer gives us the following, esthetically pleasing, dialog box:</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>The find and replace dialog.</P></DIV></P></DIV></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2">Integration in the application</A></H2><P>Implementing all this functionality is quite complex, so it is best to first make sure that we can call the find and replace dialog window from the application. This entails adding two <TTCLASS="CLASSNAME">QAction</TT>'s to the action dictionary, an icon to <TTCLASS="FILENAME">resources.py</TT>, and two new slots—and creating the dialog, of course.</P><P>You don't create, run and destroy a non-modal dialog, like we did with the settings dialog. Instead, you create it once, and show it whenever necessary. The Close button on the dialog doesn't really close it; it merely hides the window. In this case, the find and replace dialog is created in the constructor of <TTCLASS="CLASSNAME">KalamApp</TT>:</P><PRECLASS="PROGRAMLISTING">...from dlgfindreplace import DlgFindReplace...class KalamApp(QMainWindow): def __init__(self, *args): apply(QMainWindow.__init__,(self, ) + args) ... # Create the non-modal dialogs self.dlgFindReplace = DlgFindReplace(self, "Find and replace") </PRE><P>There are two actions defined: one for search, and one for find and replace. Again, the "find" icon is the standard KDE 2 icon for find operations.</P><PRECLASS="PROGRAMLISTING"> def initActions(self): self.actions = {} ... # # Edit actions # ... self.actions["editFind"] = QAction("Find", QIconSet(QPixmap(editfind)), "&Find", QAccel.stringToKey("CTRL+F"), self) self.connect(self.actions["editFind"], SIGNAL("activated()"), self.slotEditFind) self.actions["editReplace"] = QAction("Replace", "&Replace", QAccel.stringToKey("CTRL+R"), self) self.connect(self.actions["editReplace"], SIGNAL("activated()"), self.slotEditReplace) </PRE><P>By now, you probably know what comes next: adding the actions to the menu bar, and to the toolbar. Since there isn't an icon for replace, it cannot be added to the toolbar:</P><PRECLASS="PROGRAMLISTING"> def initMenuBar(self): ... self.editMenu = QPopupMenu() ... self.editMenu.insertSeparator() self.actions["editFind"].addTo(self.editMenu) self.actions["editReplace"].addTo(self.editMenu) self.menuBar().insertItem("&Edit", self.editMenu) ... def initToolBar(self): ... self.editToolbar = QToolBar(self, "edit operations") ... self.actions["editFind"].addTo(self.editToolbar) </PRE><P>Because the combined find/find and replace dialog has two modes, it is necessary to have two ways of calling it—one for find, and one for find and replace. The dialog should work on the current document and the current view, but it is difficult to determine if ‘current' should be the current document and view when the dialog is opened, as opposed to the document and view that have focus. The user might, after all, change document and view while the find dialog is open, or even close them. For now, let's use the document and view that are open when the dialog is shown.</P><PRECLASS="PROGRAMLISTING"> def slotEditFind(self): self.dlgFindReplace.showFind(self.docManager.activeDocument(), self.workspace.activeWindow()) def slotEditReplace(self): self.dlgFindReplace.showReplace(self.docManager.activeDocument(), self.workspace.activeWindow()) </PRE><P>The actual implementation in <TTCLASS="CLASSNAME">DlgFindReplace</TT> of these show function is quite simple. The Find option hides certain widgets, after which the automatic layout management ensures that the dialog looks as good as it should. The Find and Replace options makes sure they are shown. The window caption is adapted, too. Note that you must first call <TTCLASS="FUNCTION">show()</TT> on the entire dialog, and only then <TTCLASS="FUNCTION">show()</TT> on the previously hidden widgets, otherwise the layout manager doesn't show the appearing widgets.</P><PRECLASS="PROGRAMLISTING"> def showFind(self, document, view): FrmFindReplace.show(self) self.setCaption("Find in " + document.title()) self.bnReplaceNext.hide() self.bnReplaceAll.hide() self.grpReplace.hide() self.initOptions(document, view) def showReplace(self, document, view): FrmFindReplace.show(self) self.setCaption("Find and replace in " + document.title()) self.bnReplaceNext.show() self.bnReplaceAll.show() self.grpReplace.show() self.initOptions(document, view) </PRE><P>The result is pretty enough to show:</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>The Find dialog.</P></DIV></P></DIV></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2">Implementation of the functionality</A></H2><P>Now that we can show the find and replace dialog, it is time to implement some functionality. Again, we subclass the generated design and add what we need. </P><PRECLASS="PROGRAMLISTING">"""dlgfindreplace.py - Findreplace dialog for Kalam.See: frmfindreplace.uicopyright: (C) 2001, Boudewijn Remptemail: boud@rempt.xs4all.nl"""import os, sysfrom qt import *import kalamconfigfrom resources import TRUE, FALSEfrom frmfindreplace import FrmFindReplaceclass DlgFindReplace(FrmFindReplace): """ A full-featured search and replace dialog. """ def __init__(self, parent = None, name = None): FrmFindReplace.__init__(self, parent, name, FALSE, Qt.WStyle_Dialog) self.connect(self.bnFind, SIGNAL("clicked()"), self.slotFindNext) self.connect(self.bnReplaceNext, SIGNAL("clicked()"), self.slotReplaceNext) self.connect(self.bnReplaceAll, SIGNAL("clicked()"), self.slotReplaceAll) self.connect(self.radioRegexp, SIGNAL("clicked()"), self.slotRegExp) self.connect(self.chkCaseSensitive, SIGNAL("clicked()"), self.slotCaseSensitive) self.connect(self.chkWholeText, SIGNAL("clicked()"), self.slotBeginning) self.connect(self.chkSelection, SIGNAL("clicked()"), self.slotSelection) self.connect(self.radioForward, SIGNAL("clicked()"), self.slotForward) self.connect(self.radioBackward, SIGNAL("clicked()"), self.slotBackward) </PRE><P>In the constructor we connect all relevant <TTCLASS="FUNCTION">clicked()</TT> signals to their slots. The rest of the initialization (such as determining which text or part of text we will work on) is moved to the <TTCLASS="FUNCTION">show()</TT>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -