我有一个简单的应用程序需要4个文件输入才能继续生成输出。
考虑btnFile1
btnFile2
btnFile3
和btnFile4
以及btnOutput
。
btnOutput
。
btnFile1...4
所有链接到四个相似但不同的方法,将它们称为OnBtn1..4
,将变量(称为file1..file4
)分配给使用wx.FileDialog
方法选择的文件。< / p>
我有一个辅助方法EnableButton()
,只需要一个简单的测试:
if self.file1 and self.file2 and self.file3 and self.file4:
self.btnGenerate.Enable()
e.Skip()
分配所有四个变量时调用此方法的最佳方法是什么?可以按任意顺序单击这四个按钮,因此我们无法仅将其分配给第4个按钮。
一个显而易见的选择是在每个EnableButton
方法中添加对OnBtn
的调用,但这是否是理想的解决方案?如果有50个按钮怎么办?
另一个选择是为每个按钮添加一个新事件,如下所示:
for btn in (btn1, btn2, btn3, btn4):
btn.Bind(wx.EVT_BUTTON, self.EnableButton)
但是,这不适用于上述方法,因为单击第4个按钮时,尚未分配变量。它仅在从wx.FileDialog中选择文件后分配。
我相信我没有看到第三种更理想的解决方案。
答案 0 :(得分:1)
我会使用wx.Timer并将计时器设置为每秒触发一次。每秒它都会触发并调用 EnableButton 事件处理程序。代码看起来像这样:
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.EnableButton, self.timer)
self.timer.Start(1000)
在事件处理程序中,我将在if语句中添加以下内容:
self.timer.Stop()
您可能还想添加一些逻辑来在用户关闭应用程序时停止计时器,因为计时器对象可能导致应用程序在仍处于活动状态时无法正确关闭。你可以在这里阅读更多关于计时器的信息:
答案 1 :(得分:1)
事件EVT_UPDATE_UI是一个事件处理程序,用于查看应用程序的状态并相应地更改UI元素。您可以使用它来启用或禁用您的按钮,具体取决于文件的状态,继续使用复选框表示文件状态的示例,只有勾选所有四个复选框时才会启用该按钮。
import wx
from wx.lib import sized_controls
class TestFrame(sized_controls.SizedFrame):
def __init__(self, *args, **kwargs):
super(TestFrame, self).__init__(*args, **kwargs)
contents_pane = self.GetContentsPane()
self.files = {}
for number in range(1, 5):
label = 'file{}'.format(number)
ctrl = wx.CheckBox(contents_pane, label=label)
self.files[label] = ctrl
btn_output = wx.Button(contents_pane, label='btn_output')
btn_output.Bind(wx.EVT_UPDATE_UI, self.btn_update)
def btn_update(self, event):
enable = all(ctrl.IsChecked() for ctrl in self.files.values())
event.Enable(enable)
app = wx.App(False)
test_frame = TestFrame(None)
test_frame.Show()
app.MainLoop()