wxpython自定义控件_wxPython 教程(十三) 自定义控件

wxpython自定义控件_wxPython 教程(十三) 自定义控件本节讲述wxPython自定义控件。GUIToolkits会提供多数常用的部件,比如按钮、文本控件、滚动条、滑块等等。wxPython也会提供很多控件,但若需要更定制化的控件还是需要开发者自己编写。自定义控件通过两种方式创建:一种是通过修改或增强现有控件,另一种是我们从零开始直接创建。超链接控件第一个例子是创建一个超链接控件,我们基于wx.lib.stattext.GenStatic…

大家好,又见面了,我是你们的朋友全栈君。

本节讲述 wxPython 自定义控件 。GUI Toolkits 会提供多数常用的部件,比如按钮、文本控件、滚动条、滑块等等。wxPython 也会提供很多控件,但若需要更定制化的控件还是需要开发者自己编写。

自定义控件通过两种方式创建:一种是通过修改或增强现有控件,另一种是我们从零开始直接创建。

超链接控件

第一个例子是创建一个超链接控件,我们基于 wx.lib.stattext.GenStaticText 控件来构建它。

#!/usr/bin/python

import wx

from wx.lib.stattext import GenStaticText

import webbrowser

class Link(GenStaticText):

def __init__(self, *args, **kw):

super(Link, self).__init__(*args, **kw)

self.font1 = wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD, True, ‘Verdana’)

self.font2 = wx.Font(9, 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.StockCursor(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 Example(wx.Frame):

def __init__(self, *args, **kw):

super(Example, self).__init__(*args, **kw)

self.InitUI()

def InitUI(self):

panel = wx.Panel(self)

lnk = Link(panel, label=’ZetCode’, pos=(10, 60))

lnk.SetUrl(‘http://www.zetcode.com’)

motto = GenStaticText(panel, label=’Knowledge only matters’, pos=(10, 30))

motto.SetFont(wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD, False, ‘Verdana’))

self.SetSize((220, 150))

self.SetTitle(‘A Hyperlink’)

self.Centre()

self.Show(True)

def main():

ex = wx.App()

Example(None)

ex.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.StockCursor(wx.CURSOR_HAND))

self.SetFont(self.font1)

如果鼠标移到链接上方时,我们显示文本下划线,并将鼠标设置为手型。

elif e.LeftUp():

webbrowser.open_new(self.url)

如果点击链接,我们在默认浏览器打开它。

wxpython自定义控件_wxPython 教程(十三) 自定义控件

烧录控件

这个例子中,我们将从头创建一个控件。我们将在窗口的底部放置一个 wx.Panel,手动绘制整个控件。如果你之前烧录过 CD 或者 DVD,你应该见过类似控件。

为了避免 Windows 系统中的闪烁,我们需要使用双重缓冲(double buffering)。

#!/usr/bin/python

# burning.py

import wx

class Widget(wx.Panel):

def __init__(self, parent, id):

wx.Panel.__init__(self, parent, id, size=(-1, 30), style=wx.SUNKEN_BORDER)

self.parent = parent

self.font = wx.Font(9, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,

wx.FONTWEIGHT_NORMAL, False, ‘Courier 10 Pitch’)

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

self.Bind(wx.EVT_SIZE, self.OnSize)

def OnPaint(self, event):

num = range(75, 700, 75)

dc = wx.PaintDC(self)

dc.SetFont(self.font)

w, h = self.GetSize()

self.cw = self.parent.GetParent().cw

step = int(round(w / 10.0))

j = 0

till = (w / 750.0) * self.cw

full = (w / 750.0) * 700

if self.cw >= 700:

dc.SetPen(wx.Pen(‘#FFFFB8’))

dc.SetBrush(wx.Brush(‘#FFFFB8’))

dc.DrawRectangle(0, 0, full, 30)

dc.SetPen(wx.Pen(‘#ffafaf’))

dc.SetBrush(wx.Brush(‘#ffafaf’))

dc.DrawRectangle(full, 0, till-full, 30)

else:

dc.SetPen(wx.Pen(‘#FFFFB8’))

dc.SetBrush(wx.Brush(‘#FFFFB8’))

dc.DrawRectangle(0, 0, till, 30)

dc.SetPen(wx.Pen(‘#5C5142’))

for i in range(step, 10*step, step):

dc.DrawLine(i, 0, i, 6)

width, height = dc.GetTextExtent(str(num[j]))

dc.DrawText(str(num[j]), i-width/2, 8)

j = j + 1

def OnSize(self, event):

self.Refresh()

class Burning(wx.Frame):

def __init__(self, parent, id, title):

wx.Frame.__init__(self, parent, id, title, size=(330, 200))

self.cw = 75

panel = wx.Panel(self, -1)

CenterPanel = wx.Panel(panel, -1)

self.sld = wx.Slider(CenterPanel, -1, 75, 0, 750, (-1, -1),

(150, -1), wx.SL_LABELS)

vbox = wx.BoxSizer(wx.VERTICAL)

hbox = wx.BoxSizer(wx.HORIZONTAL)

hbox2 = wx.BoxSizer(wx.HORIZONTAL)

hbox3 = wx.BoxSizer(wx.HORIZONTAL)

self.wid = Widget(panel, -1)

hbox.Add(self.wid, 1, wx.EXPAND)

hbox2.Add(CenterPanel, 1, wx.EXPAND)

hbox3.Add(self.sld, 0, wx.TOP, 35)

CenterPanel.SetSizer(hbox3)

vbox.Add(hbox2, 1, wx.EXPAND)

vbox.Add(hbox, 0, wx.EXPAND)

self.Bind(wx.EVT_SCROLL, self.OnScroll)

panel.SetSizer(vbox)

self.sld.SetFocus()

self.Centre()

self.Show(True)

def OnScroll(self, event):

self.cw = self.sld.GetValue()

self.wid.Refresh()

app = wx.App()

Burning(None, -1, ‘Burning widget’)

app.MainLoop()

所有重要的代码都在 Widget 类的 OnPaint() 函数内。这个控件像我们展示了媒介(CD/DVD)的总容量和剩余的空间,通过滑块空间来控制。最小值为 0,最大值为 750。如果值到了 700,我们将颜色编程红色,这提示过度烧录。

w, h = self.GetSize()

self.cw = self.parent.GetParent().cw

till = (w / 750.0) * self.cw

full = (w / 750.0) * 700

我们动态的绘制空间。窗口越大,烧录控件越大,反之亦然。这就是为什么我们要先计算 wx.Panel 的尺寸的原因。till 参数决定了要绘制的总大小。这个参数来自于滑块空间,它是整个区域的一部分。full 参数决定了我们要使用红色绘制的那个节点值。注意到,我们使用了浮点数,这样可以达到更高的精度。

实际的绘制包括 3 步,我们绘制了黄/红 和 黄色矩阵。然后绘制竖线,这些竖线将控件划分为多个部分。最终,我们绘制数字,它提示媒介的容量。

def OnSize(self, event):

self.Refresh()

每次窗口大小改变时,我们刷新控件。

def OnScroll(self, event):

self.cw = self.sld.GetValue()

self.wid.Refresh()

当我们移动滑块控件的浮标时,我们得到实际的值,并将它存入 self.cw。这个值被用来绘制烧录控件,我们让控件刷新重绘。

wxpython自定义控件_wxPython 教程(十三) 自定义控件

CPU 控件

有一些应用会监测系统资源,温度、内存、CPU 消耗等等。如果单纯的使用文字来展示 CPU 54% 也许不那么令人映像深刻,定制化的控件可能会让应用更加的吸引人。下面例子中的控件是我们在系统应用中经常看见的。同上,为了避免 Windows 平台下的闪烁,我们使用双重缓冲。

#!/usr/bin/python

# cpu.py

import wx

class CPU(wx.Panel):

def __init__(self, parent, id):

wx.Panel.__init__(self, parent, id, size=(80, 110))

self.parent = parent

self.SetBackgroundColour(‘#000000’)

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

def OnPaint(self, event):

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 CPUWidget(wx.Frame):

def __init__(self, parent, id, title):

wx.Frame.__init__(self, parent, id, title, size=(190, 140))

self.sel = 0

panel = wx.Panel(self, -1)

centerPanel = wx.Panel(panel, -1)

self.cpu = CPU(centerPanel, -1)

hbox = wx.BoxSizer(wx.HORIZONTAL)

self.slider = wx.Slider(panel, -1, self.sel, 0, 100, (-1, -1), (25, 90),

wx.VERTICAL | wx.SL_LABELS | wx.SL_INVERSE)

self.slider.SetFocus()

hbox.Add(centerPanel, 0, wx.LEFT | wx.TOP, 20)

hbox.Add(self.slider, 0, wx.LEFT | wx.TOP, 23)

self.Bind(wx.EVT_SCROLL, self.OnScroll)

panel.SetSizer(hbox)

self.Centre()

self.Show(True)

def OnScroll(self, event):

self.sel = event.GetInt()

self.cpu.Refresh()

app = wx.App()

CPUWidget(None, -1, ‘cpu’)

app.MainLoop()

这个控件非常简单,我们创建了一个洪泽 panel。然后我们绘制了一些矩阵,矩阵的颜色取决于滑块控件的值,可以使深绿或者亮绿。

dc.SetDeviceOrigin(0, 100)

dc.SetAxisOrientation(True, True)

这里我们将坐标系改为笛卡尔坐标系,这将让绘制更加直观。

pos = self.parent.GetParent().GetParent().sel

rect = pos / 5

这里我们获取了 sizer 的值。一列有20个矩形,滑块有 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 个。如果矩形数目大于滑块值变换后的值,我们将它设置为暗绿色,否则用亮绿色。

wxpython自定义控件_wxPython 教程(十三) 自定义控件

本节中,我们创建了 wxPython 自定义控件 。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143668.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 阿里云的云服务器ECS和云虚拟主机有何区别?

    阿里云的云服务器ECS和云虚拟主机有何区别?阿里云的云服务器和云虚拟主机的共同点是都可以用来搭建网站,云服务器和云虚拟主机有很多相同之处,也有很多不同之处,云吞铺子从功能、价格、应用场景及优势几方面详细说明阿里云的云服务器和云虚拟主机之间的区别:一:云服务器ECS和虚拟主机的区别云服务器:虚拟的一台服务器,除了硬件摸不着外其他的功能和服务器一样,我们可以狭义的将云服务器ECS就看做一台物理服务器,ECS让用户拥有更多权限,用户可以在ECS上安装各种扩展插件实现各种功能,ECS需要有专业技术人员来维护。适合有技术实力、懂得服务器配置及维护的用户

    2022年6月25日
    37
  • zigbee 协议栈睡眠用法[通俗易懂]

    zigbee 协议栈睡眠用法[通俗易懂]大家都知道2430有3种睡眠模式,pm2模式比较省功耗而且可以被定时唤醒;pm3模式最省电但是只能被外部中断唤醒。开启睡眠功能很简单:首先确认/TexasInstruments/ZStack-1.4.3-1.2.1/Projects/zstack/Tools/CC2430DB目录下的f8wConfig.cfg文件中DRFD_RCVC_ALWAYS_ON定义为FALSE;然后在IAR的

    2022年5月22日
    33
  • mysql分区表详解_详解MySQL分区表「建议收藏」

    mysql分区表详解_详解MySQL分区表「建议收藏」前言:分区是一种表的设计模式,通俗地讲表分区是将一大表,根据条件分割成若干个小表。但是对于应用程序来讲,分区的表和没有分区的表是一样的。换句话来讲,分区对于应用是透明的,只是数据库对于数据的重新整理。本篇文章给大家带来的内容是关于MySQL中分区表的介绍及使用场景,有需要的朋友可以参考一下,希望对你有所帮助。1.分区的目的及分区类型MySQL在创建表的时候可以通过使用PARTITIONBY子句定…

    2022年4月30日
    66
  • 详解 & 0xff 的意义及作用

    详解 & 0xff 的意义及作用首先我们要都知道,&表示按位与,只有两个位同时为1,才能得到1,0x代表16进制数,0xff表示的数二进制11111111占一个字节.和其进行&操作的数,最低8位,不会发生变化.下面着重来说说&0xff都有哪些应用:1.只是为了取得低八位通常配合移位操作符>>使用例如:javasocket通信中基于长度的成帧方法中,如果发送的信息长度小于65535字节,长度信息的字节定义为两个字节长度。这时候将两个字节长的长度信息,以Big-Endian的

    2022年6月19日
    46
  • VMware虚拟机 桥接模式 无法上网 校园网「建议收藏」

    VMware虚拟机 桥接模式 无法上网 校园网「建议收藏」VMware桥接模式桥接模式就是将主机网卡与虚拟机虚拟的网卡利用虚拟网桥进行通信。在桥接的作用下,类似于把物理主机虚拟为一个交换机,所有桥接设置的虚拟机连接到这个交换机的一个接口上,物理主机也同样插在这个交换机当中,所以所有桥接下的网卡与网卡都是交换模式的,相互可以访问而不干扰。在桥接模式下,虚拟机ip地址需要与主机在同一个网段,如果需要联网,则网关与DNS需要与主机网卡一致。无法上网的检查步骤1.VMware中虚拟网络编辑器设置桥接网卡在“编辑”——“虚拟网络编辑器”里进.

    2022年6月7日
    121
  • java 各种架构图汇总

    java 各种架构图汇总java 各种架构图汇总

    2022年4月22日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号