我制作了一个GUI,其中在用户值上绘制了一条线,当您单击该线时,将打开另一个窗口,您可以在其中选择某些内容。当您按确定时,它应该在终端上打印。我认为是因为单击该行时正在创建一个新的tkinter窗口,所以无法检索用户选择。如何解决此问题?非常感谢您的帮助。
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import style
import tkinter as tk
from tkinter import ttk
from tkinter import *
import random
import numpy as np
LARGE_FONT = ('Verdana',12)
style.use('ggplot')
from matplotlib import pyplot as plt
class PageOne(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
label = tk.Label(self,text='Experiment', font = LARGE_FONT)
label.pack(pady=10,padx=10)
self.adding_widgets()
button2= ttk.Button(self,text='Validate', command=self.draw)
button2.pack()
button3= ttk.Button(self,text='Erase', command=self.dlet)
button3.pack()
self.lines_pts=[]
self.f1= Figure(figsize=(5,5),dpi=100)
self.b=self.f1.add_subplot(1,1,1)
self.b.set_xlim([0,10])
self.b.set_ylim([0,10])
self.canvas = FigureCanvasTkAgg(self.f1, self)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=tk.TOP,fill=tk.BOTH,expand=True)
self.f1.canvas.mpl_connect('pick_event', self.on_pick)
self.lines =[]
def adding_widgets(self,*args):
labfram=ttk.LabelFrame(self,width=100,height=100,text='Enter Member Coordinates',labelanchor=N)
labfram.pack()
l1=ttk.Label(labfram,text='x0')
l1.pack(side='left')
self.x0=Entry(labfram,width=10,)
self.x0.pack(side='left')
l2=ttk.Label(labfram,text='y0')
l2.pack(side='left')
self.y0=Entry(labfram,width=10)
self.y0.pack(side='left')
l3=ttk.Label(labfram,text='x1')
l3.pack(side='left')
self.x1=Entry(labfram,width=10)
self.x1.pack(side='left')
l4=ttk.Label(labfram,text='y1')
l4.pack(side='left')
self.y1=Entry(labfram,width=10)
self.y1.pack(side='left')
def draw(self):
p0 = float(self.x0.get()), float(self.y0.get())
p1 = float(self.x1.get()), float(self.y1.get())
self.lines_pts.append((p0,p1))
for p0,p1 in self.lines_pts:
x0, y0, x1, y1 = *p0, *p1
X = x0,x1
Y = y0,y1
ax = self.b.plot(X,Y, 'r', linewidth=4,picker=5 )
self.lines.append(ax)
self.canvas.draw()
def dlet(self):
self.b.lines.remove(self.b.lines[-1])
self.canvas.draw()
def on_pick(self,event):
w=Tk()
w.title('Channel Select')
w.geometry('250x50')
n = StringVar()
ch = ttk.Combobox(w, width = 15 , textvariable = n)
ch['values'] = ('CH1','CH2','CH3','CH4','CH5','CH6','CH7','CH8','CH9','CH10')
ch.grid(column=1,row=0)
ch_label = ttk.Label(w,text='Select Your Channel')
ch_label.grid(column=0,row=0)
ch_button = ttk.Button(w,text='OK',command=lambda: print ('value is:'+ n.get()))
ch_button.grid(column=1,row=1)
for line in self.lines:
line = event.artist
xdata, ydata = line.get_data()
ind = event.ind
print('on pick line:', np.array([xdata[ind], ydata[ind]]).T)
app = PageOne()
app.mainloop()
答案 0 :(得分:1)
您真的要在这里创建一个新窗口吗?
def on_pick(self,event):
w=Tk()
w.title('Channel Select')
w.geometry('250x50')
请注意,当您执行w=Tk()
操作时,正在创建对象的实例 NEW OBJECT (即Tk()),因此这就是创建新窗口的原因。您的目标是真的要在每次单击时弹出一个窗口吗,如果没有,我想您可以删除它。
---- UPDATE ---
所以窗口不断弹出的原因是,在函数上您创建了带有该对象的实例。然后,我尝试将w=Tk()
放到函数之外,但仍然会创建或显示该对象,因为它位于mainloop
内。
另一种解决方案是,您可以检查该窗口是否存在或其状态是否为正常,然后只需执行focus
。
这是我仅在您的on_pick
函数上添加的代码。我还为您的__init__
方法添加了self.w = None
,最初只是将w变量设置为None。
总体来说,这只是所做的更改
def on_pick(self,event):
try:
if self.w.state() == "normal":
self.w.focus()
except BaseException as on_pick_error:
self.w=Toplevel()
self.w.title('Channel Select')
self.w.geometry('250x50')
n = StringVar()
ch = ttk.Combobox(self.w, width = 15 , textvariable = n)
ch['values'] = ('CH1','CH2','CH3','CH4','CH5','CH6','CH7','CH8','CH9','CH10')
ch.grid(column=1,row=0)
ch_label = ttk.Label(self.w,text='Select Your Channel')
ch_label.grid(column=0,row=0)
ch_button = ttk.Button(self.w,text='OK',command=lambda: print ('value is:'+ n.get()))
ch_button.grid(column=1,row=1)
for line in self.lines:
line = event.artist
xdata, ydata = line.get_data()
ind = event.ind
print('on pick line:', np.array([xdata[ind], ydata[ind]]).T)
您可能想知道这样做是什么,它只是检查您弹出的窗口的self.w
的状态是否正确,它只是检查其状态是否等于“正常” strong>表示它处于活动状态,那么当它处于活动状态时,只需执行.focus()
并专注于该当前窗口即可。否则,它将创建一个新窗口,其为self.w=Toplevel()
,依此类推。
try:
if self.w.state() == "normal":
self.w.focus()
except BaseException as on_pick_error:
self.w=Toplevel()
self.w.title('Channel Select')
self.w.geometry('250x50')
为什么它是顶级而不是Tk?
我建议将其设置为Toplevel,但是要由您决定,因为Toplevel和Tk可能具有相同的属性,但是请注意它们并不相同,因此取决于您。