如何覆盖“取消"ProgressDialog 的按钮事件? [英] How to override the "Cancel" button event of a ProgressDialog?

查看:27
本文介绍了如何覆盖“取消"ProgressDialog 的按钮事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ProgressDialog类允许传递选项 wx.PD_CAN_ABORT在对话框中添加了一个取消"按钮.我需要重新绑定绑定到此的事件按钮,使其 Destroy() 对话框而不是仅仅进行下一次调用to Update() [to] return False",如该类的文档所述.

The ProgressDialog class allows passing the option wx.PD_CAN_ABORT which adds a "Cancel" button to the dialog. I need to rebind the event bound to this button, to make it Destroy() the dialog instead of just "making the next call to Update() [to] return False" as the class's documentation describes.

class PortScanProgressDialog(object):

    """Dialog showing progress of the port scan."""

    def __init__(self):
        self.dialog = wx.ProgressDialog(
            "COM Port Scan",
            PORT_SCAN_DLG_MSG,
            MAX_COM_PORT,
            style=wx.PD_CAN_ABORT | wx.PD_AUTO_HIDE)

    def get_available_ports(self):
        """Get list of connectable COM ports.

        :return: List of ports that e.g. exist, are not already open,
            that we have permission to open, etc.
        :rtype: list of str
        """
        com_list = []
        keep_going = True
        progress_count = 0
        for port_num in range(MIN_COM_PORT, MAX_COM_PORT + 1):
            if not keep_going:
                break
            port_str = "COM{}".format(port_num)
            try:
                # Check if the port is connectable by attempting to open
                # it.
                t_port = Win32Serial(
                    port_str, COMPATIBLE_BAUDRATE,
                    bytesize=SerialThread.BYTESIZE,
                    parity=SerialThread.PARITY,
                    stopbits=SerialThread.STOPBITS, timeout=4)
                t_port.close()
                com_list.append(port_str)
            finally:
                progress_count += 1
                # This returns a tuple with 2 values, the first of which
                # indicates if progress should continue or stop--as in
                # the case of all ports having been scanned or the
                # "Cancel" button being pressed.
                keep_going = self.dialog.Update(progress_count, msg)[0]
        return com_list

这个类在其他地方以这种方式使用:

This class is used elsewhere in this fashion:

# Scan for available ports.
port_scan_dlg = PortScanProgressDialog()
ports = port_scan_dlg.get_available_ports()
port_scan_dlg.dialog.Destroy()

get_available_ports() 中发生未处理的异常时,进度对话框将保持打开状态(这是预期的行为),但问题是当我点击取消"按钮是灰色的并且窗口没有关闭(点击X"也无法关闭窗口).

When an unhandled exception occurs in get_available_ports() the progress dialog will stay open (which is expected behaviour), but the problem is that when I hit "Cancel" the button is greyed and the window is not closed (clicking "X" also fails to close the window).

我正在尝试将取消"按钮重新绑定到 Destroy() 的方法对话.我该怎么做?

I'm trying to re-bind the "Cancel" button to a method that Destroy()s the dialog. How can I do this?

我知道这个解决方法,但我认为它更干净使用 ProgressDialog并根据我的需要对其进行修改.

I'm aware of this workaround, but I think it's cleaner to use ProgressDialog and modify it to my needs.

推荐答案

取消按钮未直接在此小部件中公开.您可以使用对话框的 GetChildren 方法访问它.这是一种方法:

The Cancel button is not exposed directly in this widget. You can get to it using the dialog's GetChildren method. Here's one way to do it:

import wx

class TestPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        b = wx.Button(self, -1, "Create and Show a ProgressDialog", (50,50))
        self.Bind(wx.EVT_BUTTON, self.OnButton, b)


    def OnButton(self, evt):
        max = 80

        dlg = wx.ProgressDialog("Progress dialog example",
                               "An informative message",
                               maximum = max,
                               parent=self,
                               style = wx.PD_CAN_ABORT
                                | wx.PD_APP_MODAL
                                | wx.PD_ELAPSED_TIME
                                #| wx.PD_ESTIMATED_TIME
                                | wx.PD_REMAINING_TIME
                                )
        for child in dlg.GetChildren():
            if isinstance(child, wx.Button):
                cancel_function = lambda evt, parent=dlg: self.onClose(evt, parent)
                child.Bind(wx.EVT_BUTTON, cancel_function)

        keepGoing = True
        count = 0

        while keepGoing and count < max:
            count += 1
            wx.MilliSleep(250)  # simulate some time-consuming thing...

            if count >= max / 2:
                (keepGoing, skip) = dlg.Update(count, "Half-time!")
            else:
                (keepGoing, skip) = dlg.Update(count)


        dlg.Destroy()

    #----------------------------------------------------------------------
    def onClose(self, event, dialog):
        """"""
        print "Closing dialog!"


########################################################################
class MyFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title='Progress')
        panel = TestPanel(self)
        self.Show()

if __name__ == '__main__':
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

这是基于此特定对话框的 wxPython 演示示例.根据您的平台,您将获得本机小部件(如果存在),否则您将获得 wx.GenericProgressDialog.我怀疑本机小部件根本不允许您访问取消"按钮,但我不确定.

This is based on the wxPython demo example of this particular dialog. Depending on your platform, you will get the native widget if it exists, otherwise you'll get wx.GenericProgressDialog. I suspect the native widget won't allow you to access the Cancel button at all, but I'm not sure.

这篇关于如何覆盖“取消"ProgressDialog 的按钮事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆