wxPython:使用 Show() 和 Hide()

发布于 2024-12-13 09:23:54 字数 2574 浏览 2 评论 0原文

我正在开发一个收集和检查用户输入的简单程序。除了展示之外 如果用户提供的输入未通过检查,则会出现一个消息框,我还想添加一个提示 就在输入字段的右侧,告诉用户需要什么类型的数据。为了实现此目的,我创建了一个单行 FlexGridSizer,其中包含以下内容:

[(wx.StaticText, "名称"), (wx.TextCtrl, "用户在此输入"), (wx.StaticText, "输入指导")]

在初始化时,“输入指导”小部件被隐藏。如果用户未能在提供的字段中输入任何内容,然后单击“确定”按钮,我希望发生三件事

  1. 字段会更改颜色以提醒用户有问题
  2. “输入指导”小部件(上行中的第三个)变得
  3. 可见DialogBox 会自动调整大小以考虑现在可见的小部件

到目前为止,我只能使(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()

I'm working on a simple program that collects and checks user-input. In addition to displaying
a message box if the user-supplied input fails the checks, I'd also like to add a prompt
just to the right of the input field telling the user what type of data is required. To accomplish this I've created a single-row FlexGridSizer consisting of the following:

[(wx.StaticText, "Name"), (wx.TextCtrl, "user inputs here"), (wx.StaticText, "Input Guidance")]

On initialization the "Input Guidance" widget is hidden. If the user fails to enter anything in provided field, and then hits the OK button, I want three things to happen

  1. Field changes colour to alert user to a problem
  2. The "input guidance" widget (the third in the above row) becomes visible
  3. The DialogBox is automatically resized to take account of the now visible widget

So far I can only get (1) to work, and am looking for help with (2) and (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()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼眸里的那抹悲凉 2024-12-20 09:23:54

编辑:对于新问题,我将使用 pubsub 来解决这个问题。将侦听器放置在 MyDialog 类的 init 中,然后在另一个类中运行 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

另请注意,我导入了 string 模块以使事情变得更容易一些。该代码可能需要一些清理,但它在我的机器上运行。

EDIT: For the new question(s), I would use pubsub to solve this. Put a listener the init of the MyDialog class and then publish a message to it when the Validate method is run in the other class. In the message handler that you will theoretically create in MyDialog, you'll want Show your other widget and call Layout() on the dialog. That should cause it to resize appropriately.

You can read a tutorial on pubsub here: http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/

The following was for the original question:

Your Validate method doesn't ever fire, so I rearranged your Validate and OnChar methods to look like the following:

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

Also note that I imported the string module to makes things a little easier. The code probably needs some clean up, but it worked on my machine.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文