2013-07-24 153 views
1

我正在编写一个程序,它执行一些工作并使用matplotlib来绘制一些数据。这可能需要一些时间,所以我使用tkinter设置了一个进度条。用tkinter进行线程化并不那么容易。我正在主线程中运行进度条,并在基本线程中运行我的工作内容。但是我的工作完成后我无法关闭进度条窗口,因为matplotlib在tk根窗口中执行了某些操作。我不知道是什么。我添加了一个我正在尝试做的最简单的例子。注意,删除“plotsomething()”这一行使得它可以做我想做的事情:完成工作后关闭进度条。当matplotlib窗口打开时关闭tkinter进度条窗口

你能帮我弄清楚如何关闭进度条窗口而不关闭matplotlib窗口吗?

# coding = utf-8 
import numpy as np 
import matplotlib.pyplot as plt 
import tkinter as tk 
from tkinter import ttk 
import threading, queue 
import time 

def MAIN(): 
    PB = q.get() 
    for i in np.arange(10): 
     time.sleep(0.2) 
     print(i) 
     PB.step(10) 
     PB.update() 
    print("Done") 

def plotsomething(): 
    x = np.linspace(0,10,100) 
    y = np.sin(x) 
    plt.plot(x,y) 

root = tk.Tk() 
root.title("Progress") 
PB = ttk.Progressbar(root, orient = "horizontal",length=300, mode = 'determinate') 
PB.pack() 
q = queue.Queue() 
q.put(PB) 

plotsomething() 

T = threading.Thread(target=MAIN(), name="MAIN") 
T.start() 
T.join() 
plt.show() 

编辑 - 解决方案:我通过使用matplotlib TK后端seperatly绘制每一个窗口,现在解决这个问题。显然PyPlot正在干扰tkinter根窗口。有关更多细节和提示,请参阅tcaswell的评论。非常感谢你!

import numpy as np 
import matplotlib 
matplotlib.use('TkAgg') 

from numpy import arange, sin, pi 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg 
from matplotlib.figure import Figure 
import tkinter as tk 
from tkinter import ttk 
import queue, threading, time 

def center_window(window_parent, w=300, h=20): 
    # get screen width and height 
    ws = window_parent.winfo_screenwidth() 
    hs = window_parent.winfo_screenheight() 
    # calculate position x, y 
    x = (ws/2) - (w/2) 
    y = (hs/2) - (h/2) 
    window_parent.geometry('%dx%d+%d+%d' % (w, h, x, y)) 

def MAIN(): 
    PB = q.get() 
    for i in np.arange(10): 
     time.sleep(0.2) 
     print(i) 
     PB.step(10) 
     PB.update() 
    print("Done") 

root = tk.Tk() 
root.wm_title("Embedding in TK") 


f = Figure(figsize=(5,4), dpi=100) 
a = f.add_subplot(111) 
t = arange(0.0,3.0,0.01) 
s = sin(2*pi*t) 

a.plot(t,s) 
a.set_title('Tk embedding') 
a.set_xlabel('X axis label') 
a.set_ylabel('Y label') 


#a tk.DrawingArea 
root2 = tk.Tk() 

PB = ttk.Progressbar(root2, orient = "horizontal",length=300, mode = 'determinate') 
PB.pack() 

canvas = FigureCanvasTkAgg(f, master=root) 
canvas.show() 
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) 

toolbar = NavigationToolbar2TkAgg(canvas, root) 
toolbar.update() 
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 

root2.iconify() 
root2.update() 
root2.deiconify() 

center_window(root2) 

q = queue.Queue() 
q.put(PB) 

T = threading.Thread(target=MAIN(), name="MAIN") 
T.start() 
T.join() 

root2.quit() 
root2.destroy() 

tk.mainloop() 
+0

所以,你要的进度在启动时启动,数到10,打印 “完成”,破坏本身,那么matplotlib窗口会正确启动? – iCodez

+0

作为一个侧面问题,您希望在文档中查找哪些内容以找到它?这个问题每隔一周以各种形式出现,这表明文档失败。 – tacaswell

+0

再次看到这个问题,你真的应该发布你的编辑作为答案。为了愤世嫉俗,我代表我的一半答案,你应该得到你的完整答案;) – tacaswell

回答

2

你所得到的TK你开始和TKplt是启动之间冲突的图形用户界面的主回路。如果你想用你自己的gui使用matplotlib,你需要嵌入它你自己和你不能进口pyplot。所有的幕后魔法让界面变得美好,这就是你在这里搞砸了什么。

有关教程,请参见herempl的嵌入方式请参阅here

另见: