如何从主

时间:2016-06-13 22:15:11

标签: python multithreading tkinter multiprocessing

我在创建进度条的方法中有代码:

def progress_bar(self, message = None, icon_path = None, icon_name = None, size = 0, file_location = None, interval = 100):
    #size: in bytes of download
    #file_location: location of the download
    #interval: frequency, in ms, of how often to poll the file for progress
    self.find_icon(icon_path, icon_name)
    self.text_label = tk.Label(text = message)
    self.set_colors(self.text_label)
    self.set_colors(self.image_label)
    self.image_label.grid(row = 1, column = 1, sticky = 'NSEW')
    self.text_label.grid(row = 1, column = 2, sticky = 'NSEW')
    self.progress = ttk.Progressbar(self, orient="horizontal", length=(self.xp/3), mode="determinate")
    self.progress.grid(row = 1, column = 3, sticky = 'NSEW')
    self.progress["value"] = 0
    self.progress["maximum"] = size
    self.auto_resize(1, 3)
    self.progress.start(interval)
    self.after(1, self.check_for_completion(file_location))
    self.mainloop()

def check_for_completion(self, file_location):
    #while (self.progress["value"] < self.progress["maximum"]):
    self.progress["value"] = os.stat(file_location).st_size
    print self.progress["value"]

    if (self.progress["value"] >= self.progress["maximum"]):
        self.text_label = tk.Label(text = message + ": Completed")
        #force a repaint and wait for the user to see it
        self.text_label.grid(row = 1, column = 2)
        time.sleep(30)
        self.choice(True)
        self._delete_window

并且通过健全性测试,我在同一个脚本中有一个_ _ main _ _方法,我想要做的是创建一个临时文件,启动进度条,然后开始将chars放入临时文件中。不幸的是,我找不到以非阻塞的方式启动进度条的方法。

我尝试使用python Multiprocessing这样:

p = Process(target = frame4.progress_bar, kwargs = kwarrgh)
p.start()
p.join()

并且非常生气;}消息说

Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.

注意:本练习的重要部分是从主要窗口启动Tkinter窗口,而不是相反。我在后者身上发现了一堆SO问题,而不是前者。

如果存在多线程而不是多处理方法,则答案不需要是线程安全的。

2 个答案:

答案 0 :(得分:2)

只需继续使用check_for_completion调用after()函数,直到您的流程完成。

def check_for_completion(self, file_location):
    ... # your code

    if (self.progress["value"] >= self.progress["maximum"]):
        ... # you code 
    else:             # 'value' is not bigger then maximum so we run the function again.
        self.after(10, lambda: self.check_for_completion(file_location))

请注意我是如何用after方法用参数调用函数的。您也应该这样做:

#self.after(1, self.check_for_completion(file_location))  # Not like this
self.after(1, lambda: self.check_for_completion(file_location))  # like this

答案 1 :(得分:0)

Stevo,谢谢你的小费。我认为我们很接近,但并不完全在那里。也许我应该分享我用来测试它的代码:

tmp, location = tempfile.mkstemp() 
print location 
frame4 = InstallerUserMessage(text = "", title = "foo")   
frame4.progress_bar(message = "bar", icon_name="logo.gif", size = 0, file_location = location) 
with closing(os.fdopen(tmp, 'w')) as tmp_handle: 
    time.sleep(5) 
    tmp_handle.write('a') 
    frame4.after(1, lambda: self.check_for_completion(message, file_location))
    print 1 
    time.sleep(3)
    tmp_handle.write('a')
    frame4.after(1, lambda: self.check_for_completion(message, file_location))
    print 2
    time.sleep(7)
    tmp_handle.write('a')
    frame4.after(1, lambda: self.check_for_completion(message, file_location))
    print 3
    time.sleep(1)
    tmp_handle.write('a')
    frame4.after(1, lambda: self.check_for_completion(message, file_location))
    print 4
    time.sleep(8)
    tmp_handle.write('a')
    frame4.after(1, lambda: self.check_for_completion(message, file_location))
    print 5
    time.sleep(2)
    tmp_handle.write('a')
    frame4.after(1, lambda: self.check_for_completion(message, file_location))
    print 6

不幸的是,我得到的是打印出的位置,从第一次调用check_for_completion打印出来的0,然后它在终端和进度条处挂起,显示已满并且已完成消息。它似乎也需要很长时间才能进行绘画,可能是因为它直到最后都不会绘画?