【问题标题】:buttons and a refreshing display area in wxpythonwxpython中的按钮和刷新显示区域
【发布时间】:2019-01-01 08:06:23
【问题描述】:

我是一名人文学科教师,正在尝试改编一个简单的应用程序来帮助教师管理课堂互动 - 它需要出勤率,然后允许随机召集学生上课,或将他们分组,或记录因故缺席,以及很快。长期以来,我一直在笔记本电脑上本地运行 PHP / MySQL 的工作版本,但我想让它成为一个可移植的 python / sqlite 应用程序,着眼于发布到野外供其他教师使用和改进。

但我对 wxPython 完全陌生,一般来说,我对面向对象的编程并不是很擅长。我花了几个小时阅读(或浏览)相当多的教程和介绍以及 StackOverflow 问题,我也玩过 wxFormBuilder,但我觉得我没有取得进展——我仍然对面板和大小和布局,以及哪些位应该属于哪些父项。

我认为,如果我可以让这个最小版本正常工作,那对我真正的应用程序会有很大帮助。顶部的类似工具栏的按钮似乎工作正常,但我希望下方有一个“显示”区域,垂直尺寸最小(但可扩展),文本区域居中,显示中有一排 2-3 个按钮该文本下方的区域。该显示区域应根据上面按下的按钮进行更改和清除。这是我得到的:

#!/usr/bin/env python3

import wx

class MainWindow(wx.Frame):
    def __init__(self, parent, title):

        wx.Frame.__init__(self, parent, title=title, size=(-1,-1))

        # self.panel = wx.Panel(self, size=(-1,300))

        # buttons bar

        self.top_button_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.btn_left = wx.Button(self, -1, label="left")
        self.btn_right = wx.Button(self, -1, label="right")

        self.btn_left.Bind(wx.EVT_BUTTON, self.OnLeft)
        self.btn_right.Bind(wx.EVT_BUTTON, self.OnRight)

        self.top_button_sizer.Add(self.btn_left, 1, wx.EXPAND)
        self.top_button_sizer.Add(self.btn_right, 1, wx.EXPAND)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.display_sizer = wx.BoxSizer(wx.VERTICAL)
        self.text_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.display_text = wx.StaticText(self, label="Push a button!")
        self.display_buttons_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.text_sizer.Add(self.display_text, 0, wx.ALIGN_CENTER, 5)
        self.display_sizer.Add(self.text_sizer, 1, wx.ALIGN_CENTER, 5)
        self.display_sizer.Add(self.display_buttons_sizer, 0, wx.EXPAND)

        self.sizer.Add(self.top_button_sizer, 0, wx.TOP | wx.EXPAND)
        # self.sizer.Add(self.panel)
        self.sizer.Add(self.display_sizer, 1, wx.EXPAND)

        self.SetSizerAndFit(self.sizer)
        self.Show()

    def OnLeft(self,e):
        # for child in self.display_buttons_sizer.GetChildren():
        #     child.Destroy()
        # ^ my attempt to "clear" causes a SegFault
        for child in self.display_buttons_sizer.GetChildren():
            child.Destroy()
        self.display_text.SetLabel("Hey lefty!")
        self.btn_hey = wx.Button(self, -1, label="Hey yourself lefty.")
        self.btn_whoa = wx.Button(self, -1, label="Whoa there lefty.")
        self.display_buttons_sizer.Add(self.btn_hey, 1, wx.EXPAND)
        self.display_buttons_sizer.Add(self.btn_whoa, 1, wx.EXPAND)

        self.sizer.Layout()

    def OnRight(self,e):
        # for child in self.display_buttons_sizer.GetChildren():
        #     child.Destroy()
        # ^ my attempt to "clear" causes a SegFault!
        self.display_text.SetLabel("Hey righty!")
        self.btn_hey = wx.Button(self, -1, label="Hey yourself righty.")
        self.btn_whoa = wx.Button(self, -1, label="Whoa there righty.")
        self.display_buttons_sizer.Add(self.btn_hey, 1, wx.EXPAND)
        self.display_buttons_sizer.Add(self.btn_whoa, 1, wx.EXPAND)

        self.sizer.Layout()

app = wx.App(False)
frame = MainWindow(None, "MWE")
app.MainLoop()

(我确信这在很多方面都是可恶的代码。)我应该在某个地方放置一个面板吗?在哪里,如何?学习“笔记本”而不是使用我的顶部按钮会更容易吗?如何正确清除下方“显示”区域中的内容以便下次按下按钮?

奖励积分:在我的真实应用中,最复杂的顶部按钮是用于考勤。它将显示多行文本(我从 sqlite 获得的那个班级的学生;我认为我已经完成了那部分),每行旁边带有出席/缺席的单选按钮,然后记录在数据库中。对此的提示也将不胜感激。

提前感谢您的耐心等待。

【问题讨论】:

    标签: python layout wxpython


    【解决方案1】:

    你可以用几种不同的方式来做这种事情。您可以在按下按钮时更换面板,或者您可以只使用wx.Notebook,这基本上是相同的想法。我在这里写了一个关于面板切换的教程,你可能会觉得有帮助:

    它使用菜单而不是按钮,但这并不难改变。这是一个不进行面板切换的简单示例,但确实显示了如何添加一个多行文本控件,该控件在按下按钮时会自行清除:

    import wx
    
    class MainPanel(wx.Panel):
    
        def __init__(self, parent):
            wx.Panel.__init__(self, parent)
    
            self.main_sizer = wx.BoxSizer(wx.VERTICAL)
            btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
    
            left_button = wx.Button(self, label='Left')
            left_button.Bind(wx.EVT_BUTTON, self.on_left)
            btn_sizer.Add(left_button, 0, wx.ALL, 5)
    
            right_button = wx.Button(self, label='Right')
            right_button.Bind(wx.EVT_BUTTON, self.on_right)
            btn_sizer.Add(right_button, 0, wx.ALL, 5)
    
            self.text_ctrl = wx.TextCtrl(self, style=wx.TE_MULTILINE)
    
            self.main_sizer.Add(btn_sizer, 0, wx.CENTER)
            self.main_sizer.Add(self.text_ctrl, 1, wx.ALL|wx.EXPAND, 5)
            self.SetSizer(self.main_sizer)
    
        def on_left(self, event):
            self.text_ctrl.Clear()
            self.text_ctrl.SetValue('Left')
    
        def on_right(self, event):
            self.text_ctrl.Clear()
            self.text_ctrl.SetValue('Right')
    
    
    
    class MainWindow(wx.Frame):
        def __init__(self, parent, title):
    
            wx.Frame.__init__(self, parent, title=title, size=(-1,-1))
            panel = MainPanel(self)
            self.Show()
    
    
    app = wx.App(False)
    frame = MainWindow(None, "MWE")
    app.MainLoop()
    

    这还演示了如何添加面板,建议使用面板,因为面板可以在所有平台上为您提供正确的“外观”,并且还可以在控件之间进行选项卡。

    您可以使用此处显示的相同概念轻松地将另一组按钮添加到底部,然后只需将第二组按钮的大小调整器添加到主大小调整器。

    如果您想使用某种单选按钮或检查按钮来处理文本行,我建议您使用wx.ListCtrl 或(更好)ObjectListViewhttps://objectlistview-python-edition.readthedocs.io/en/latest/recipes.html#recipe-checkbox)(另请参阅https://www.blog.pythonlibrary.org/2009/12/23/wxpython-using-objectlistview-instead-of-a-listctrl/

    您可以将事件绑定到复选框,然后可以适当地更新您的数据库。

    【讨论】:

    • 非常感谢您抽出宝贵时间回答这个长长的问题!我一直在玩 PyQt5(并观看 Udemy 课程),部分原因是信号/插槽对我来说似乎比按钮绑定更容易,而且我无论如何都打算开源。但是看看这些事情是如何在 wxPython 和 PyQt 中完成的有助于我进行三角测量,我可能会切换回去。我希望这个问题/答案对其他人也有帮助!
    • wxPython 内置了 pubsub,它做了很多 PyQt 的信号/槽的东西,虽然公平地说,PyQt 的信号/槽的东西更强大。
    • 另请注意,现在有用于 Python / PySide2 的 Qt,如果你真的想获得 Qt 路线,它可能比 PyQt 更适合你
    猜你喜欢
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2014-09-05
    相关资源
    最近更新 更多