wxPython: 使用Show()和Hide()

1 投票
1 回答
3929 浏览
提问于 2025-04-17 05:26

我正在做一个简单的程序,用来收集和检查用户输入的信息。除了在用户输入不符合要求时显示一个提示框外,我还想在输入框的右边加一个提示,告诉用户需要输入什么类型的数据。为此,我创建了一个单行的FlexGridSizer,里面包含了以下内容:

[(wx.StaticText, "姓名"), (wx.TextCtrl, "在这里输入用户信息"), (wx.StaticText, "输入提示")]

在程序初始化时,“输入提示”这个部分是隐藏的。如果用户在输入框里什么都没输入,然后点击确认按钮,我希望能发生三件事情:

  1. 输入框的颜色改变,以提醒用户有问题
  2. 第三个部分“输入提示”变得可见
  3. 对话框会自动调整大小,以适应现在可见的部分

到目前为止,我只实现了第一点,正在寻找帮助来完成第二点和第三点。


import wx


class Not_Empty(wx.PyValidator):

    def __init__(self):
        wx.PyValidator.__init__(self)

    def Clone(self):

        return Not_Empty()

    ################################################################################
    def Validate(self, win):
        """"""
        evt_location = self.GetWindow()
        val = evt_location.GetValue()

        if val == "":
            evt_location.SetBackgroundColour(wx.Color(250,200,230))
            MyDialog().nameWarning_ST.Show(True)
            return False

        else:
            return True
    ################################################################################

    def TransferToWindow(self):
        return True

    def TransferFromWindow(self):
        return True

class MyDialog(wx.Dialog):
    def __init__(self):
        wx.Dialog.__init__(self, parent=None, id=-1, title="Getting Input", style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)


        # Create field labels
        name = wx.StaticText(self, -1, "Name")

        # Create user-input widgets
        name_TC = wx.TextCtrl(self, validator=Not_Empty())

        # Create and hide warning boxes
        self.nameWarning_ST = wx.StaticText(self, label="Field cannot be left empty", name="emptyAlert")

        # to see what I want the dialog to look like AFTER the user has entered an
        # empty string change 'False' to 'True' in the line below.
        self.nameWarning_ST.Show(False)

        # Create accept/cancel buttons
        btns = self.CreateButtonSizer(flags=wx.OK|wx.CANCEL)

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)

        fgs = wx.FlexGridSizer(cols = 3, rows = 1)

        fgs.AddMany([(name, -1, wx.ALL, 5), (name_TC, -1, wx.ALL, 5), (self.nameWarning_ST, -1, wx.ALL, 5)])

        self.mainSizer.AddMany([(fgs, 1, wx.ALL, 0), (btns, 1, wx.ALL|wx.EXPAND, 5)])

        self.SetSizer(self.mainSizer)       
        self.mainSizer.Fit(self)

if __name__ == '__main__':

    app = wx.App() 
    dlg = MyDialog()
    dlg.Center()
    dlg.ShowModal()
    dlg.Destroy()

    app.MainLoop()

1 个回答

3

编辑:对于新的问题,我建议使用pubsub来解决。你可以在MyDialog类的初始化时设置一个监听器,然后在另一个类的Validate方法运行时向它发布一条消息。在你理论上会在MyDialog中创建的消息处理器里,你需要显示其他的控件,并在对话框上调用Layout()。这样应该会让它适当地调整大小。

你可以在这里阅读关于pubsub的教程:http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/

以下内容是针对原始问题的:

你的Validate方法从来没有被触发,所以我把你的Validate和OnChar方法重新排列成了下面的样子:

import string
def Validate(self, win):
    """
    Enter your code here...
    """
    return True


def OnChar(self, event):
    txtObj = event.GetEventObject()
    txt = txtObj.GetValue()
    if txt == "": txt = '0'
    key = chr(event.GetKeyCode())

    if key in string.digits:
        if int(txt+str(key)) < 150:
            event.Skip()
        else:
            msg = "You have entered an age greater than 150!"
            wx.MessageBox(msg, "Improbable entry", style=wx.OK|wx.ICON_ERROR)

            # PROBLEM ARISES HERE
            # ===================
            MyDialog().ageWarning_ST.Show()
            MyDialog().mainSizer.Fit(MyDialog())

            return False

    key = event.GetKeyCode()
    if key in(wx.WXK_RETURN, wx.WXK_DELETE, wx.WXK_BACK):
        event.Skip()

    elif (chr(key)).isdigit():
        event.Skip()
    else:
        return

另外,我还导入了字符串模块,这样会让事情变得简单一些。代码可能还需要一些整理,但在我的机器上是可以运行的。

撰写回答