c6351.htm

来自「GUI Programming with Python」· HTM 代码 · 共 1,422 行 · 第 1/3 页

HTM
1,422
字号
<HTML><HEAD><TITLE>Using Dialog Windows</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="Creating real applications with PyQt"HREF="p4627.htm"><LINKREL="PREVIOUS"TITLE="Conclusion"HREF="x6342.htm"><LINKREL="NEXT"TITLE="Non-modal: Search and      replace"HREF="x6734.htm"></HEAD><BODYCLASS="CHAPTER"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"><AHREF="x6342.htm"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="x6734.htm"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1><ANAME="CH14">Chapter 19. Using Dialog Windows</A></H1><DIVCLASS="TOC"><DL><DT><B>Table of Contents</B></DT><DT><AHREF="c6351.htm#AEN6357">Modal: a preferences dialog</A></DT><DT><AHREF="x6734.htm">Non-modal: Search and      replace</A></DT><DT><AHREF="x6992.htm">Conclusion</A></DT></DL></DIV><P>In this chapter we add a few dialog windows    to the <SPANCLASS="APPLICATION">Kalam</SPAN> program. Dialog windows    come in two basic flavors: modal and non-modal. Modal dialog    windows block the interface of you application. Settings dialog,    file dialogs and such are typically modal. Non-modal dialogs can    stay open while the user continues working in the application.    Search and replace or style dialogs are typical examples of    non-modal dialogs.</P><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="AEN6357">Modal: a preferences dialog</A></H1><P>We will start with a preferences dialog.      Nowadays, the taste is for dialogs with a strip of icons to the      left that somehow indicates what section should be shown. But we      will start out with a simple tabbed dialog that PyQt supports      out of the box, and for which we don't have to draw icons      (that's always the difficult bit, creating the artwork).</P><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN6360">Designing the dialog</A></H2><P>So: time to fire up the designer module        of BlackAdder or Qt Designer!</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>The settings dialog - editor tab</P></DIV></P></DIV><P>I like to show a sample of what the user        selects in the dialog. In this tab, the user can select font,        text and background color for the editor windows. These        changes are reflected in the little label with the "Lorem        ipsum" text. There are two more options: a combobox for        selecting the wrapping mode (either no wrapping, wrap to the        maximum line width, or wrap to the width of the window), and a        spin box to set the maximum line width.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>The settings dialog - interface tab</P></DIV></P></DIV><P>Most users will not immediately get what        we mean with "Window view" - in the interface tab w show an        example of what we mean, too. I propose to make the "Look and        Feel" selection automatically active, so that doesn't need a        preview.</P><P>To fill in the preview I've snapshotted        <SPANCLASS="APPLICATION">Kalam</SPAN> in all its variations and        scaled the pictures down a lot. Adding these pictures as        inline-image data to the dialog would make loading very slow,        since Python is not so quick in reading bytecode files. It is        better to create a <TTCLASS="FILENAME">pixmaps</TT> directory and        store the pictures there.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>The settings dialog - document tab</P></DIV></P></DIV><P>As for the document, we need two        settings: the first is the document encoding. While        <SPANCLASS="APPLICATION">Kalam</SPAN> is meant to be a Unicode        editor for standard <SPAN><ICLASS="EMPHASIS">utf8</I></SPAN> files, people        might prefer things like iso-8859-1. This is mere        window-dressing&#8212;actually loading and saving in encodings        other than utf-8 will not be implemented for now. The second        option is about document endings. A text file should end with        a newline character, and we added code to make sure it does in        <AHREF="c5783.htm">Chapter 17</A>&#8212;ultimately, this should be a        configuration option.</P><P>Of course, during the course of        development we will expand the contents of these pages, adding        items when we need them. Someone once remarked that a        configuration dialog presents the history of design decisions        that were avoided during development&#8212;and it often feels        that way indeed.</P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN6398">Creating the settings dialog window</A></H2><P>The first part of the drill is well        known: compile the <TTCLASS="FILENAME">frmsettings.ui</TT> file to        Python using <BCLASS="COMMAND">pyuic</B>.      </P><PRECLASS="SCREEN">pyuic -x frmsettings.ui &#62; frmsettings.py      </PRE><P>You can either call this generated        dialog directly from <TTCLASS="CLASSNAME">KalamApp</TT>, or you        can subclass it and add some intelligence. Since intelligence        is what is needed to synchronize the switches between        interface paradigm, we will go ahead and add subclass the        design and add some.        </P><PRECLASS="PROGRAMLISTING">"""dlgsettings.py - Settings dialog for Kalam.See: frmsettings.uicopyright: (C) 2001, Boudewijn Remptemail:     boud@rempt.xs4all.nl"""import os, sysfrom qt import *import kalamconfigfrom frmsettings import FrmSettingsclass DlgSettings(FrmSettings):    def __init__(self,                 parent = None,                 name = None,                 modal = 0,                 fl = 0):        FrmSettings.__init__(self, parent, name, modal, fl)        self.textFont = kalamconfig.get("textfont")        self.textBackgroundColor = kalamconfig.get("textbackground")        self.textForegroundColor = kalamconfig.get("textforeground")        self.MDIBackgroundColor = kalamconfig.get("mdibackground")        self.initEditorTab()        self.initInterfaceTab()        self.initDocumentTab()      </PRE><P>The <TTCLASS="CLASSNAME">DlgSettings</TT>        dialog is a subclass of <TTCLASS="CLASSNAME">FrmSettings</TT>,        which we created with Designer. In the constructor we create        four objects for housekeeping purposes, to store changed        settings until the user chooses to apply them by pressing OK,        or to cancel.</P><P>These objects represent the editor font,        the editor text color, the editor background color and the        background color of the MDI workspace. As you can see from the        calls to <TTCLASS="FILENAME">kalamconfig</TT>, actually        implementing this dialog necessitated quite a few changes to        the <TTCLASS="FILENAME">kalamconfig</TT> module.</P><P>The full source of        <TTCLASS="FILENAME">kalamconfig</TT> is not so interesting for        this chapter, but it is available with the rest of the code.        To summarize the development: all settings are now retrieved        and set through a single pair of get/set functions. There are        a lot more settings, too. If a setting requires special        handling, then the relevant get/set function is retrieved from        a dictionary (you can just as easily store references to        functions or classes in a dictionary as in strings, since        everything is considered an object) and executed with        <TTCLASS="FUNCTION">apply()</TT>. If a setting is changed, a        signal is emitted from the <TTCLASS="CLASSNAME">QApplication</TT>        instance, which can be reached with the global variable        <TTCLASS="VARNAME">qApp</TT>. Note how the actual signal identifier        is constructed dynamically:</P><PRECLASS="PROGRAMLISTING">## kalamconfig.py# Get and set - set emits a signal via Config.notifier#customGetSetDictionary = {    "style" : (getStyle, setStyle),    "workspace" : (getWorkspace, setWorkspace),    "textfont" : (getTextFont, setTextFont),    "textforeground" : (getTextForegroundColor, setTextForegroundColor),    "textbackground" : (getTextBackgroundColor, setTextBackgroundColor),    "mdibackground" : (getMDIBackgroundColor, setMDIBackgroundColor),}def set(attribute, value):    if customGetSetDictionary.has_key(attribute):        apply(customGetSetDictionary[attribute][1], (value,))    else:        setattr(Config, attribute, value)    qApp.emit(PYSIGNAL("sig" + str(attribute) + "Changed"),                         (value,))def get(attribute):    if customGetSetDictionary.has_key(attribute):        value = apply(customGetSetDictionary[attribute][0])    else:        value = getattr(Config, attribute)    return value      </PRE><P>But, let us continue with        <TTCLASS="FILENAME">dlgsettings.py</TT>. There are three tab        pages, and every tab pages has its own initialization function.</P><PRECLASS="PROGRAMLISTING">    def initEditorTab(self):        self.txtEditorPreview.setFont(self.textFont)        pl = self.txtEditorPreview.palette()        pl.setColor(QColorGroup.Base, self.textBackgroundColor)        pl.setColor(QColorGroup.Text, self.textForegroundColor)                self.cmbLineWrapping.setCurrentItem(kalamconfig.get("wrapmode"))        self.spinLineWidth.setValue(kalamconfig.get("linewidth"))        self.connect(self.bnBackgroundColor,                     SIGNAL("clicked()"),                     self.slotBackgroundColor)        self.connect(self.bnForegroundColor,                     SIGNAL("clicked()"),                     self.slotForegroundColor)        self.connect(self.bnFont,                     SIGNAL("clicked()"),                     self.slotFont)      </PRE><P>The editor tab shows a nice preview of        the font and color combination the user has chosen. Setting        these colors, however, is not as straightforward as you might        think. Qt widget colors are governed by a complex system based        around palettes. A palette (<TTCLASS="CLASSNAME">QPalette</TT>)        contains three color groups        (<TTCLASS="CLASSNAME">QColorGroup</TT>), one that is used if the        widget is active, one that is used if the widget is disabled,        and one that is used if the widget is inactive.</P><P>A <TTCLASS="CLASSNAME">QColorGroup</TT> in its turn, is a set      of colors with certain roles:</P><P></P><UL><LI><P>Background - general            background color.</P></LI><LI><P>Foreground - general            foreground color.</P></LI><LI><P>Base - background color text            entry widgets          </P></LI><LI><P>Text - the foreground color            used with Base.</P></LI><LI><P>Button - general button            background color</P></LI><LI><P>ButtonText - for button            texts</P></LI><LI><P>Light - lighter than Button            color. </P></LI><LI

⌨️ 快捷键说明

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