如何解决如何从TextCtrl派生wxPython自定义控件
对我来说,wxPython wx.lib.masked.NumCtrl
有一些非常奇怪的怪癖。因此,我想创建自己的 NumberCtrl
派生自 wx.TextCtrl
,它只是跳过非数字输入。旁注:缺点是 ctrl.SetValue()
只接受字符串。
由于调用超类构造函数中的参数(或参数数量)不匹配,以下类失败。
class NumberCtrl(wx.TextCtrl):
def __init__(self,parent,id=wx.ID_ANY,label=None):
wx.TextCtrl.__init__(self,parent=parent,id=id,label=label)
self.Bind(wx.EVT_CHAR,lambda event: self.force_numeric(event))
def force_numeric(self,event):
raw_value = self.GetValue().strip()
keycode = event.GetKeyCode()
if keycode < 255:
if chr(keycode).isdigit() or chr(keycode) == '.' and '.' not in raw_value:
event.Skip()
但是,仅使用基本参数是可行的。
def __init__(self,parent):
wx.TextCtrl.__init__(self,parent=parent)
我不明白这里发生了什么。
解决方法
尝试简单地使用 TextCtrl 的显式初始化值。
我已将 label
替换为 value
,并在事件验证中添加了允许“退格”(我的设置中的键码 8)。
编辑将 value
的默认值更改为字符串 not None
class NumberCtrl(wx.TextCtrl):
def __init__(self,parent,id=wx.ID_ANY,value="",pos=wx.DefaultPosition,size=wx.DefaultSize,style=0,validator=wx.DefaultValidator,name=wx.TextCtrlNameStr):
wx.TextCtrl.__init__(self,parent=parent,id=id,value=value)
self.Bind(wx.EVT_CHAR,lambda event: self.force_numeric(event))
def force_numeric(self,event):
raw_value = self.GetValue().strip()
keycode = event.GetKeyCode()
print(keycode)
if keycode < 255:
if chr(keycode).isdigit() or keycode == 8 or chr(keycode) == '.' and '.' not in raw_value:
event.Skip()
编辑 - 工作代码(在 Linux wxpython 4.1.1 上)
import wx
class MyPanel(wx.Panel):
def __init__(self,flags=0):
super().__init__(parent)
# Panel 1 (contains button that takes up entire panel)
self.pnl1 = wx.Panel(self)
self.btn1 = wx.Button(self.pnl1,label="Panel2",size=(250,75))
self.btn1.Bind(wx.EVT_BUTTON,self.show_pnl2)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox1.Add(self.btn1)
self.pnl1.SetSizer(vbox1)
# Panel 2 (contains button that takes up entire panel)
self.pnl2 = wx.Panel(self)
self.btn2 = wx.Button(self.pnl2,label="Panel1",size=(75,250))
self.num = NumberCtrl(self.pnl2,wx.ID_ANY,value="1",250))
self.btn2.Bind(wx.EVT_BUTTON,self.show_pnl1)
vbox2 = wx.BoxSizer(wx.VERTICAL)
vbox2.Add(self.btn2)
vbox2.Add(self.num)
self.pnl2.SetSizer(vbox2)
# Main panel (displays either Panel 1 or Panel 2)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.pnl1,flag=flags)
vbox.Add(self.pnl2,flag=flags)
self.SetSizer(vbox)
# Start off with panel 1 showing and panel 2 hidden
self.Show()
self.pnl1.Hide()
def show_pnl1(self,event):
self.pnl2.Hide()
self.pnl1.Show()
self.Layout()
self.Fit()
def show_pnl2(self,event):
self.pnl1.Hide()
self.pnl2.Show()
self.Layout()
self.Fit()
class NumberCtrl(wx.TextCtrl):
def __init__(self,event):
raw_value = self.GetValue().strip()
keycode = event.GetKeyCode()
print(keycode)
if keycode < 255:
if chr(keycode).isdigit() or keycode == 8 or chr(keycode) == '.' and '.' not in raw_value:
event.Skip()
class PanelSwitchExample(wx.Frame):
"""Represents application window that includes switchable panel"""
def __init__(self,flags=0):
super().__init__(None)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(MyPanel(self,flags))
self.SetSizer(vbox)
self.Show()
if __name__ == "__main__":
app = wx.App()
PanelSwitchExample()
app.MainLoop()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。