我對 tkinter(和 OOP)比較陌生,并且正在嘗試制作一個帶有第二個偏好視窗的 gui。如果我以相反的順序關閉它們,則沒有問題,但我試圖使它們能夠無序關閉(以便關閉主視窗關閉子視窗)。
我嘗試系結一個簡單的函式來關閉視窗,如果它存在的話,在父級銷毀時,雖然它看起來不一致。有時它會關閉子視窗,有時它會凍結,我不得??不關閉內核。我不確定凍結的原因,因為它似乎發生在關閉子視窗之后。作為完整代碼中的快速說明,當滑鼠懸停在按鈕上時,我使用 tkmacosx 更改按鈕的背景。
這是我的一個作業示例代碼的子集,可能還有其他問題。我的測驗還有一些額外的東西(例如系結破壞子視窗到回傳鍵并在函式內列印)
import tkinter as tk
from tkinter import ttk
import tkinter.filedialog as fd
import os
from tkmacosx import Button
from tkmacosx import Marquee
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
self.mainframe = tk.Frame(parent)
self.mainframe.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S))
self.mainframe.columnconfigure(0, weight=1)
self.mainframe.rowconfigure(0, weight=1)
self.create_widgets()
self.parent.update()
self.window = None
self.parent.geometry(str(self.parent.winfo_width()) "x" str(self.parent.winfo_height()) \
" " str((self.parent.winfo_screenwidth()-self.parent.winfo_width())//2)\
" " str(int((self.parent.winfo_screenheight()-self.parent.winfo_height())*.4)))
self.parent.bind("<Destroy>", self.Destroy_subwindow)
self.parent.bind('<Return>', self.Destroy_subwindow)
def Destroy_subwindow(self, event):
if self.window is not None:
print("closing subwindow")
self.window.destroy()
def create_widgets(self):
self.filepath = ttk.Entry(self.mainframe, width=10)
self.filepath.grid(column = 1, row = 0)
ttk.Label(self.mainframe, text="Input Directory:").grid(column=0, row=0, sticky=tk.W)
# Preferences
self.advOptions = Button(self.mainframe, text = "Preferences", command = self.Preferences,\
borderless = 1,highlightthickness = 0, width = 90, \
overbackground = '#227afe',activebackground = ('#227afe','#0b60ff'),\
activeforeground = "white", overforeground = 'white')
self.advOptions.bind('<Return>', self.Preferences)
self.advOptions.grid(column = 3, row = 1, sticky = tk.E)
def Preferences(self, event = None):
self.window = tk.Toplevel(root)
self.window.title("Preferences")
self.style = ttk.Style(self.window)
self.style.theme_settings( "aqua", settings={
"TNotebook.Tab": {
"configure": {"padding": [5, 1], "background": "#e7e7e9","foreground": "black" },
"map": {"background": [("selected", "#cfcfd1")], "foreground":[("selected", "black")],\
"expand": [("selected", [1, 1, 1, 0])] } } } )
self.tabcontrol = ttk.Notebook(self.window)
self.tab1 = ttk.Frame(self.window)
self.tabcontrol.add(self.tab1, text = "Plot")
root = tk.Tk()
root.title("Kinetic Plotting")
MainApplication(root)
root.mainloop()
如果需要,這里是完整的代碼:
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
self.mainframe = tk.Frame(parent)
self.mainframe.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S))
self.mainframe.columnconfigure(0, weight=1)
self.mainframe.rowconfigure(0, weight=1)
self.create_widgets()
self.parent.update()
self.window = None
self.parent.geometry(str(self.parent.winfo_width()) "x" str(self.parent.winfo_height()) \
" " str((self.parent.winfo_screenwidth()-self.parent.winfo_width())//2)\
" " str(int((self.parent.winfo_screenheight()-self.parent.winfo_height())*.4)))
self.parent.bind("<Destroy>", self.Destroy_subwindow)
self.parent.bind('<Return>', self.Destroy_subwindow)
def Destroy_subwindow(self, event):
if self.window is not None:
print("closing subwindow")
self.window.destroy()
def create_widgets(self):
global tempdir, fittingEquation, saveFileType
# Directory input
self.filepath = ttk.Entry(self.mainframe, width=10)
self.filepath.grid(column = 1, row = 0)
ttk.Label(self.mainframe, text="Input Directory:").grid(column=0, row=0, sticky=tk.W)
self.browseButton = Button(self.mainframe, text = "Browse", command = self.Browse_files,\
borderless = 1,highlightthickness = 0, width = 80, \
overbackground = '#227afe',activebackground = ('#227afe','#0b60ff'),\
activeforeground = "white", overforeground = 'white')
self.browseButton.bind('<Return>', self.Browse_files)
self.browseButton.grid(column = 3, row = 0, sticky = tk.E)
# Preferences
self.advOptions = Button(self.mainframe, text = "Preferences", command = self.Preferences,\
borderless = 1,highlightthickness = 0, width = 90, \
overbackground = '#227afe',activebackground = ('#227afe','#0b60ff'),\
activeforeground = "white", overforeground = 'white')
self.advOptions.bind('<Return>', self.Preferences)
self.advOptions.grid(column = 3, row = 1, sticky = tk.E)
# Image type dropdown
self.imageOptions = [".jpg", ".png", ".tiff"]
self.var2 = tk.StringVar(self.mainframe)
self.var2.set(self.imageOptions[0]) # initial value
saveFileType = self.imageOptions[0]
self.imageOption = tk.OptionMenu(self.mainframe, self.var2, *self.imageOptions, command = self.get_savetype)
self.imageOption.grid(columnspan = 2,row = 1, sticky = tk.W)
# Fitting Equation dropdown
self.Options = ["Single Exponential", "Double Exponential", "Control (Flat)"]
self.var = tk.StringVar(self.mainframe)
self.var.set(self.Options[0]) # initial value
fittingEquation = self.Options[0]
self.option = tk.OptionMenu(self.mainframe, self.var, *self.Options, command = self.get_variable)
self.option.grid(columnspan = 2,row = 2, sticky = tk.W)
def set_text(self, text):
self.filepath.delete(0,tk.END)
self.filepath.insert(0,text)
def Browse_files(self):
global tempdir
self.currdir = os.getcwd()
self.tempdir = fd.askdirectory(parent=root, initialdir=self.currdir, title='Please select a directory')
self.set_text(self.tempdir)
tempdir = self.tempdir
def get_variable(self, var):
global fittingEquation
fittingEquation = self.var.get()
def get_savetype(self, var2):
global saveFileType
saveFileType = self.var2.get()
def PlotOptionsWidgets(self):
self.tab1.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S))
self.tab1.columnconfigure(0, weight=1)
self.tab1.rowconfigure(0, weight=1)
# Errorbar checkbox
self.errorvar = tk.IntVar(value = 1)
self.checkerror = tk.Checkbutton(self.tab1, text = "Errorbars (only plotting)", variable = self.errorvar, \
onvalue = 1, offvalue = 0,bg = "#e4e4e4")
self.checkerror.grid(column = 0, row = 0, columnspan = 5)
# Column Labels
ttk.Label(self.tab1, text = "Linear Plots (kobs vs conc)").grid(column = 3, row=1, columnspan = 2)
ttk.Label(self.tab1, text = "Kinetic Traces (F vs time)").grid(column = 0, row=1, columnspan = 2)
# Figure Sizes
self.linearFigureSize = tk.StringVar(value = "2.45, 1")
self.linearFigureSizeEntry = ttk.Entry(self.tab1,textvariable =self.linearFigureSize, width=10)
self.linearFigureSizeEntry.grid(column = 4, row = 2, sticky = tk.W)
ttk.Label(self.tab1, text="Figure Size (in, in)").grid(column=3, row=2, sticky=tk.E)
self.KineticFigureSize = tk.StringVar(value = "2.49, 2.32")
self.KineticFigureSizeEntry = ttk.Entry(self.tab1,textvariable =self.KineticFigureSize, width=10)
self.KineticFigureSizeEntry.grid(column = 1, row = 2, sticky = tk.W)
ttk.Label(self.tab1, text="Figure Size (in, in)").grid(column=0, row=2, sticky=tk.E)
# Axes limits
self.leftAxisLimit = tk.StringVar(value = "Auto")
self.leftAxisLimitentry = ttk.Entry(self.tab1,textvariable =self.leftAxisLimit, width=10)
self.leftAxisLimitentry.grid(column = 1, row = 5, sticky = tk.W)
ttk.Label(self.tab1, text="Left x limit (time)").grid(column=0, row=5, sticky=tk.E)
self.rightAxisLimit = tk.StringVar(value = "Auto")
self.rightAxisLimitentry = ttk.Entry(self.tab1,textvariable =self.rightAxisLimit, width=10)
self.rightAxisLimitentry.grid(column = 1, row = 6, sticky = tk.W)
ttk.Label(self.tab1, text="Right x limit (time)").grid(column=0, row=6, sticky=tk.E)
self.leftAxisLimitConc = tk.StringVar(value = "Auto")
self.leftAxisLimitConcentry = ttk.Entry(self.tab1,textvariable =self.leftAxisLimitConc, width=10)
self.leftAxisLimitConcentry.grid(column = 4, row = 5, sticky = tk.W)
ttk.Label(self.tab1, text="Left x limit (conc.)").grid(column=3, row=5, sticky=tk.E)
self.rightAxisLimitConc = tk.StringVar(value = "Auto")
self.rightAxisLimitConcentry = ttk.Entry(self.tab1,textvariable =self.rightAxisLimitConc, width=10)
self.rightAxisLimitConcentry.grid(column = 4, row = 6, sticky = tk.W)
ttk.Label(self.tab1, text="Right x limit (conc.)").grid(column=3, row=6, sticky=tk.E)
# Axes titles
self.xAxisTitle = tk.StringVar(value = "Time (s)")
self.xAxisTitleEntry = ttk.Entry(self.tab1,textvariable =self.xAxisTitle, width=10)
self.xAxisTitleEntry.grid(column = 1, row = 3, sticky = tk.W)
ttk.Label(self.tab1, text="x-Axis Label").grid(column=0, row=3, sticky=tk.E)
self.yAxisTitle = tk.StringVar(value = "Rel. Emission Intensity")
self.yAxisTitleEntry = ttk.Entry(self.tab1,textvariable =self.yAxisTitle, width=10)
self.yAxisTitleEntry.grid(column = 1, row = 4, sticky = tk.W)
ttk.Label(self.tab1, text="y-Axis Label").grid(column=0, row=4, sticky=tk.E)
self.xAxisTitleLinear = tk.StringVar(value = "[Ion] (Units)")
self.xAxisTitleLinearEntry = ttk.Entry(self.tab1,textvariable =self.xAxisTitleLinear, width=10)
self.xAxisTitleLinearEntry.grid(column = 4, row = 3, sticky = tk.W)
ttk.Label(self.tab1, text="x-Axis Label").grid(column=3, row=3, sticky=tk.E)
self.yAxisTitleLinear = tk.StringVar(value = "kobs (Units)")
self.yAxisTitleLinearEntry = ttk.Entry(self.tab1,textvariable =self.yAxisTitleLinear, width=10)
self.yAxisTitleLinearEntry.grid(column = 4, row = 4, sticky = tk.W)
ttk.Label(self.tab1, text="y-Axis Label").grid(column=3, row=4, sticky=tk.E)
# Font options
self.LinearFont = tk.StringVar(value = "Arial")
self.LinearFontEntry = ttk.Entry(self.tab1, textvariable = self.LinearFont, width = 10)
self.LinearFontEntry.grid(column = 4, row = 7, sticky=tk.W)
ttk.Label(self.tab1, text = "Font Style").grid(column = 3, row = 7, sticky=tk.E)
self.LinearFontSize = tk.DoubleVar(value = 10)
self.LinearFontSizeEntry = ttk.Entry(self.tab1, textvariable = self.LinearFontSize, width = 10)
self.LinearFontSizeEntry.grid(column = 4, row = 8, sticky=tk.W)
ttk.Label(self.tab1, text = "Font Size").grid(column = 3, row = 8, sticky=tk.E)
self.ExponentialFont = tk.StringVar(value = "Arial")
self.ExponentialFontEntry = ttk.Entry(self.tab1, textvariable = self.ExponentialFont, width = 10)
self.ExponentialFontEntry.grid(column = 1, row = 7, sticky=tk.W)
ttk.Label(self.tab1, text = "Font Style").grid(column = 0, row = 7, sticky=tk.E)
self.ExponentialFontSize = tk.DoubleVar(value = 10)
self.ExponentialFontSizeEntry = ttk.Entry(self.tab1, textvariable = self.ExponentialFontSize, width = 10)
self.ExponentialFontSizeEntry.grid(column = 1, row = 8, sticky=tk.W)
ttk.Label(self.tab1, text = "Font Size").grid(column = 0, row = 8, sticky=tk.E)
def RegressionOptionsWidgets(self):
self.tab2.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S))
self.tab2.columnconfigure(0, weight=1)
self.tab2.rowconfigure(0, weight=1)
# Dead time
self.deadTime= tk.DoubleVar(value = 0.01)
self.deadTimeEntry = ttk.Entry(self.tab2, textvariable = self.deadTime, width = 10)
self.deadTimeEntry.grid(column = 3, row = 4, sticky = tk.W)
ttk.Label(self.tab2, text = "Dead Time (s)").grid(column = 0,row = 4, sticky = tk.E, columnspan = 3)
# Weighting
self.weightExp = tk.IntVar(value = 1)
self.checkWeightExp = tk.Checkbutton(self.tab2, text = "Weight Exponential Fit", variable = self.weightExp, \
onvalue = 1, offvalue = 0,bg = "#e4e4e4")
self.checkWeightExp.grid(column = 0, row = 0, columnspan = 5, sticky = tk.W)
self.weightLinear = tk.IntVar(value = 1)
self.checkWeightLinear = tk.Checkbutton(self.tab2, text = "Weight Linear Fit", variable = self.weightLinear, \
onvalue = 1, offvalue = 0,bg = "#e4e4e4")
self.checkWeightLinear.grid(column = 0, row = 1, columnspan = 5, sticky = tk.W)
# Biasing
self.outliers = tk.IntVar(value = 0)
self.checkOutliers = tk.Checkbutton(self.tab2, text = "Check for Outliers", variable = self.outliers, \
onvalue = 1, offvalue = 0,bg = "#e4e4e4")
self.checkOutliers.grid(column = 0, row = 2, columnspan = 5, sticky = tk.W)
self.intialParam = tk.IntVar(value = 1)
self.checkInitialParam = tk.Checkbutton(self.tab2, text = "Calculate Initial Parameters", variable = self.intialParam, \
onvalue = 1, offvalue = 0,bg = "#e4e4e4")
self.checkInitialParam.grid(column = 0, row = 3, columnspan = 5, sticky = tk.W)
def OutputOptionsWidgets(self):
self.tab3.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S))
self.tab3.columnconfigure(0, weight=1)
self.tab3.rowconfigure(0, weight=1)
# DPI output
self.outDpi = tk.StringVar(value = "600")
self.outDpiEntry = ttk.Entry(self.tab3,textvariable =self.outDpi, width=10)
self.outDpiEntry.grid(column = 4, row = 0, sticky = tk.W)
ttk.Label(self.tab3, text="DPI output").grid(column=2, row=0, columnspan = 2)
def resizingfunction(self, event = None):
global tabcontrolw, tabcontrolh
self.active_tab = self.tabcontrol.index(self.tabcontrol.select())
if self.active_tab != 1:
self.window.geometry(str(tabcontrolw) "x" str(tabcontrolh))
elif self.active_tab == 1:
self.window.geometry(str(int(tabcontrolw*.7)) "x" str(int(tabcontrolh*.6)))
def Preferences(self, event = None):
self.window = tk.Toplevel(root)
self.window.title("Preferences")
self.style = ttk.Style(self.window)
self.style.theme_settings( "aqua", settings={
"TNotebook.Tab": {
"configure": {"padding": [5, 1], "background": "#e7e7e9","foreground": "black" },
"map": {"background": [("selected", "#cfcfd1")], "foreground":[("selected", "black")],\
"expand": [("selected", [1, 1, 1, 0])] } } } )
self.tabcontrol = ttk.Notebook(self.window)
self.tab1 = ttk.Frame(self.window)
self.PlotOptionsWidgets()
self.tab2 = ttk.Frame(self.window)
self.RegressionOptionsWidgets()
self.tab3 = ttk.Frame(self.window)
self.OutputOptionsWidgets()
self.tabcontrol.add(self.tab1, text = "Plot")
self.tabcontrol.add(self.tab2, text = "Regression")
self.tabcontrol.add(self.tab3, text = "Output")
self.tabcontrol.pack(expand = 1, fill = "both")
self.window.update()
global tabcontrolw, tabcontrolh
tabcontrolw = self.tabcontrol.winfo_width()
tabcontrolh = self.tabcontrol.winfo_height()
self.tabcontrol.bind("<<NotebookTabChanged>>", self.resizingfunction)
root = tk.Tk()
root.title("Kinetic Plotting")
MainApplication(root)
root.mainloop()
uj5u.com熱心網友回復:
請注意,我無法復制您在破壞子視窗時遇到的錯誤。但是,當您嘗試銷毀單個視窗時,您可能會遇到問題,而您可以只銷毀主視窗(如@furas 所說)。只需呼叫self.parent.destroy()您的Destroy_subwindow函式。
def Destroy_subwindow(self, event):
self.parent.destroy()
還有一種方法可以將<Destroy>和<Return>事件系結到此函式。您可以使用協議處理程式。這允許您在用戶使用視窗管理器顯式關閉視窗時進行處理。您如何實作這一點的示例如下。
import tkinter as tk
class MainApplication():
def __init__(self, parent):
# Main window
self.parent = parent
but1 = tk.Button(self.parent, text="Main window", width = 30, command=self.sub_window)
but1.pack()
self.parent.protocol("WM_DELETE_WINDOW", self.on_main_close)
def sub_window(self):
# Sub window(s)
self.window = tk.Toplevel(self.parent)
but2 = tk.Button(self.window, text="Sub window", width = 30)
but2.pack()
def on_main_close(self):
print("Closing everything")
self.parent.destroy()
root = tk.Tk()
app = MainApplication(root)
root.mainloop()
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/356579.html
