首页 > 解决方案 > wxpython中的按钮和刷新显示区域

问题描述

我是一名人文学科教师,试图改编一个简单的应用程序来帮助教师管理课堂互动——它需要出勤率,然后允许随机召集学生上课,或将他们分成小组,或记录因故缺席,等等。我长期以来一直在我的笔记本电脑上本地运行 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 获得的那个班级的学生;我认为我已经完成了那部分),每行旁边带有出席/缺席的单选按钮,然后记录在数据库中。对此的提示也将不胜感激。

提前感谢您的耐心等待。

标签: pythonlayoutwxpython

解决方案


你可以用几种不同的方式来做这种事情。您可以在按下按钮时更换面板,或者您可以只使用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/

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


推荐阅读