⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 index.lxp@lxpwrap=x7601_252ehtm.htm

📁 GUI Programming with Python
💻 HTM
📖 第 1 页 / 共 2 页
字号:
    <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&#153;</div>    </div>      </td></tr></table>    <div align="center" class="author">      	<a href="../products.lxp">Products</a>	&nbsp;|&nbsp;	<a href="../wheretobuy.lxp">Where to buy</a>	&nbsp;|&nbsp;	<a href="../bookstore.lxp">Retailers</a>	&nbsp;|&nbsp;	<a href="../faq.lxp">FAQ</a>	&nbsp;|&nbsp;        <a href="../writeforus.lxp">Write for Us.</a>        &nbsp;|&nbsp;        <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>QCanvas</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="Drawing on Painters and Canvases"HREF="c7391.htm"><LINKREL="PREVIOUS"TITLE="Drawing on Painters and Canvases"HREF="c7391.htm"><LINKREL="NEXT"TITLE="Conclusion"HREF="x7875.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=c7391_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 21. Drawing on Painters and Canvases</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=x7875_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1">QCanvas</A></H1><P>The other way of pushing pixels on the      screen is using the <TTCLASS="CLASSNAME">QCanvas</TT> class. This      is rather more complicated than simply painting what you want,      but offers the unique capability of accessing the individual      elements of the composition. Not only that, but you can also      determine whether elements overlap each other, set them moving      across the canvas at a predefined rate, and show and hide them      at will.</P><P>In working with      <TTCLASS="CLASSNAME">QCanvas</TT>, three classes play an essential      role: the <TTCLASS="CLASSNAME">QCanvas</TT> itself, which is a      receptacle for <TTCLASS="CLASSNAME">QCanvasItem</TT> objects      &#8212; or rather, their descendants, and one or more      <TTCLASS="CLASSNAME">QCanvasView</TT> widgets are used to show the      canvas and its contents on screen.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>the relation between QCanvas,          QCanvasItems and QCanvasView</P></DIV></P></DIV><P>The class <TTCLASS="CLASSNAME">QCanvasItem</TT>      is rather special: you cannot instantiate objects from it, nor      can you directly subclass it. You <SPAN><ICLASS="EMPHASIS">can</I></SPAN>      instantiate and subclass the subclasses of      <TTCLASS="CLASSNAME">QCanvasItem</TT>:      <TTCLASS="CLASSNAME">QCanvasPolygonalItem</TT>,      <TTCLASS="CLASSNAME">QCanvasSprite</TT> and      <TTCLASS="CLASSNAME">QCanvasText</TT>.</P><P>Even      <TTCLASS="CLASSNAME">QCanvasPolygonalItem</TT> itself is not      terribly useful: the derived classes      <TTCLASS="CLASSNAME">QCanvasEllipse</TT>,      <TTCLASS="CLASSNAME">QCanvasLine</TT>,      <TTCLASS="CLASSNAME">QCanvasPolygon</TT> and      <TTCLASS="CLASSNAME">QCanvasRectangle</TT> can be used to draw      ellipses, lines, polygons and rectangles on the canvas.      Interestingly, these items can have a non-square bounding      box.</P><P>This means that two circles won't touch if      they overlap the box that contains them: only if the circles      themselves touch. This is quite special, and if you create new      derivations of these classes yourself, you should take care to      carefully calculate the area your object occupies.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>Overlapping and non-overlapping circles.</P></DIV></P></DIV><P>A <TTCLASS="CLASSNAME">QCanvasSprite</TT>      should be familiar to anyone who has ever played with an 8-bit      home computer. A <TTCLASS="CLASSNAME">QCanvasSprite</TT> is an      animated pixmap, and can move (like any      <TTCLASS="CLASSNAME">QCanvasItem</TT>) across the canvas under its      own steam. You fill the <TTCLASS="CLASSNAME">QCanvasSprite</TT>      with a <TTCLASS="CLASSNAME">QPixMapArray</TT>. This class contains      a list of <TTCLASS="CLASSNAME">QPixmap</TT>s and a list of      <TTCLASS="CLASSNAME">QPoint</TT>s. These define how the sprite      looks and where its hot spots are. If you want to create a game      using PyQt you'll probably want to use this class.</P><P>Lastly, the      <TTCLASS="CLASSNAME">QCanvasText</TT> can draw a single line of      text on the canvas. Let me repeat that: you can not create a      whole column of text, put it in a      <TTCLASS="CLASSNAME">QCanvasText</TT> object, and paste it on the      canvas. This makes creating a PageMaker clone just a little bit      more difficult.</P><P>Nevertheless, it is      <TTCLASS="CLASSNAME">QCanvasText</TT> which we are going to use in      the next section. Another example of the use      <TTCLASS="CLASSNAME">QCanvasText</TT> is the      <SPANCLASS="APPLICATION">Eric</SPAN> debugger, which is part of the      PyQt source distribution.</P><DIVCLASS="SECT2"><H2CLASS="SECT2">A simple Unicode character picker</A></H2><P>The goal of this example is to provide a        point-and-click way of entering characters from the        <SPAN><ICLASS="EMPHASIS">complete</I></SPAN> unicode range in        <SPANCLASS="APPLICATION">Kalam</SPAN>. The Unicode range is divided        into a few hundred scripts. What I want is a window that shows        a clickable table of one of those scripts, with a combo-box        that allows me to select the script I need. And when I click        on a character, that character should be inserted into the        current document.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>A Unicode character picker</P></DIV></P></DIV><P>The underlying data can be retrieved from the Unicode        consortium website. They provide a file,        <TTCLASS="FILENAME">Blocks.txt</TT>, that gives you the range each        script occupies:</P><PRECLASS="SCREEN"># Start Code; End Code; Block Name0000; 007F; Basic Latin0080; 00FF; Latin-1 Supplement0100; 017F; Latin Extended-A0180; 024F; Latin Extended-B0250; 02AF; IPA Extensions02B0; 02FF; Spacing Modifier Letters0300; 036F; Combining Diacritical Marks...F900; FAFF; CJK Compatibility IdeographsFB00; FB4F; Alphabetic Presentation FormsFB50; FDFF; Arabic Presentation Forms-AFE20; FE2F; Combining Half MarksFE30; FE4F; CJK Compatibility FormsFE50; FE6F; Small Form VariantsFE70; FEFE; Arabic Presentation Forms-BFEFF; FEFF; SpecialsFF00; FFEF; Halfwidth and Fullwidth FormsFFF0; FFFD; Specials      </PRE><P>This file can be used to fill a combobox        with all different scripts:</P><DIVCLASS="EXAMPLE"></A><P><B>Example 21-2. charmap.py - a Unicode character selection        widget</B></P><PRECLASS="PROGRAMLISTING">"""charmap.py - A unicode character selectorcopyright: (C) 2001, Boudewijn Remptemail:         boud@rempt.xs4all.nl"""import string, os.pathfrom qt import *TRUE=1FALSE=0class CharsetSelector(QComboBox):    def __init__(self, datadir, *args):        apply(QComboBox.__init__,(self,)+args)        self.charsets=[]        self.connect(self,                     SIGNAL("activated(int)"),                     self.sigActivated)        f=open(os.path.join(datadir,"Blocks.txt"))        f.readline() # skip first line        for line in f.readlines():            try:                self.charsets.append((string.atoi(line[0:4],16)                                      ,string.atoi(line[6:10],16)))                self.insertItem(line[12:-1])            except: pass    def sigActivated(self, index):        begin, start=self.charsets[index]        self.emit(PYSIGNAL("sigActivated"),(begin, start))      </PRE></DIV><P>This is simple enough: the location of        <TTCLASS="FILENAME">Blocks.txt</TT> is retrieved, and each line is        read. Every line represents one script, and for every line an        entry is inserted into the <TTCLASS="CLASSNAME">QComboBox</TT>.        In a separate list, <TTCLASS="VARNAME">self.charsets</TT>, we keep        a tuple with the begin and the end of each range, converted to        integers from their hexadecimal representation. Python is a        great language for this kind of data massaging.</P><P>Whenever the user selects an item from the combobox, a        signal is emitted, <TTCLASS="VARNAME">sigActivated</TT>, that        carries the begin and endpoint of the range.</P><DIVCLASS="SECT3"><H3CLASS="SECT3">The canvas</A></H3><P>Working with          <TTCLASS="CLASSNAME">QCanvas</TT> entails handling two classes:          <TTCLASS="CLASSNAME">QCanvas</TT> and          <TTCLASS="CLASSNAME">QCanvasView</TT>. In this section, we'll          lay out the Unicode table on the          <TTCLASS="CLASSNAME">QCanvas</TT>. From PyQt 3.0 onwards, the          canvas classes are in a separate module:          <TTCLASS="FILENAME">qtcanvas</TT>, which has to be imported          separately.</P><P>You can think of a          <TTCLASS="CLASSNAME">QCanvas</TT> as a virtually boundless          two-dimensional paste-board, which you can fill with          <TTCLASS="CLASSNAME">QCanvasItems</TT>. The main difference          between a <TTCLASS="CLASSNAME">QCanvas</TT> with          <TTCLASS="CLASSNAME">QCanvasItem</TT>s on it and a          <TTCLASS="CLASSNAME">QWidget</TT> with a lot of sub-widgets, is          that the first is a lot more efficient in terms of          memory-use, and offers easy collision detection. Of course,          <TTCLASS="CLASSNAME">QCanvasItem</TT>s are not widgets, so you          don't have easy event handling &#8212; but you can fake it          easily enough, by catching mouse presses on individual          <TTCLASS="CLASSNAME">QCanvasItem</TT>s.</P><P>Here, we will create a          <TTCLASS="CLASSNAME">QCanvasText</TT> for every Unicode          glyph. In the <TTCLASS="CLASSNAME">QCanvasView</TT>          mouse-clicks on those items will be caught.</P><PRECLASS="PROGRAMLISTING">class CharsetCanvas(QCanvas):    def __init__(self, parent, font, start, end, maxW, *args):        apply(QCanvas.__init__,(self, ) + args)        self.parent=parent        self.start=start        self.end=end        self.font=font        self.drawTable(maxW)    def drawTable(self, maxW):        self.maxW=maxW        self.items=[]        x=0        y=0        fontMetrics=QFontMetrics(self.font)        cell_width=fontMetrics.maxWidth() + 3        if self.maxW &#60; 16 * cell_width:            self.maxW = 16 * cell_width        cell_height=fontMetrics.lineSpacing()        for wch in range(self.start, self.end + 1):            item=QCanvasText(QString(QChar(wch)),self)            item.setFont(self.font)            item.setX(x)            item.setY(y)            item.show()            self.items.append(item)            x=x + cell_width            if x &#62;= self.maxW:                x=0                y=y+cell_height        if self.parent.height() &#62; y + cell_height:            h = self.parent.height()        else:            h = y + cell_height        self.resize(self.maxW + 20, h)        self.update()    def setFont(self, font):        self.font=font        self.drawTable(self.maxW)        </PRE><P>Most of the real work is done in the          <TTCLASS="FUNCTION">drawTable()</TT> method. The          <TTCLASS="VARNAME">maxW</TT> parameter determines how wide the          canvas will be. However, if there is not place enough for at          least sixteen glyphs, the width is adjusted.</P><P>Then the          <TTCLASS="CLASSNAME">QCanvasText</TT> items are created, in a          plain loop, starting at the beginning of the character set          and running to the end. You must give these items an initial          position and size, and explicitly call          <TTCLASS="FUNCTION">show()</TT> on each item. If you forget to          do this, all you will see is a very empty canvas.</P><P>You will also be greeted by an equally          empty canvas if you do not keep a Python reference to the          items &#8212; here a list of          <TTCLASS="CLASSNAME">QCanvasText</TT> items is kept in          <TTCLASS="VARNAME"

⌨️ 快捷键说明

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