Python:如何获取progressbar start()信息从一个窗口(类)到其他 [英] Python: How to get progressbar start() info from one window (class) to other

查看:281
本文介绍了Python:如何获取progressbar start()信息从一个窗口(类)到其他的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个包含菜单和进度条的主窗口。具有OK按钮的通信窗口在菜单命令时打开,并且OK按钮开始处理(这里:3秒睡眠)。
通信窗口是通过继承自我没有提供的类(如果需要回答,请让我知道)创建。方法 apply ok 覆盖母类中的现有方法。



现在我的问题:由于进度条位于主窗口(类App)和 progressbar(start) progressbar / code>在通讯窗口我不知何故必须通过(开始)和(停止)通过母亲类tkSimpleDialog.Dialog类应用程序。所以我想我也重写 __ 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 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)

类对话框(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()

如果没有self.initial_focus:
self.initial_focus = self

self.protocol(WM_DELETE_WINDOW,self.cancel)
self.geometry(+%d +%d%(parent.winfo_rootx ,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):
全局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()

错误讯息:
第一次点击确定后:

  Tkinter回调中的异常
Traceback(最近最后调用):
File/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ lib-tk / Tkinter.py,行1410,在__call__
文件ask-progressbar.py,第57行,在ok
self.start_foo_thread()
文件ask-progressbar .py,第66行,在start_foo_thread
self.progressbar.start()
AttributeError:Dialog2实例没有属性'progressbar'

秒:关闭应用程式后

  Tkinter回调中的异常
回溯(最近调用最后):
文件/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py,行1410,在__call__
文件ask-progressbar.py,第26行,在do
do1 = Dialog2(self.master,progressbar)
文件ask-progressbar.py,第33行,在__init__
self.transient(parent)
文件/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py,第1652行,在wm_transient
TclError:无法调用wm命令:应用程序已被销毁


方案

下面是你的代码的工作版本。有一些问题,我不得不解决,因为你没有改变的代码中的一些东西从我的答案到你的另一个

这里的主要问题的答案基本上是你必须通过的进度条并在需要时在所涉及的各种类实例中记住它,以便在他们需要它们时,它们的方法将通过 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):
# 最大值决定进度条的移动速度
self._progressbar = ttk.Progressbar(master,mode ='indeterminate',
maximum = 4)#进度条速度
self._progressbar。地方(anchor ='ne',height =20,width =150,
x =175,y =30)
@property
def progressbar :
return self._progressbar#私人成员的返回值

类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 ,command = self.do)
self.menu_bar.add_cascade(label =now,menu = self.create_menu)

def do(self):
Dialog self.master,self.progressbar)#显示对话框

类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()

#添加对话方法...
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):#一些耗时的函数...
time.sleep(3)


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

希望这有帮助。


There is a main window with menu and the progressbar. A correspondence window with OK button opens upon menu command and the OK button starts the process (here: 3 sec. sleep). The correspondence window is created via inheritance from a class I have not provided here (If required for answer, please let me know). The methods apply and ok override existing methods in the mother class.

Now my problem: Since the progressbar sits in the main window (class App) and progressbar(start) and progressbar(stop) in the correspondence window I somehow have to pass (start) and (stop) via the mother class tkSimpleDialog.Dialog to class App. So I thought I also override the __init__(self..) method, provide self. to progressbar.

How can I make this work?

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()

error messages: first after clicking ok:

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'

second: after closing app

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

解决方案

Below is a working version of your code. There were a number of issues I had to fix because you didn't change a number of things in the code from my answer to your other question about progressbars.

The answer to your main question here is basically that you have to pass the instance around and remember it when necessary in the various class instances involved so that their methods will have it available through theself argument when they need it. Also, the way you were trying to derive and override the tkSimpleDialog.Dialog base class methods was both over-complicated and incorrect as well.

Usually the best (and simplest) thing to do is just supply your own validate() and apply() methods since that's how it was designed to work. If you also need your own __init__() constructor, it's important to only pass parameters to the base class's method that it understands from within the one in the subclass. If you need more functionality, it can usually be provided via additional derived-class-only methods, that only it or other classes you've also created know about.

Anyway, here's what I ended-up with:

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()

Hope this helps.

这篇关于Python:如何获取progressbar start()信息从一个窗口(类)到其他的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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