最开始跟着B站的视频学的,看不太懂。
然后跟着学习的网站(本文相当于学习这篇博客中的小拓展与思考,学习wxpython的话还是得看这篇博客为主):wxPython入门中文版 (Getting Started with wxPython)-CSDN博客
做点笔记,记录学习过程中的疑问:
1.wx.Button, wx.StaticText, wx.TextCtrl 和 wx.ComboBox的作用:
-
wx.Button:
wx.Button
用于创建一个按钮控件。用户可以点击按钮来触发事件,例如提交表单或调用一个函数。- 按钮控件通常用于接收用户的操作指令。
-
wx.StaticText:
wx.StaticText
用于显示不可编辑的文本,例如标签或提示信息。- 与文本编辑框不同,静态文本控件不支持用户输入。
-
wx.TextCtrl:
wx.TextCtrl
是一个文本编辑框,允许用户输入和编辑文本。- 它可以是单行或多行(通过设置
wx.TE_MULTILINE
样式)。 wx.TextCtrl
可用于接收用户输入的文本数据。
-
wx.ComboBox:
wx.ComboBox
是一个下拉列表控件,结合了文本输入和选择列表的功能。- 用户可以从列表中选择一个选项,或者在允许编辑的情况下输入文本。
- 它适用于提供有限选项集供用户选择。
以下是如何在 wxPython
应用程序中使用这些组件的简单示例:在这个示例中,我们创建了一个包含静态文本、文本输入框、下拉列表和按钮的简单窗口。每个控件都放置在窗口的面板上,并设置了合适的位置。按钮绑定了一个事件处理函数 on_button_click
,当按钮被点击时,将打印一条消息。
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super(MyFrame, self).__init__(parent, title=title, size=(350, 250))
# 创建一个面板,以便在窗口中加入其他控件
panel = wx.Panel(self)
# 创建静态文本
static_text = wx.StaticText(panel, label="请输入文本:", pos=(20, 20))
# 创建文本输入框
text_ctrl = wx.TextCtrl(panel, pos=(100, 20))
# 创建下拉列表
combo_box = wx.ComboBox(panel, pos=(100, 50), choices=["选项1", "选项2", "选项3"])
# 创建按钮
button = wx.Button(panel, label="提交", pos=(20, 100))
# 绑定按钮点击事件
button.Bind(wx.EVT_BUTTON, self.on_button_click)
def on_button_click(self, event):
print("按钮被点击了!")
app = wx.App(False)
frame = MyFrame(None, "wxPython 控件示例")
frame.Show(True)
app.MainLoop()
2.wx.Panel的作用
wx.Panel
是 wxPython
中的一个类,它提供了一个容器,用于在其中放置其他控件,如按钮、文本框、标签等。使用 wx.Panel
可以创建复杂的用户界面布局,并且可以作为其他控件的父级容器。
以下是 wx.Panel
的一些关键特性和用法:
-
容器:
wx.Panel
可以包含其他GUI控件,如wx.Button
、wx.StaticText
、wx.TextCtrl
等。 -
布局管理:
wx.Panel
可以利用wxPython
的布局管理器(如wx.BoxSizer
、wx.GridSizer
等)来自动管理其子控件的布局。 -
样式和颜色:可以为
wx.Panel
设置背景颜色、边框样式等属性。 -
事件处理:
wx.Panel
可以处理各种事件,如鼠标点击、键盘输入等。 -
绘图:可以在
wx.Panel
上进行自定义绘图,通过重写其OnPaint
事件处理函数。 -
子控件管理:
wx.Panel
提供了方法来添加、移除和查询子控件。
使用示例:
在这个示例中,我们创建了一个 wx.Frame
和一个 wx.Panel
。然后在 wx.Panel
中添加了一个 wx.Button
,并使用 wx.BoxSizer
来管理按钮的布局。我们还设置了 wx.Panel
的背景颜色,以区分它与主窗口的边界。
使用 wx.Panel
是组织和管理复杂GUI应用程序中控件的一种有效方式,它提供了灵活性和强大的布局选项。
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super(MyFrame, self).__init__(parent, title=title, size=(350, 250))
self.panel = wx.Panel(self) # 创建 Panel 实例
self.panel.SetBackgroundColour(wx.Colour(225, 236, 255)) # 设置背景颜色
# 在 Panel 中创建其他控件
self.button = wx.Button(self.panel, label="点击我", pos=(50, 50))
self.button.Bind(wx.EVT_BUTTON, self.on_button_click)
# 使用布局管理器
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.button, 0, wx.ALL, 10)
self.panel.SetSizer(sizer)
def on_button_click(self, event):
print("按钮被点击了!")
app = wx.App(False)
frame = MyFrame(None, "wxPython Panel 示例")
frame.Show(True)
app.MainLoop()
3.menuExit=filemenu.Append(wx.ID_EXIT, "&Exit", "Terminate the program") menuExit = filemenu.Append(wx.ID_EXIT, "E&xit", " Terminate the program") 有什么区别,&的位置有什么影响
在 wxPython
中,当你调用 wx.Menu.Append()
方法来添加一个菜单项时,可以指定一些特殊的字符来影响菜单项的显示和行为:
-
"&Exit":在这个字符串中,
&
符号用于指定一个快捷键(也称为加速键或热键)。在这里,&E
表示 "E" 键是这个菜单项的快捷键。在大多数操作系统中,用户可以通过按下Alt
键加上这个字符(在这个例子中是 "E")来快速选择这个菜单项。 -
"E&xit":在这个字符串中,
&
符号放在了 "Exit" 的第一个字母前面,这意味着 "X" 将成为快捷键。用户将使用Alt+X
来激活这个菜单项。 -
" Terminate the program":这是菜单项的描述,它是一个字符串,提供了关于菜单项功能的额外信息。在大多数菜单实现中,这个描述不会直接显示在菜单上,但可以在工具提示或菜单项的辅助访问信息中使用。
-
空格:在 "E&xit" 中,
&
后面的空格是必需的,以确保菜单项在显示时 "X" 字母下面能够正确地出现一个下划线,这是图形用户界面中指示快捷键的标准方式。 -
wx.ID_EXIT:这是一个预定义的标识符,通常用于表示退出程序的标准菜单项。使用预定义的ID可以让菜单项在不同的应用程序中保持一致的行为,并且可以利用操作系统的快捷键(如果存在)。
总结来说,&
的位置决定了哪个字母将成为菜单项的快捷键,这对于用户快速访问菜单功能非常重要。如果 &
后面紧跟的字符是空格或不在可见字符范围内,那么通常不会显示下划线,且不会有快捷键效果。
在 wxPython
的某些版本或配置中,如果 &
后面没有紧跟字母,或者紧跟的是特殊字符,可能不会显示下划线,但这个字符仍然可以作为快捷键使用。因此,正确的使用 &
可以提高菜单的可访问性和用户体验。
4.状态栏跟菜单栏在哪儿?
点击运行出来的窗口里的File,就会出现菜单栏,鼠标放在具体菜单项目的时候,相关的状态信息会在frame窗口的最下面显示。(我最开始也纳闷儿我菜单栏跟状态栏呢。。。)
5.验证器validation的示例
wx.Validator
在 wxPython
中是用来提供对用户输入进行验证的机制。简单来说,它是一种确保用户在文本控件(如 wx.TextCtrl
)中输入的数据符合特定要求的方法。以下是对 wx.Validator
的一些关键点的解释,以及如何使用它们:
-
目的:
wx.Validator
的主要目的是确保用户输入的数据是有效的,比如检查输入是否为数字、电子邮件地址、特定格式的字符串等。 -
使用场景:当你创建需要用户输入的对话框或输入控件时,可以使用
wx.Validator
。 -
自定义验证器:要使用
wx.Validator
,通常需要定义一个wx.Validator
的子类。这个子类可以是wx.TextValidator
(专门用于文本输入的验证器)或者其他自定义的验证器。 -
关联控件:创建了验证器对象后,你需要将它与特定的输入控件关联起来。这可以通过调用控件的
SetValidator()
方法来实现。 -
处理事件:
wx.Validator
还可以截取控件内发生的事件,如键盘敲击事件,并根据这些事件执行特定的逻辑。 -
数据转储:
wx.Validator
还可以用来从控件中提取数据,并将它们转换成适当的格式。
示例:这个示例展示了如何使用 wxPython
创建一个简单的应用程序,其中包含一个文本输入框,该输入框通过自定义验证器限制只能输入文字。
import wx
class NumericTextValidator(wx.Validator):
def __init__(self):
super(NumericTextValidator, self).__init__()
self.Bind(wx.EVT_CHAR, self.OnChar)
def Clone(self):
# 返回当前验证器的一个副本
return NumericTextValidator()
def Validate(self, parent):
# 验证控件内容
return True
def TransferToWindow(self):
# 将验证器中的数据传输到控件
return True
def TransferFromWindow(self):
# 从控件传输数据到验证器
return True
def OnChar(self, event):
# 检查按键事件,只允许数字
key = event.GetKeyCode()
if key < wx.WXK_SPACE or key == wx.WXK_DELETE:
event.Skip() # 允许空格、删除等特殊键
elif not wx.GetKeyState(wx.MOD_CONTROL) and chr(key).isdigit():
event.Skip() # 允许数字键
else:
event.Veto() # 阻止其他字符
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super(MyFrame, self).__init__(parent, title=title, size=(300, 200))
panel = wx.Panel(self)
text_ctrl = wx.TextCtrl(panel, pos=(20, 20), size=(150, -1))
validator = NumericTextValidator()
text_ctrl.SetValidator(validator)
# 其他代码...
app = wx.App(False)
frame = MyFrame(None, "wxPython Validator Example")
frame.Show(True)
app.MainLoop()
自留能跑成功的示例代码:
这个布局死板些,但是好理解一点
import wx
class ExamplePanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.quote = wx.StaticText(self, label='Your quote:', pos=(20, 30))
# 这个多行的文本框只是用来记录并显示events,不要纠结之
self.logger = wx.TextCtrl(self, pos=(500,20), size=(200,150),
style=wx.TE_MULTILINE | wx.TE_READONLY)
# 一个按钮
self.button = wx.Button(self, label='Save', pos=(300, 300))
self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)
# 仅有1行的编辑控件
self.lblname = wx.StaticText(self, label='Your name:', pos=(20, 60))
self.editname = wx.TextCtrl(self, value='Enter here your name:',
pos=(150, 60), size=(140, -1))
self.Bind(wx.EVT_TEXT, self.EvtText, self.editname)
self.Bind(wx.EVT_CHAR, self.EvtChar, self.editname)
# 一个ComboBox控件(下拉菜单)
self.sampleList = ['friends', 'advertising', 'web search',
'Yellow Pages']
self.lblhear = wx.StaticText(self, label="How did you hear from us ?",
pos=(20, 90))
self.edithear = wx.ComboBox(self, pos=(190, 90), size=(95, -1),
choices=self.sampleList,
style=wx.CB_DROPDOWN)
self.Bind(wx.EVT_COMBOBOX, self.EvtComboBox, self.edithear)
# 注意ComboBox也绑定了EVT_TEXT事件
self.Bind(wx.EVT_TEXT, self.EvtText, self.edithear)
# 复选框
self.insure = wx.CheckBox(self, label="Do you want Insured Shipment ?",
pos=(20,180))
self.Bind(wx.EVT_CHECKBOX, self.EvtCheckBox, self.insure)
# 单选框
radioList = ['blue', 'red', 'yellow', 'orange', 'green', 'purple',
'navy blue', 'black', 'gray']
self.rb = wx.RadioBox(self, label="What color would you like ?",
pos=(20, 210), choices=radioList,
style=wx.RA_SPECIFY_COLS)
self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox, self.rb)
def OnClick(self, event):
self.logger.AppendText('Button Clicked\n')
def EvtText(self, event):
self.logger.AppendText('Text Changed: %s\n' % event.GetString())
def EvtChar(self, event):
self.logger.AppendText('EvtChar: %d\n' % event.GetKeyCode())
event.Skip()
def EvtComboBox(self, event):
self.logger.AppendText('EvtComboBox: %s\n' % event.GetString())
def EvtCheckBox(self, event):
self.logger.AppendText('EvtCheckBox: %d\n' % event.Checked())
def EvtRadioBox(self, event):
self.logger.AppendText('EvtRadioBox: %d\n' % event.GetInt())
app = wx.App(False)
frame = wx.Frame(None, title="Example", size=(750, 400))
panel = ExamplePanel(frame)
frame.Show()
app.MainLoop()
这个布局好像是要灵活一点,用了wxGridBagSizer,但是感觉没有上面那个示例好理解
# -*- coding: utf-8 -*-
import wx
class ExamplePanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# 创建一些Sizer
mainSizer = wx.BoxSizer(wx.VERTICAL)
grid = wx.GridBagSizer(hgap=5, vgap=5) # 行和列的间距是5像素
hSizer = wx.BoxSizer(wx.HORIZONTAL)
self.quote = wx.StaticText(self, label='Your quote:', pos=(20, 30))
grid.Add(self.quote, pos=(0,0)) # 加入GridBagSizer
self.logger = wx.TextCtrl(self, pos=(300,20), size=(200,300), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.button = wx.Button(self, label='Save', pos=(200, 325))
self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)
self.lblname = wx.StaticText(self, label='Your name:', pos=(20, 60))
grid.Add(self.lblname, pos=(1,0))
self.editname = wx.TextCtrl(self, value='Enter here your name:', pos=(150, 60), size=(140, -1))
grid.Add(self.editname, pos=(1,1))
self.Bind(wx.EVT_TEXT, self.EvtText, self.editname)
self.Bind(wx.EVT_CHAR, self.EvtChar, self.editname)
# 向GridBagSizer中填充空白的空间
grid.Add((10, 40), pos=(2,0))
self.sampleList = ['friends', 'advertising', 'web search', 'Yellow Pages']
self.lblhear = wx.StaticText(self, label="How did you hear from us ?", pos=(20, 90))
grid.Add(self.lblhear, pos=(3,0))
self.edithear = wx.ComboBox(self, pos=(150, 90), size=(95, -1), choices=self.sampleList, style=wx.CB_DROPDOWN)
grid.Add(self.edithear, pos=(3,1))
self.Bind(wx.EVT_COMBOBOX, self.EvtComboBox, self.edithear)
self.Bind(wx.EVT_TEXT, self.EvtText, self.edithear)
self.insure = wx.CheckBox(self, label="Do you want Insured Shipment ?", pos=(20,180))
# 加入Sizer的同时,设置对齐方式和边距
grid.Add(self.insure, pos=(4,0), span=(1,2), flag=wx.BOTTOM, border=5)
self.Bind(wx.EVT_CHECKBOX, self.EvtCheckBox, self.insure)
radioList = ['blue', 'red', 'yellow', 'orange', 'green', 'purple', 'navy blue', 'black', 'gray']
self.rb = wx.RadioBox(self, label="What color would you like ?", pos=(20, 210), choices=radioList,
majorDimension=3, style=wx.RA_SPECIFY_COLS)
grid.Add(self.rb, pos=(5,0), span=(1,2)) # 合并了1行2列的单元格
self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox, self.rb)
hSizer.Add(grid, 0, wx.ALL, 5)
hSizer.Add(self.logger)
mainSizer.Add(hSizer, 0, wx.ALL, 5)
mainSizer.Add(self.button, 0, wx.CENTER)
# 可以把SetSizer()和sizer.Fit()合并成一条SetSizerAndFit()语句
self.SetSizerAndFit(mainSizer)
def OnClick(self, event):
self.logger.AppendText('Click on object with Id %d\n' % event.GetId())
def EvtText(self, event):
self.logger.AppendText('EvtText: %s\n' % event.GetString())
def EvtChar(self, event):
self.logger.AppendText('EvtChar: %d\n' % event.GetKeyCode())
event.Skip()
def EvtComboBox(self, event):
self.logger.AppendText('EvtComboBox: %s\n' % event.GetString())
def EvtCheckBox(self, event):
self.logger.AppendText('EvtCheckBox: %d\n' % event.Checked())
def EvtRadioBox(self, event):
self.logger.AppendText('EvtRadioBox: %d\n' % event.GetInt())
app = wx.App(False)
frame = wx.Frame(None, title="Demo with Notebook")
nb = wx.Notebook(frame)
nb.AddPage(ExamplePanel(nb), "Absolute Positioning")
nb.AddPage(ExamplePanel(nb), "Page Two")
nb.AddPage(ExamplePanel(nb), "Page Three")
frame.Show()
app.MainLoop()