我正在尝试在Linux(Ubuntu 14.04LTS)系统上的python3中使用ttk.notebook来读取Blockquote`# - - 编码:utf-8 - - 来自实验的数据并执行几个曲线拟合此数据,以计算有限元计算所需的系数。 我已经在没有tkinter的情况下执行了这些曲线的实际计算。我现在正在设置用户界面。 一切正常,直到我想填充变量a作为全局变量,注意到导出到Ipython shell(使用spyder2)。变量:CreepData和path2以相同的方式全局化,在Ipython shell中是可见的。 我不确定我从组合框中提取值的方式或笔记本页面上的Entry字段选择单位并以预期方式运行工作。 请参阅以下代码:
""" Created on Sat Jan 16 18:56:16 2016 @author: peterk Derived frpm a lot of posted examples """ import csv from copy import deepcopy import numpy as np import matplotlib import scipy import matplotlib matplotlib.use("TkAgg") from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,NavigationToolbar2TkAgg from matplotlib.figure import Figure from matplotlib import pyplot as plt from scipy import stats from scipy.optimize import curve_fit from tkinter import * import tkinter as tk import tkinter.font as tkFont import tkinter.ttk as ttk from tkinter import filedialog path2="./creep.csv" class CreepNotebook(ttk.Frame): def __init__(self, isapp=True, name='notebookdemo'): ttk.Frame.__init__(self, name=name) self.pack(expand=True, fill="both") self.master.title('Creep fit') self.isapp = isapp self._create_widgets() self.master.minsize(1920,1000) def _create_widgets(self): self._create_main_panel() def _create_main_panel(self): mainPanel = ttk.Frame(self, name='demo') mainPanel.pack( expand=True, side="top", fill="both") # create the notebook nb = ttk.Notebook(mainPanel, name='notebook') # extend bindings to top level window allowing # CTRL+TAB - cycles thru tabs # SHIFT+CTRL+TAB - previous tab # ALT+K - select tab using mnemonic (K = underlined letter) nb.enable_traversal() nb.pack(fill="both", padx=2, pady=3,expand=True) self._create_readme_tab(nb) self._create_import_data_tab(nb) self._create_select_units_run_tab(nb) self._create_text_tab(nb) def _create_readme_tab(self, nb): # frame explaining the app frame = ttk.Frame(nb, name='readMeFirst') # widgets to be displayed on 'Description' tab msg = ["Ttk is the new Tk themed widget set. One of the widgets ", "it includes is the notebook widget, which provides a set ", "of tabs that allow the selection of a group of panels, ", "each with distinct content. They are a feature of many ", "modern user interfaces. Not only can the tabs be selected ", "with the mouse, but they can also be switched between ", "using Ctrl+Tab when the notebook page heading itself is ", "selected. Note that the second tab is disabled, and cannot " "be selected." " aaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "ccccccccccccccccccccccccccccccccccccccccccccccccccccccc", "dddddd", "eeeee", "f", "a", "b", "c", "d", "e", "f", "g", "h", " here is text too"] lbl = ttk.Label(frame, wraplength='4i', justify=tk.LEFT, anchor=tk.CENTER, text=''.join(msg)) neatVar = tk.StringVar() btn = ttk.Button(frame, text='Neat!', underline=0, command=lambda v=neatVar: self._say_neat(v)) neat = ttk.Label(frame, textvariable=neatVar, name='neat') # position and set resize behaviour lbl.grid(row=0, column=0, columnspan=2, sticky='new', pady=5) btn.grid(row=1, column=0, pady=(2,4)) neat.grid(row=1, column=1, pady=(2,4)) frame.rowconfigure(1, weight=1) frame.columnconfigure((0,1), weight=1, uniform=1) # bind for button short-cut key # (must be bound to topplevel window) self.winfo_toplevel().bind('<Alt-n>', lambda e, v=neatVar: self._say_neat(v)) # add to notebook (underline = index for short-cut character) nb.add(frame, text='ReadMeFirst', underline=0, padding=2) def _say_neat(self, v): v.set('Yeah, I know...') self.update() self.after(500, v.set('')) # return path2 # ============================================================================= def _create_import_data_tab(self, nb): # Populate the second pane. frame = ttk.Frame(nb, name="import data") global l global k global sigma global creepData global filen global path2 butn=ttk.Button(frame, text='select csv file', command=self.askopenfilename2) butn.pack(side="top") self.file_opt = options = {} options['defaultextension'] = '.csv' options['filetypes'] =[('csv files', '.csv'),('all files', '.*')] options['initialdir'] = '.' options['initialfile'] = 'creep2.csv' options['parent'] = nb options['title'] = 'Select csv file' global creepData print("path2 in _create_import_data_tab") print (path2) nb.add(frame, text='Import data', underline=0) def askopenfilename2(self): global path2 global creepData path2 = filedialog.askopenfilename(**self.file_opt) print("path2 in askopenfilename2") print(path2) creepReader=csv.reader(open(path2, newline=""), delimiter=',') creepData=list(creepReader) #enter code here ======================================== def _create_text_tab(self, nb): # populate the third frame with a text widget frame = ttk.Frame(nb) txt = tk.Text(frame, width=40, height=10) vscroll = ttk.Scrollbar(frame, orient=tk.VERTICAL, command=txt.yview) txt['yscroll'] = vscroll.set vscroll.pack(side=tk.RIGHT) # txt.pack(tk.fill=BOTH, tk.expand=True) txt.pack() # btn2l.pack(side="top", pady=5) # btn2.pack(side="top", pady=2) # w.pack(side="top", pady=2) # neatVar = tk.StringVar() # btn = ttk.Button(frame, text='Neat!', underline=0, # command=lambda v=neatVar: self._say_neat(v)) # neat = ttk.Label(frame, textvariable=neatVar, name='neat') # def _say_neat(self, v): # v.set('Yeah, I know...') # self.update() # self.after(500, v.set('')) # add to notebook (underline = index for short-cut character) nb.add(frame, text='Text Editor', underline=0) #============================================================ def _create_select_units_run_tab(self, nb): # select units and perform the calculation frame = ttk.Frame(nb, name="select units and calculate") global l global k global sigma global creepData global a a=tk.StringVar() frame.grid(column=0, row=0, rowspan=12, columnspan=5,sticky=(N,S,E,W)) units = ('m,kg,s', 'mm,Mg,s', 'mm,kg,ms') a=tk.StringVar() cbl0 = ttk.Label(frame, text='Select or fill in the required fields and push the run button') cbl1 = ttk.Label(frame, text='Select units used in your FE-prgram') cb1 = ttk.Combobox(frame, value=units, state='readonly') # cbl1.pack(side="top") # cb1.pack(side="top") time_units=('hrs', 's','ms') cbl2=ttk.Label(frame, text='Select time units used in the csv file') cb2 = ttk.Combobox(frame, value=time_units, state='readonly') # cbl2.pack(side="top") # cb2.pack(side="top") strain_units=('strain [%]', 'strain [-]','CreepModulus [MPa]') cbl3=ttk.Label(frame, text='Select strain or modulus units used in the csv file') cb3 = ttk.Combobox(frame, value=strain_units, state='readonly') # cbl3.pack(side="top") # cb3.pack(side="top") yml=ttk.Label(frame, text=' Input Anisotropic Youngs Modulus in MPa') ym=Entry(frame) # yml.pack(side="top") # ym.pack(side="top") isfl=ttk.Label(frame, text='Input Isotropic factor') isf=Entry(frame) # isfl.pack(side="top") # isf.pack(side="top") run1Var = tk.StringVar() btn2 = ttk.Button(frame, text='Run', underline=0, command=lambda w=run1Var: self._run1(w)) btn2l = ttk.Label(frame, textvariable=run1Var, name='run1') cbl0.grid(column=0, row=0, sticky=W, pady=100) cbl1.grid(column=6, row=1, sticky=W, pady=25) cb1.grid(column=6, row=2, sticky=W, pady=2) cbl2.grid(column=6, row=3, sticky=W, pady=25) cb2.grid(column=6, row=4, sticky=W, pady=2) cbl3.grid(column=6, row=5, sticky=W, pady=25) cb3.grid(column=6, row=6, sticky=W, pady=2) yml.grid(column=6, row=7, sticky=W, pady=25) ym.grid(column=6, row=8, sticky=W ,pady=2) isfl.grid(column=6, row=9, sticky=W, pady=25) isf.grid(column=6, row=10, sticky=W, pady=2) btn2l.grid(column=6, row=11, sticky=W, pady=25) btn2.grid(column=6, row=12, sticky=W, pady=2) nb.add(frame, text='Select data and run', underline=0, padding=2) a=cb1.get() print(a) print(cb1.get()) yms=ym.get() isfs=isf.get() def _run1(self, w): # global CreepData # global creepDat # creepDat=deepcopy(creepData) w.set('CreepData is copied') self.update() self.after(500, w.set('')) #=================================================================== if __name__ == '__main__': CreepNotebook().mainloop()`
如果需要,我可以在我的repro上传csv.files,但我认为不需要回答这个问题。 run1函数将用于拟合数据曲线并返回执行计算的消息。
答案 0 :(得分:0)
已更改 - 抱歉,我最初没有理解您的问题,这可能会更有帮助:
首先,我建议您仔细研究这两个方面:
Share variables between methods
第二,您在_create_select_units_run_tab
中创建输入条目,然后执行:
def _create_select_units_run_tab:
...
a = cb1.get()
...
这将在创建后立即获取内容,甚至在.mainloop()
被调用之前,因此它绝对总是一个空字符串,以便稍后在_run1
中获取内容,您需要跟踪而是改为:
def _create_select_units_run_tab:
...
self.input_fields = [cb1,cb2,cb3,ym,isf]
#this will give all other methods access to the input fields
#then to get them back you can use this:
def get_inputs(self):
return [entry.get() for entry in self.input_fields]
#then in run you can get the data in the fields
def _run1(self, w):
inp_data = self.get_inputs()
print(inp_data)
if "" in inp_data:
w.set("you need to fill everthing in first!")
else:
w.set(str(inp_data))
...
在测试代码时,我取消了因path2 == ""
而导致错误的文件对话框窗口,因此您可能需要检查:
def askopenfilename2(self):
...
if path2 is not "":
creepReader=csv.reader(open(path2, newline=""), delimiter=',')
creepData = list(creepReader)
#else:
# creepData = None # or just leave it as the last used value?
...
更不用说open()
永远不会关闭(Input and Output Python documentation):
在处理文件对象时,最好使用with关键字。这样做的好处是,即使在路上引发异常,文件也会在套件完成后正确关闭。它也比编写等效的`try-finally`块短得多:with open('workfile', 'r') as f: ... read_data = f.read() >>> f.closed True
所以你可能也希望实现它:
with open(path2, newline="") as file_obj:
creepReader=csv.reader(file_obj, delimiter=',')
最后,我想提请注意:
self.after(500,w.set('')
立即调用 w.set('')
并使用None
中的返回值self.after
,而是使用您需要执行此操作的参数调用w.set
:
self.after(500,w.set,'')
然后tkinter会在500ms后调用它,转发它在after
我错过了您的代码可能存在的其他问题,但我希望这会有所帮助。