📄 index.lxp@lxpwrap=x7947_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>Creating themes with QStyle</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="Gui Design in the Baroque Age"HREF="c7878.htm"><LINKREL="PREVIOUS"TITLE="Faking it with bitmaps"HREF="x7898.htm"><LINKREL="NEXT"TITLE="Drag and drop"HREF="c8016.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=x7898_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 22. Gui Design in the Baroque Age</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=c8016_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1">Creating themes with QStyle</A></H1><P>We've just created a beautifully sculpted interface, with all the highlights exactly right. Of course, the process lacked any flexibility. Fortunately, PyQt offers complete access to the Qt theming mechanism. Using this mechanism we can achieve almost the same effect, but in a more flexible and generic manner. </P><P>The key class here is <TTCLASS="CLASSNAME">QStyle</TT>. This class provides an enormous number of methods that are used by Qt's widgets to express themselves on screen — and a few hooks that you can use to intervene just before a widget paints itself. <TTCLASS="CLASSNAME">QCommonStyle</TT> is based on <TTCLASS="CLASSNAME">QStyle</TT>, and implements most of the actual drawing routines. On top of <TTCLASS="CLASSNAME">QCommonStyle</TT> is a whole tree of styles for Motif, Windows, MacOS-platinum, SGI and CDE. A desktop environment like KDE adds a whole host of other styles - and we can add one, too, once we have designed it. </P><DIVCLASS="SECT2"><H2CLASS="SECT2">Designing the style</A></H2><P>Designing a successful widget style is an artistic endeavor that calls for sensitive handling and an acute awareness of usability principles, as can easily be seen from the thousands of horrible styles available from websites like www.themes.org. But then, designing a user interface calls for the same expertise. That's the reason most software houses employ interaction designers and graphic artists. Software developers who don't have access to these specialists can refer to the excellent books on interface design published by Apple and Microsoft. These are the <SPAN><ICLASS="EMPHASIS">Macintosh Human Interface Guidelines</I></SPAN> (http://www.devworld.apple.com/techpubs/mac/HIGuidelines/HIGuidelines-2.html) and <SPAN><ICLASS="EMPHASIS">Microsoft Guidelines for Interface design</I></SPAN>, respectively. The Interface Hall of Shame website (http://www.iarchitect.com/mshame.htm) has some hilarious examples of interface design!</P><P>On the other hand, making something <SPAN><ICLASS="EMPHASIS">look</I></SPAN> like something else is a lot easier. For this project, I've pondered a few example styles that would illustrate the capabilities of the <TTCLASS="CLASSNAME">QStyle</TT> mechanism: the old Athena widget look and feel, or the old ‘flat' MacOS look and feel. The new Aqua style was right out, for legal reasons. Perhaps the look of the rubber keyboard or the old ZX-Spectrum? For my example, we'll try the old, flat MacOS look. This one has the advantage of being visually simple. You can complicate the implementation of a style enormously by using complex gradients to fill buttons, or bitmaps and masks to fill widget backgrounds. The <TTCLASS="CLASSNAME">QStyle</TT> is flexible enough that you can use anything the <TTCLASS="CLASSNAME">QPainter</TT> class offers to paint your widgets. On the other hand, some parts are exceedingly difficult to adapt, as we shall see.</P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2">Setting up</A></H2><P>The system that is used to implement custom styles changed completely between Qt 2 and Qt 3, which is a pity, because at the time of writing this book the new styling system had not been completely finished (and not wrapped for PyQt), but the old system has been removed.</P><P>New styles are implemented by subclassing one of the descendants of <TTCLASS="CLASSNAME">QStyle</TT> (this holds for both systems).</P><P>Under the old system, most of the widget drawing code would have been placed in the <TTCLASS="FUNCTION">polish()</TT> and <TTCLASS="FUNCTION">unpolish()</TT> methods of the style implementation.</P><P>The new system demands that you re-implement the primitive drawing functions, such as <TTCLASS="FUNCTION">drawItem()</TT>, <TTCLASS="FUNCTION">drawPrimitive()</TT> or <TTCLASS="FUNCTION">drawComplexControl</TT>.</P><P>In both cases, you can decide to either use bitmaps for buttons and backgrounds. This is shown in the <TTCLASS="FILENAME">themes.py</TT> example in your <SPANCLASS="APPLICATION">BlackAdder</SPAN> or <SPANCLASS="APPLICATION">PyQt</SPAN> distribution. Alternatively, you can write your own drawing routines. It is surprising that Python is fast enough to allow re-implementing the most basic drawing routines.</P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2">A Qt 2 custom style</A></H2><DIVCLASS="EXAMPLE"></A><P><B>Example 22-4. A Qt 2 custom style - a minimalist implementation of the classic Mac style in PyQt.</B></P><PRECLASS="PROGRAMLISTING">## macstyle.py - A minimalist implementation of the Mac Classic style for PyQt# and Qt 2.# Use with styletester.py#from qt import *import timeFALSE=0TRUE=1class MacStyle(QWindowsStyle): def __init__(self): QWindowsStyle.__init__(self) self.setButtonDefaultIndicatorWidth(0) def polish(self, object): # Overloading doesn't work here, for Python cannot distinguish # between QApplication and QWidget - Python can only overload based # on the number of arguments. if isinstance(object, QApplication): self.polish_qapplication(object) elif isinstance(object, QWidget): self.polish_qwidget(object) else: QPlatinumStyle.polish(self, object) def unPolish(self, object): if isinstance(object, QApplication): self.unPolish_qapplication(object) elif isinstance(object, QWidget): self.unPolish_qwidget(object) else: QPlatinumStyle.unPolish(self, object) def polish_qapplication(self, app): # Set a font that's an approximation of Chicago: keep a ref to # the old font self.oldFont=app.font() app.setFont(QFont("chicago", app.font().pointSize()-2, QFont.Bold), TRUE) # keep a reference to the old color palette, otherwise # it cannot be restored self.oldPalette=app.palette() # create a new palette - black, white and 50% gray for text and buttons # color definitions white=QColor("white") lightgray=QColor(210,210,210) gray=QColor(190,190,190) darkgray=QColor(120,120,120) black=QColor("black") active=QColorGroup() # # Basic colors # active.setColor(QColorGroup.Background, white) # general background color active.setColor(QColorGroup.Foreground, black) # general foreground color active.setColor(QColorGroup.Base, white) # lighter background for text widgets active.setColor(QColorGroup.Text, black) # foreground to go with Base active.setColor(QColorGroup.Button, white) # button background color active.setColor(QColorGroup.ButtonText, black) # button text color # # Used for bevels and shadows # active.setColor(QColorGroup.Light, lightgray ) # a bit lighter than Button active.setColor(QColorGroup.Midlight, gray) active.setColor(QColorGroup.Dark, darkgray) # depressed button state active.setColor(QColorGroup.Mid, gray) # mid tone active.setColor(QColorGroup.Shadow, black) # shadow tone # # Selections # active.setColor(QColorGroup.Highlight, black) active.setColor(QColorGroup.HighlightedText, white) # # Text color that shows well on Dark # active.setColor(QColorGroup.BrightText, white) disabled=QColorGroup(active) disabled.setColor(QColorGroup.Base, gray) disabled.setColor(QColorGroup.Text, darkgray) inactive=QColorGroup(active) inactive.setColor(QColorGroup.Text, darkgray) self.newPalette=QPalette(active, disabled, inactive) app.setPalette(self.newPalette, TRUE) def unPolish_qapplication(self, app): # Restore the old palette app.setFont(self.oldFont, TRUE) app.setPalette(self.oldPalette, TRUE) def polish_qwidget(self, w): # Hook to set attributes of certain widgets # the polish function will set some widgets to transparent mode, to get the # full benefit from the nice pixmaps in the color group. if w.inherits("QTipLabel"): return if w.inherits("QLCDNumber"): return if not w.isTopLevel(): if w.inherits("QLabel") \ or w.inherits("QButton") \ or w.inherits("QComboBox") \ or w.inherits("QGroupBox") \ or w.inherits("QSlider") \ or w.inherits("QTabWidget") \ or w.inherits("QPanel"): w.setAutoMask(TRUE) def unPolish_qwidget(self, w): # Undo what we did in polish_qwidget if w.inherits("QTipLabel"): return if w.inherits("QLCDNumber"): return if not w.isTopLevel(): if w.inherits("QLabel") \ or w.inherits("QButton") \ or w.inherits("QComboBox") \ or w.inherits("QGroupBox") \ or w.inherits("QSlider") \ or w.inherits("QTabWidget") \ or w.inherits("QPanel"): w.setAutoMask(FALSE) # # Panel, rectangles and lines # def drawPopupPanel(self, painter,x, y, w, h, colorGroup, lineWidth, fill): self.drawPanel(painter, x, y, w, h, colorGroup, FALSE, lineWidth, fill) def drawPanel(self, painter, x, y, w, h, colorGroup, sunken, lineWidth, fill): oldpen=painter.pen() oldbrush=painter.brush() if sunken:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -