python - 如何从一个窗口(类)到另一个窗口(类)获取进度条 start() 信息?

标签 python python-2.7 class progress-bar ttk

有一个带有菜单和进度条的主窗口。带有 OK 按钮的对应窗口根据菜单命令打开,OK 按钮启动该过程(此处:3 秒 sleep )。 通信窗口是通过继承 self 未在此处提供的类创建的(如果需要回答,请告诉我)。 applyok 方法覆盖了母类中的现有方法。

现在我的问题是:由于进度条位于主窗口(App 类)中,而 progressbar(start)progressbar(stop) 在对应窗口中,我不知何故通过母类 tkSimpleDialog.Dialog 将 (start) 和 (stop) 传递给 App 类。所以我想我也覆盖了 __init__(self..) 方法,提供 self. 到 progressbar.

我怎样才能让它工作?

import Tkinter, ttk, tkFileDialog, tkSimpleDialog, time, threading

class App:
  def __init__(self, master, progressbar):
    self.progress_line(master)

  def progress_line (self, master):
    self.progressbar = ttk.Progressbar(master, mode='indeterminate')
    self.progressbar.place(anchor = 'ne', height = "20", width = "150", x = "175", y = "30")

class AppMenu(object):

  def __init__(self, master, progressbar):
    self.master = master
    self.menu_bar()

  def menu_bar(self):
    menu_bar = Tkinter.Menu(self.master)
    self.menu_bar = Tkinter.Menu(self.master)
    self.master.config(menu=self.menu_bar)
    self.create_menu = Tkinter.Menu(self.menu_bar, tearoff = False)
    self.create_menu.add_command(label = "do", command = self.do)
    self.menu_bar.add_cascade(label = "now", menu = self.create_menu)

  def do(self):
    do1 = Dialog(self.master, progressbar)    

class Dialog(tkSimpleDialog.Dialog):

  def __init__(self, parent, progressbar):

    tkSimpleDialog.Dialog.__init__(self, parent, progressbar)
    self.transient(parent)

    self.parent = parent
    self.result = None

    self.progressbar = progressbar

    body = Frame(self)
    self.initial_focus = self.body(body)
    body.pack(padx=5, pady=5)

    self.buttonbox()
    self.grab_set()

    if not self.initial_focus:
        self.initial_focus = self

    self.protocol("WM_DELETE_WINDOW", self.cancel)
    self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
    self.initial_focus.focus_set()
    self.wait_window(self)

  def ok(self, event=None):
    self.withdraw()
    self.start_foo_thread()
    self.cancel()
  def apply(self):
    time.sleep(5)

  def start_foo_thread(self):
    global foo_thread
    self.foo_thread = threading.Thread(target=self.apply)
    self.foo_thread.daemon = True
    self.progressbar.start()
    self.foo_thread.start()
    master.after(20, check_foo_thread)

  def check_foo_thread(self):
    if self.foo_thread.is_alive():
        root.after(20, self.check_foo_thread)
    else:
        self.progressbar.stop()    

master = Tkinter.Tk()
progressbar = None
app = App(master, progressbar)
appmenu = AppMenu(master, progressbar)
master.mainloop()

错误信息: 单击确定后首先:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1410, in __call__
  File "ask-progressbar.py", line 57, in ok
    self.start_foo_thread()
  File "ask-progressbar.py", line 66, in start_foo_thread
    self.progressbar.start()
AttributeError: Dialog2 instance has no attribute 'progressbar'

第二个:关闭应用后

Exception in Tkinter callback
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1410, in __call__
  File "ask-progressbar.py", line 26, in do
    do1 = Dialog2(self.master, progressbar)
  File "ask-progressbar.py", line 33, in __init__
    self.transient(parent)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1652, in wm_transient
TclError: can't invoke "wm" command:  application has been destroyed

最佳答案

以下是您的代码的工作版本。我必须解决许多问题,因为您没有更改代码中的许多内容,这些内容来 self 对您的其他 question 的回答。关于进度条。

这里主要问题的答案基本上是你必须传递实例并在必要时在涉及的各种类实例中记住它,以便它们的方法可以通过 self 参数使用它当他们需要的时候。此外,您尝试推导和覆盖 tkSimpleDialog.Dialog 的方式基类方法既过于复杂又不正确。

通常,最好(也是最简单)的做法就是提供您自己的 validate()apply() 方法,因为它就是这样设计的。如果您还需要自己的 __init__() 构造函数,重要的是只将参数传递给它从子类中的方法中理解的基类方法。如果您需要更多功能,通常可以通过额外的仅派生类方法提供,只有它或您创建的其他类知道。

无论如何,这就是我最终得到的:

import Tkinter, ttk, tkFileDialog, tkSimpleDialog, time, threading

class App:
    def __init__(self, master):
        self.progress_line(master)

    def progress_line(self, master):
        # the value of "maximum" determines how fast progressbar moves
        self._progressbar = ttk.Progressbar(master, mode='indeterminate', 
                                            maximum=4) # speed of progressbar
        self._progressbar.place(anchor='ne', height="20", width="150", 
                                x="175", y="30")
    @property
    def progressbar(self):
        return self._progressbar # return value of private member

class AppMenu(object):
  def __init__(self, master, progressbar):
      self.master = master
      self.menu_bar()
      self.progressbar = progressbar

  def menu_bar(self):
      self.menu_bar = Tkinter.Menu(self.master)
      self.master.config(menu=self.menu_bar)
      self.create_menu = Tkinter.Menu(self.menu_bar, tearoff=False)
      self.create_menu.add_command(label="do", command=self.do)
      self.menu_bar.add_cascade(label="now", menu=self.create_menu)

  def do(self):
      Dialog(self.master, self.progressbar) # display the dialog box

class Dialog(tkSimpleDialog.Dialog):
    def __init__(self, parent, progressbar):
        self.progressbar = progressbar
        tkSimpleDialog.Dialog.__init__(self, parent, title="Do foo?")

    def apply(self):
        self.start_foo_thread()

    # added dialog methods...
    def start_foo_thread(self):
        self.foo_thread = threading.Thread(target=self.foo)
        self.foo_thread.daemon = True
        self.progressbar.start()
        self.foo_thread.start()
        master.after(20, self.check_foo_thread)

    def check_foo_thread(self):
        if self.foo_thread.is_alive():
            master.after(20, self.check_foo_thread)
        else:
            self.progressbar.stop()

    def foo(self): # some time-consuming function...
        time.sleep(3)


master = Tkinter.Tk()
master.title("Foo runner")
app = App(master)
appmenu = AppMenu(master, app.progressbar)
master.mainloop()

希望这对您有所帮助。

关于python - 如何从一个窗口(类)到另一个窗口(类)获取进度条 start() 信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16420041/

相关文章:

python-2.7 - 即使 RAM 空闲,内存也会出现错误

java - 用两种泛型类型的对象填充数组列表

python - 实现一个名为 Average 的类作为 List 的子类

c++ - 如何公开大量 protected 内部类函数?

Python Docker API 需要知道 attach(**kwargs) 到容器的语法

python - 如何在不同的子图中绘制 pcolor colorbar - matplotlib

python - 如何将 setup.py console_script 与 native 命名空间包一起使用

python - Cygwin 新手 : How do I uninstall Python 2. 6.x 来自 Cygwin 并安装 Python 2.7.x?

python - 如何实现临时函数 "memoization"?

windows - 如何通过Python静音麦克风