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)。
绘制简单线条
#!/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
设备上下文属性
Attribute | Object | Default value | Get Method | Set 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
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()