wx.DC
能够在电脑显示器上显示对象,是GUI工具包最基本的功能之一。对于wxPython,对象通过发送给设备上下文(Device Context, DC)的绘制命令显示在屏幕上。在底层,所有控件都是以位图形式绘制在屏幕上。DC的接口允许自定义控件的外观。
所有可见地显示在屏幕上的窗口发出一些绘制命令给DC,告诉系统哪些像素信息显示在屏幕上。一些控件类,例如wx.Control, wx.Window和wx.Panel,允许通过使用wx.EVT_PAINT,自定义控件在屏幕上显示什么。
示例说明
创建一个滑动显示窗口部件,用来显示目录下PNG或JPG文件。
#-*-coding: UTF-8 -*-
#------------------------------------------------------
#Purpose: nothing....
#Author: 阿Bin先生
#Created: 2017年5月21日
#------------------------------------------------------
import os
import wx
class SlideShowPanel(wx.PyPanel):
def __init__(self, parent):
super(SlideShowPanel, self).__init__(parent)
# Attributes
self.idx = 0 # Current index in image list
self.images = list() # list of images found to display
# Event Handlers
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_LEFT_UP, self.Next)
self.Bind(wx.EVT_RIGHT_UP, self.Previous)
self.SetImageDir("E:/TestData")
def DoGetBestSize(self):
"""Virtual override for PyPanel"""
newsize = wx.Size(0, 0)
if len(self.images):
imgpath = self.images[self.idx]
bmp = wx.Bitmap(imgpath)
newsize = bmp.GetSize()
newsize = newsize + (20, 20) # some padding
else:
tsize = self.GetTextExtent("No Image!")
newsize = tsize + (20, 20)
# Ensure new size is at least 300x300
return wx.Size(max(300, newsize[0]),
max(300, newsize[1]))
def OnPaint(self, event):
"""Draw the image on to the panel"""
dc = wx.PaintDC(self) # Must create a PaintDC
# Get the working rectangle
rect = self.GetClientRect()
# Setup the DC
dc.SetTextForeground(wx.BLACK)
# Do the drawing
if len(self.images):
# Draw the current image
imgpath = self.images[self.idx]
bmp = wx.Bitmap(imgpath)
bsize = bmp.GetSize()
# Try and center the image
# Note: assumes image is smaller than canvas
xpos = (rect.width - bsize[0]) / 2
ypos = (rect.height - bsize[1]) / 2
dc.DrawBitmap(bmp, xpos, ypos)
# Draw a label under the image saying what
# number in the set it is.
imgcount = len(self.images)
number = "%d / %d" % (self.idx+1, imgcount)
tsize = dc.GetTextExtent(number)
xpos = (rect.width - tsize[0]) / 2
ypos = ypos + bsize[1] + 5 # 5px below image
dc.DrawText(number, xpos, ypos)
else:
# Display that there are no images
font = self.GetFont()
font.SetWeight(wx.FONTWEIGHT_BOLD)
dc.SetFont(font)
dc.DrawLabel("No Images!", rect, wx.ALIGN_CENTER)
def Next(self, event):
"""Goto next image"""
self.idx += 1
if self.idx >= len(self.images):
self.idx = 0 # Go back to zero
self.Refresh() # Causes a repaint
def Previous(self, event):
"""Goto previous image"""
self.idx -= 1
if self.idx < 0:
self.idx = len(self.images) - 1 # Goto end
self.Refresh() # Causes a repaint
def SetImageDir(self, imgpath):
"""Set the path to where the images are"""
assert os.path.exists(imgpath)
# Find all the images in the directory
self.images = [ os.path.join(imgpath, img)
for img in os.listdir(imgpath)
if img.lower().endswith('.png') or
img.lower().endswith('.jpg') ]
self.idx = 0
class MyFrame(wx.Frame):
def __init__(self, parent, *args, **kwargs):
super(MyFrame, self).__init__(parent, *args, **kwargs)
# Attributes
self.mypanel = SlideShowPanel(self)
self.mypanel.SetBackgroundColour(wx.WHITE)
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, title="wx.DC",size = [1000, 900])
self.SetTopWindow(self.frame)
self.frame.Show()
return True
if __name__ == "__main__":
app = MyApp(False)
app.MainLoop()
运行结果:
示例分析
SlideShowPanel继承于PyPanel,以至于能够访问它的一些虚方法。DoGetBestSize方法是虚重写。绑定绘制处理器给EVT_PAINT事件。鼠标左击向前预览,鼠标右击向后预览。Refresh方法导致系统发出EVT_PAINT事件。
OnPaint方法,首先实例一个PaintDC对象,PaintDC提供了DC的接口,允许绘制外观在屏幕上。GetClientRect获取控件的客户端区域。DC的DrawBitmap方法绘制图片对象到屏幕上,DC的DrawLabel方法绘制文本。