wxpython 之 GDI(一)

GDI (图形设备接口) 是与图形界面交互的接口。它用于与图形设备如显示器、 打印机或文件进行交互。GDI 允许程序员在屏幕或打印机上显示数据,而不必关心特定设备的详细信息。GDI 可以使程序开发隔离于硬件。

从程序员的角度来看,GDI 是一组用于处理图形的类和方法。GDI 包括二维矢量图形、 字体和图像。

在开始绘制图形前,我们必须先创建一个设备上下文 (DC) 对象。在 wxPython中, 这个设备上下文叫wx.DC。可以在其上绘制的图形和文本。它一般方式表示设备的数量。相同的代码片段可以用不同种类的设备来实现。Wx.DC 不直接使用。相反,程序员应该选择派生类之一。每个派生的类的目的是要在特定条件下使用。

 

  • wxBufferedDC
  • wxBufferedPaintDC
  • wxPostScriptDC
  • wxMemoryDC
  • wxPrinterDC
  • wxScreenDC
  • wxClientDC
  • wxPaintDC
  • wxWindowDC

Wx.ScreenDC 用于绘制在屏幕上的任意位置。Wx.WindowDC绘制整个窗口中 (仅 Windows),这包括窗口装饰部分。Wx.ClientDC 用于绘制窗口的客户端区域。客户端区域的面积不包括它的装饰品(标题和边框)。Wx.PaintDC也是用于在客户端领域绘制。但wx.PaintDC 和 wx.ClientDC之间有一个区别。w.PaintDC应该在wx.PaintEvent事件中使用。Wx.ClientDC 不应该在wx.PaintEvent中使用。Wx.MemoryDC 用于在位图上绘制图形。Wx.PostScriptDC 用于写入任何平台上的 PostScript 文件。Wx.PrinterDC 用来访问打印机 (仅 Windows)。

 

绘制简单线条

我们的第一个示例在窗口的客户端区域绘制简单线条。
DrawLine (int x 1、 int y1、 int x 2、 int y2)
此方法绘制一条从第一个点到第二个。不包括第二点。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class DrawLineDemo(wx.Frame):
    def __init__(self, parent, title = 'draw a simple line demon'):
        super(DrawLineDemo, self).__init__(parent, title = title, size = (250, 150) )
        
        wx.FutureCall(2000, self.__DrawLine)
        self.Centre()
        self.Show()
    
    def __DrawLine(self):
        dc = wx.ClientDC(self)
        dc.DrawLine(50, 60, 190 ,60)

if __name__ == '__main__':
    app = wx.App()
    DrawLineDemo(None)
    app.MainLoop()

我们在窗口显示出来2秒后,画一条线

 wx.FutureCall(2000, self.DrawLine)

在创建窗口后,我们调用 DrawLine() 方法。我们这样做,是因为在创建窗口时,它画过了。我们的所有绘图都会因此丢失。在创建窗口后,我们可以用wx.FutureCall() 方法画线。

 def DrawLine(self):
     dc = wx.ClientDC(self)
     dc.DrawLine(50, 60, 190, 60)

我们创建 wx.ClientDC 的设备上下文。唯一的参数是,我们想要绘制的窗口。在我们的例子中self DrawLineDemo实例的引用。我们调用设备上下文的DrawLine() 方法。此调用实际上是在我们的窗口上绘制线条。

它是非常重要的是要了解以下的行为。如果我们调整窗口的大小,行将消失。为什么会这样呢?如果窗口大小被改变或者最大最小化,窗口将被重绘。窗口绘制到它的默认状态,我们的线都将丢失。我们要在每次调整窗口的大小时,绘制线条。解决方案是 wx.PaintEvent。每次在重绘窗口,将触发此事件。我们将绘制直线的方法挂钩到 paint 事件的方法内。

 

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class DrawLineDemo(wx.Frame):
    def __init__(self, parent, title = 'draw a simple line demon'):
        super(DrawLineDemo, self).__init__(parent, title = title, size = (250, 150) )
        
        self.Centre()
        self.Bind(wx.EVT_PAINT, self.__OnPaint)
        self.Show()
    
    def __OnPaint(self, event):
        self.__DrawLine()
    
    def __DrawLine(self):
        dc = wx.PaintDC(self)
        dc.DrawLine(50, 60, 190 ,60)

if __name__ == '__main__':
    app = wx.App()
    DrawLineDemo(None)
    app.MainLoop()

 这次是在paint event中 画这条线的。

self.Bind(wx.EVT_PAINT, self.OnPaint)

我们绑定方法 OnPaint到事件wx.PaintEvent. 这意味着每次窗口重新绘制, 我们调用OnPaint方法。如果我们改变窗口大小,现在这条线将不会消失了。注意这次 我们使用wx.PaintDC设备上下文。

计算机图形

有两个不同的计算机图形。矢量和栅格图形。栅格图形是像素的集合表示的图像。矢量图形是几何基元 (如点、 线条、 曲线或多边形来表示图像。这些基元是使用数学方程来创建的。
两种类型的计算机图形学有优点和缺点。矢量图像相对于栅格图形的优势是:
  • 较小的大小
  • 无限放大的能力
  • 移动、 缩放、 填充或旋转不会降低图像的质量

 基元类型 

  • points
  • lines
  • polylines
  • polygons
  • circles
  • ellipses
  • Splines

设备上下文属性  

AttributeObjectDefault valueGet MethodSet Method
Brush wx.Brush wx.WHITE_BRUSH wx.Brush GetBrush() SetBrush(wx.Brush brush)
Pen wx.Pen wx.BLACK_PEN wx.Pen GetPen() SetPen(wx.Pen pen)
Mapping Mode - wx.MM_TEXT int GetMapMode() SetMapMode(int mode)
BackgroundMode - wx.TRANSPARENT int GetBackgroundMode() SetBackgroundMode(int mode)
Text background colour wx.Colour wx.WHITE wx.Colour GetTextBackground() SetTextBackground(wx.Colour colour)
Text foreground colour wx.Colour wx.BLACK wx.Colour GetTextForeground() SetTextForeground(wx.Colour colour)

 

 

 

 

 

基本元素

在以下各节中,我们将介绍的元素对象,颜色、 画笔、 笔、 联接,帽,渐变。

Colours

颜色对象是由红色、 绿色和蓝色 (RGB) 值的组合。有效的 RGB 值为 0 到 255 范围内。有三种方法来设置颜色。我们可以创建 wx.Colour对象,使用一个预定义的颜色名称或使用十六进制值的字符串。wx.Colour(0,0,255),'BLUE'、 '#0000FF'。这三种表示法生产同一颜色。
在 colorjack.com 网站上,可以找到一个完美的工具,用于处理颜色。或者我们可以作为 Gimp 使用这种工具。
我们也有我们可以在我们的程序中使用的预定义的颜色名称的列表。
Standard Colour Database
AQUAMARINE BLACK BLUE BLUE VIOLET BROWN
CADET BLUE CORAL CORNFLOWER BLUE CYAN DARK GREY
DARK GREEN DARK OLIVE GREEN DARK ORCHID DARK SLATE BLUE DARK SLATE GREY
DARK TURQUOISE DIM GREY FIREBRICK FOREST GREEN GOLD
GOLDENROD GREY GREEN GREEN YELLOW INDIAN RED
KHAKI LIGHT BLUE LIGHT GREY LIGHT STEEL BLUE LIME GREEN
MAGENTA MAROON MEDIUM AQUAMARINE MEDIUM BLUE MEDIUM FOREST GREEN
MEDIUM GOLDENROD MEDIUM ORCHID MEDIUM SEA GREEN MEDIUM SLATE BLUE MEDIUM SPRING GREEN
MEDIUM TURQUOISE MEDIUM VIOLET RED MIDNIGHT BLUE NAVY ORANGE
ORANGE RED ORCHID PALE GREEN PINK PLUM
PURPLE RED SALMON SEA GREEN SIENNA
SKY BLUE SLATE BLUE SPRING GREEN STEEL BLUE TAN
THISTLE TURQUOISE VIOLET VIOLET RED WHEAT
WHITE YELLOW YELLOW GREEN  

 

 

 基本使用:

 

 

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class ColorDemo(wx.Frame):
    def __init__(self, parent, title = 'draw rectangle with color'):
        super(ColorDemo, self).__init__(parent, title = title, size = (250, 150) )
        
        self.Centre()
        self.Bind(wx.EVT_PAINT, self.__OnPaint)
        self.Show()
    
    def __OnPaint(self, event):
        dc = wx.PaintDC(self)
        dc.SetPen(wx.Pen('#d4d4d4'))
        
        dc.SetBrush(wx.Brush('#c56c00'))
        dc.DrawRectangle(10, 15, 90, 60)
        
        dc.SetBrush(wx.Brush('#1ac500'))
        dc.DrawRectangle(130, 15, 90, 60)

        dc.SetBrush(wx.Brush('#539e47'))
        dc.DrawRectangle(250, 15, 90, 60)

        dc.SetBrush(wx.Brush('#004fc5'))
        dc.DrawRectangle(10, 105, 90, 60)

        dc.SetBrush(wx.Brush('#c50024'))
        dc.DrawRectangle(130, 105, 90, 60)

        dc.SetBrush(wx.Brush('#9e4757'))
        dc.DrawRectangle(250, 105, 90, 60)

        dc.SetBrush(wx.Brush('#5f3b00'))
        dc.DrawRectangle(10, 195, 90, 60)

        dc.SetBrush(wx.Brush('#4c4c4c'))
        dc.DrawRectangle(130, 195, 90, 60)

        dc.SetBrush(wx.Brush('#785f36'))
        dc.DrawRectangle(250, 195, 90, 60)
        
        
if __name__ == '__main__':
    app = wx.App()
    ColorDemo(None)
    app.MainLoop()

 

我们画了9个矩形,而且用不同的颜色填充。

dc.SetBrush(wx.Brush('#c56c00'))
dc.DrawRectangle(10, 15, 90, 60)

 

我们用16进制数定义颜色。画刷用来填充形状的背景色。我们画; 如下矩形:

wx.Pen

画笔是一个基本图形对象。它用于绘制线条、 曲线和矩形、 椭圆、 多边形或其他形状的轮廓。

wx.Pen(wx.Colour colour, width=1, style=wx.SOLID)

 

wx.Pen的构造函数 有3个参数, Colour, width and style。 下面列举了所有可能的pen的 style

Pen styles

  • wx.SOLID
  • wx.DOT
  • wx.LONG_DASH
  • wx.SHORT_DASH
  • wx.DOT_DASH
  • wx.TRANSPARENT

 

基本用法:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class PensDemo(wx.Frame):
    def __init__(self, parent, id = -1, title = ' pens demo'):
        wx.Frame.__init__(self, parent, id, title, size=(350, 190))

        self.Bind(wx.EVT_PAINT, self.OnPaint)

        self.Centre()
        self.Show(True)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)

        dc.SetPen(wx.Pen('#4c4c4c', 1, wx.SOLID))
        dc.DrawRectangle(10, 15, 90, 60)

        dc.SetPen(wx.Pen('#4c4c4c', 1, wx.DOT))
        dc.DrawRectangle(130, 15, 90, 60)

        dc.SetPen(wx.Pen('#4c4c4c', 1, wx.LONG_DASH))
        dc.DrawRectangle(250, 15, 90, 60)

        dc.SetPen(wx.Pen('#4c4c4c', 1, wx.SHORT_DASH))
        dc.DrawRectangle(10, 105, 90, 60)

        dc.SetPen(wx.Pen('#4c4c4c', 1, wx.DOT_DASH))
        dc.DrawRectangle(130, 105, 90, 60)

        dc.SetPen(wx.Pen('#4c4c4c', 1, wx.TRANSPARENT))
        dc.DrawRectangle(250, 105, 90, 60)
        
        
if __name__ == '__main__':
    app = wx.App()
    PensDemo(None)
    app.MainLoop()

如果我们不自定义画笔,则使用默认画笔wx.WHITE_BRUSH。由钢笔绘制矩形的边界。最后一个没有边框。它是透明的。例如不可见。

 

Joins and Caps

 Pen 对象具有额外的两个参数。联接和帽。联接定义如何绘制线条之间的联接。联接样式具有以下选项:

  • wx.JOIN_MITER
  • wx.JOIN_BEVEL
  • wx.JOIN_ROUND

当使用wx.JOIN_MITER,扩展线的外边缘。他们满足一定角度,这个区域被填充。

当使用wx.JOIN_BEVEL,填充两条直线之间的三角槽口。

当使用wx.JOIN_ROUND,用扇形来填充两条直线之间的结合处。该是默认的选项。

帽定义如何绘制线的末端。选项有:

  • wx.CAP_ROUND 
  • wx.CAP_PROJECTING
  • wx.CAP_BUTT

wx.CAP_ROUND 绘制带弧度的末端。The wx.CAP_PROJECTING and thewx.CAP_BUTT都绘制方形末端。他们之间的不同是,wx.CAP_PROJECTING将多绘制超过线的一半尺寸的末端。

 

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class JoinsCaps(wx.Frame):
    def __init__(self, parent, id = -1, title = 'Pen joins caps'):
        wx.Frame.__init__(self, parent, id, title, size=(330, 300))

        self.Bind(wx.EVT_PAINT, self.OnPaint)

        self.Centre()
        self.Show(True)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)

        pen = wx.Pen('#4c4c4c', 10, wx.SOLID)

        pen.SetJoin(wx.JOIN_MITER)
        dc.SetPen(pen)
        dc.DrawRectangle(15, 15, 80, 50)

        pen.SetJoin(wx.JOIN_BEVEL)
        dc.SetPen(pen)
        dc.DrawRectangle(125, 15, 80, 50)

        pen.SetJoin(wx.JOIN_ROUND)
        dc.SetPen(pen)
        dc.DrawRectangle(235, 15, 80, 50)

        pen.SetCap(wx.CAP_BUTT)
        dc.SetPen(pen)
        dc.DrawLine(30, 150,  150, 150)

        pen.SetCap(wx.CAP_PROJECTING)
        dc.SetPen(pen)
        dc.DrawLine(30, 190,  150, 190)

        pen.SetCap(wx.CAP_ROUND)
        dc.SetPen(pen)
        dc.DrawLine(30, 230,  150, 230)

        pen2 = wx.Pen('#4c4c4c', 1, wx.SOLID)
        dc.SetPen(pen2)
        dc.DrawLine(30, 130, 30, 250)
        dc.DrawLine(150, 130, 150, 250)
        dc.DrawLine(155, 130, 155, 250)

app = wx.App()
JoinsCaps(None, -1, 'Joins and Caps')
app.MainLoop()
        
        
if __name__ == '__main__':
    app = wx.App()
    JoinsCaps(None)
    app.MainLoop()

 

要查看不同的联接和帽样式,我们需要设置画笔的宽度必须大于 线条1

dc.DrawLine(150, 130, 150, 250)
dc.DrawLine(155, 130, 155, 250)

 

请注意这两个封闭垂直线条。它们之间的距离是 5px。它是宽度的完全的当前画笔的一半。

 

Gradients

在计算机图形中,渐变是从亮到暗或从到另一种颜色的底纹的光滑混合。在 2D 绘图程序和画图程序中,使用渐变创建丰富的背景和特殊效果以及模拟灯和阴影。

GradientFillLinear(wx.Rect rect, wx.Colour initialColour, wx.Colour destColour, int nDirection=wx.EAST)

 

 此方法用线性渐变填充 rect所指定的区域,从 initialColour 开始,最终渐变到 destColour。NDirection 参数指定的颜色变化的方向,则默认值为 wx.EAST

 

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class Gradients(wx.Frame):
    def __init__(self, parent, id = -1, title = 'Gradients'):
        wx.Frame.__init__(self, parent, id, title, size=(220, 260))

        self.Bind(wx.EVT_PAINT, self.OnPaint)

        self.Centre()
        self.Show(True)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)

        dc.GradientFillLinear((20, 20, 180, 40), '#ffec00', '#000000', wx.NORTH)
        dc.GradientFillLinear((20, 80, 180, 40), '#ffec00', '#000000', wx.SOUTH)
        dc.GradientFillLinear((20, 140, 180, 40), '#ffec00', '#000000', wx.EAST)
        dc.GradientFillLinear((20, 200, 180, 40), '#ffec00', '#000000', wx.WEST)
       
        
if __name__ == '__main__':
    app = wx.App()
    Gradients(None)
    app.MainLoop()

 

wx.Brush

画刷是一个基本图形对象。它用来绘制的图形形状,如矩形、 椭圆或多边形背景。

 wx.Brush(wx.Colour colour, style=wx.SOLID)

 

wx.Brush构造函数接受2个参数,  Colour name and style.。下面列举了所有可能的画刷styles

Brush styles

  • wx.SOLID
  • wx.STIPPLE
  • wx.BDIAGONAL_HATCH
  • wx.CROSSDIAG_HATCH
  • wx.FDIAGONAL_HATCH
  • wx.CROSS_HATCH
  • wx.HORIZONTAL_HATCH
  • wx.VERTICAL_HATCH
  • wx.TRANSPARENT
#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class Brushs(wx.Frame):
    def __init__(self, parent , id = -1, title = 'Brushs'):
        wx.Frame.__init__(self, parent, id, title, size=(350, 280))

        self.Bind(wx.EVT_PAINT, self.OnPaint)

        self.Centre()
        self.Show(True)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)

        dc.SetBrush(wx.Brush('#4c4c4c', wx.CROSS_HATCH))
        dc.DrawRectangle(10, 15, 90, 60)

        dc.SetBrush(wx.Brush('#4c4c4c', wx.SOLID))
        dc.DrawRectangle(130, 15, 90, 60)

        dc.SetBrush(wx.Brush('#4c4c4c', wx.BDIAGONAL_HATCH))
        dc.DrawRectangle(250, 15, 90, 60)

        dc.SetBrush(wx.Brush('#4c4c4c', wx.CROSSDIAG_HATCH))
        dc.DrawRectangle(10, 105, 90, 60)

        dc.SetBrush(wx.Brush('#4c4c4c', wx.FDIAGONAL_HATCH))
        dc.DrawRectangle(130, 105, 90, 60)

        dc.SetBrush(wx.Brush('#4c4c4c', wx.HORIZONTAL_HATCH))
        dc.DrawRectangle(250, 105, 90, 60)

        dc.SetBrush(wx.Brush('#4c4c4c', wx.VERTICAL_HATCH))
        dc.DrawRectangle(10, 195, 90, 60)

        dc.SetBrush(wx.Brush('#4c4c4c', wx.TRANSPARENT))
        dc.DrawRectangle(130, 195, 90, 60)

       
        
if __name__ == '__main__':
    app = wx.App()
    Brushs(None)
    app.MainLoop()

Custom Patterns

我们并不局限于使用预定义的模式。我们可以轻松地创建我们自己的自定义模式。

wx.Brush BrushFromBitmap(wx.Bitmap stippleBitmap)
#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class CustomPatterns(wx.Frame):
    def __init__(self, parent, id = -1, title = 'image brush'):
        wx.Frame.__init__(self, parent, id, title, size=(350, 280))

        self.Bind(wx.EVT_PAINT, self.OnPaint)

        self.Centre()
        self.Show(True)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)

        dc.SetPen(wx.Pen('#C7C3C3'))

        brush1 = wx.BrushFromBitmap(wx.Bitmap('pattern1.jpg'))
        dc.SetBrush(brush1)
        dc.DrawRectangle(10, 15, 90, 60)

        brush2 = wx.BrushFromBitmap(wx.Bitmap('pattern2.jpg'))
        dc.SetBrush(brush2)
        dc.DrawRectangle(130, 15, 90, 60)

        brush3 = wx.BrushFromBitmap(wx.Bitmap('pattern3.jpg'))
        dc.SetBrush(brush3)
        dc.DrawRectangle(250, 15, 90, 60)

        
       
        
if __name__ == '__main__':
    app = wx.App()
    CustomPatterns(None)
    app.MainLoop()

 

 

 

 

 

posted on 2012-12-30 10:08  |残阳|露  阅读(3712)  评论(0编辑  收藏  举报

导航