前面系列文章中,我们介绍了wxPython提供各种的各种控件,在一般情况下可以满足我们开发应用的各种需求。但是在一些情况下,比如对按钮的美化,一个可以显示CPU占用率的控件等等。这首就需要自定义的控件,才能满足要求。
自定义控件可以通过两种方式创建:一种是通过修改或增强现有控件,另一种是我们使用GDI直接创建。下面我们将分别演示采用这两种方式如何在wxPython中实现一个自定义控件。
一、简单的超链接控件
创建一个超链接控件,我们基于
wx.lib.stattext.GenStaticText 控件来构建它,控件的字体用蓝色显示。点击该控件时将调用默认浏览器打开指定的网址。
import wx
from wx.lib.stattext import GenStaticText
import webbrowser
class MyLink(GenStaticText):
def __init__(self, *args, **kw):
super(MyLink, self).__init__(*args, **kw)
self.font1 = wx.Font(11, wx.SWISS, wx.NORMAL, wx.BOLD, True, 'Verdana')
self.font2 = wx.Font(11, wx.SWISS, wx.NORMAL, wx.BOLD, False, 'Verdana')
self.SetFont(self.font2)
self.SetForegroundColour("#0000ff")
self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
self.Bind(wx.EVT_MOTION, self.OnMouseEvent)
def SetUrl(self, url):
self.url = url
def OnMouseEvent(self, e):
if e.Moving():
self.SetCursor(wx.Cursor(wx.CURSOR_HAND))
self.SetFont(self.font1)
elif e.LeftUp():
webbrowser.open_new(self.url)
else:
self.SetCursor(wx.NullCursor)
self.SetFont(self.font2)
e.Skip()
class SampleHyperlink(wx.Frame):
def __init__(self, *args, **kw):
super(SampleHyperlink, self).__init__(*args, **kw)
self.InitUi()
def InitUi(self):
self.SetTitle("实战wxPython: 自定义控件演示")
self.SetSize(400, 240)
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
st = GenStaticText(panel, label="连接到Web站点:")
st.SetFont(wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, "Verdana"))
hbox.Add(st, flag=wx.LEFT, border=20)
link_wid = MyLink(panel, label="bing")
link_wid.SetUrl("https://cn.bing.com")
hbox.Add(link_wid, flag=wx.LEFT, border=20)
vbox.Add(hbox, flag=wx.TOP, border=30)
panel.SetSizer(vbox)
self.Centre()
def main():
app = wx.App()
sample = SampleHyperlink(None)
sample.Show()
app.MainLoop()
if __name__ == "__main__":
main()
上面的例子中我们使用已有控件,没有绘制任何新的东西,做了一点修改,构建了一个超链接控件。
from wx.lib.stattext import GenStaticText
import webbrowser
导入我们需要的模块,webbrowser 是 python 的标准模块,使用它在默认浏览器中打开超链接。
self.SetFont(self.font2)
self.SetForegroundColour("#0000ff")
修改控件中字体和字体的颜色
if e.Moving():
self.SetCursor(wx.Cursor(wx.CURSOR_HAND))
self.SetFont(self.font1)
如果鼠标移到链接上方时,我们显示文本下划线,并将鼠标设置为手型。
elif e.LeftUp():
webbrowser.open_new(self.url)
如果点击链接,将在默认浏览器打开超链接控件所关联的网址。
图1:自定义超链接演示
二、一个显示资源使用率的控件
在一些应用中,会需要监测系统资源,温度,内存消耗,CPU使用率等等。如果仅单纯地使用文字(比如CPU 60%),则显得不那么直观,如果使用一定定制化的控件,以直观的图形方式来显示,则会更加一目了然。
import wx
class MyCPU(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, size=(80, 110))
self.parent = parent
self.SetBackgroundColour("black")
self.Bind(wx.EVT_PAINT, self.OnPaint)
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.SetDeviceOrigin(0, 100)
dc.SetAxisOrientation(True, True)
pos = self.parent.GetParent().GetParent().sel
rect = pos / 5
for i in range(1,21):
if i>rect:
dc.SetBrush(wx.Brush("#075100"))
dc.DrawRectangle(10, i * 4, 30, 5)
dc.DrawRectangle(41, i * 4, 30, 5)
else:
dc.SetBrush(wx.Brush("#36ff27"))
dc.DrawRectangle(10, i * 4, 30, 5)
dc.DrawRectangle(41, i * 4, 30, 5)
class SampleMyCPU(wx.Frame):
def __init__(self, *args, **kw):
super(SampleMyCPU, self).__init__(*args, **kw)
self.InitUi()
def InitUi(self):
self.SetTitle("实战wxPython: 自定义控件演示")
self.SetSize(400, 240)
self.sel = 0
panel = wx.Panel(self)
centerPanel = wx.Panel(panel)
self.cpu = MyCPU(centerPanel)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.slider = wx.Slider(panel, value=self.sel, maxValue=100, size=(-1,100), style=wx.VERTICAL|wx.SL_INVERSE)
self.slider.SetFocus()
hbox.Add(centerPanel, 0, wx.LEFT|wx.TOP, 20)
hbox.Add(self.slider, 0, wx.LEFT|wx.TOP, 30)
self.Bind(wx.EVT_SCROLL, self.OnScroll)
panel.SetSizer(hbox)
self.Centre()
def OnScroll(self, e):
self.sel = e.GetInt()
self.cpu.Refresh()
def main():
app = wx.App()
sample = SampleMyCPU(None)
sample.Show()
app.MainLoop()
if __name__ == "__main__":
main()
上面的例子里,我们创建一个控件,它继承自wx.Panel。在其上绘制了一些矩形,矩形的颜色取决于滑块控件的值,可以为深绿或者亮绿。
dc.SetDeviceOrigin(0, 100)
dc.SetAxisOrientation(True, True)
上面的例子里,我们创建一个控件,它继承自wx.Panel。在其上绘制了一些矩形,矩形的颜色取决于滑块控件的值,可以为深绿或者亮绿。
dc.SetDeviceOrigin(0, 100)
dc.SetAxisOrientation(True, True)
将坐标系设置为笛卡尔坐标系,让绘制更加直观。
pos = self.parent.GetParent().GetParent().sel
rect = pos / 5
获取sizer的值。一列有20个小矩形,滑块的变化范围为0到100 。rect参数保存将滑块值转变成需要用亮绿色绘制的矩形数目。
for i in range(1,21):
if i>rect:
dc.SetBrush(wx.Brush("#075100"))
dc.DrawRectangle(10, i * 4, 30, 5)
dc.DrawRectangle(41, i * 4, 30, 5)
else:
dc.SetBrush(wx.Brush("#36ff27"))
dc.DrawRectangle(10, i * 4, 30, 5)
dc.DrawRectangle(41, i * 4, 30, 5)
这里我们绘制了40个矩形,每列20个。如果矩形数目大于rect的值,用暗绿色绘制,否则用亮绿色绘制。
图2:自定义控件之CPU占用率演示
三、本文知识点
- 什么时候需要自定义控件。
- 创建自定义控件的两种方式。
- 使用EVT_PAINT事件。
前一篇:实战wxPython:050 - 动态添加和删除控件