最近剛拿起 tkinter
我有一個程式,當用戶單擊 [...] 按鈕時,它將顯示一個頂層視窗,其中包含一個日歷和其中的 [OK] 按鈕。
當用戶單擊 [OK] 按鈕時,我希望它在主視窗中更改 [startDate] 變數和 [labelStartDate] 標簽。我的下一個資料處理需要 [startDate] 變數。和 [labelStartDate] 標簽是向用戶顯示日期已更改。
如何做到這一點?我嘗試使用 command=lambda 或 stringvar,但老實說,我在嘗試將它應用到我的程式時有點迷失了。


from datetime import date
from textwrap import fill
import tkinter as tk
from tkinter import ttk
from tkinter import Toplevel
from tkinter import font
from tkcalendar import Calendar
from turtle import color, width
# Define the GUI
class App(tk.Tk):
def __init__(self):
super().__init__()
# root window
self.title('Main Window')
self.geometry('620x570')
global startDate #variable that I want to use for later data processing
startDate = date.today().strftime("%Y/%m/%d/")
#DATE MENU FRAME
DateMenuBar = ttk.LabelFrame(self.master, borderwidth = 1, text='Setting')
subFrame2 = tk.Frame(DateMenuBar, borderwidth = 1, relief = tk.FLAT, pady=0, padx=0)
#SUB FRAME 2
labelStart = tk.Label(subFrame2, text='Start',font=('meiryoui', 15))
labelStartDate = tk.Label(subFrame2, text=startDate,font=('meiryoui', 15))
btnOpenCalendar1 = tk.Button(subFrame2, height=1, background='#eeeeee', text='...', font=('meiryoui', 8), command=self.changeStartDate)
labelStart.pack(side = tk.LEFT, ipadx=10)
labelStartDate.pack(side = tk.LEFT, padx=(30,10))
btnOpenCalendar1.pack(side = tk.LEFT)
subFrame2.pack(fill = tk.X,padx=0, pady=10)
DateMenuBar.pack(fill = tk.X,padx=20, ipadx=20, ipady=20)
def changeStartDate(self):
window = Window(self)
window.grab_set()
class Window(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.title("Pick Date")
self.geometry("250x250")
def selectStartDate():
startDate = cal.get_date()
#I got stuck here, trying to figure out how to change the labelStartDate's text
cal = Calendar(self, selectmode = 'day')
cal.pack(padx=20, pady=10)
frame = tk.Frame(self, borderwidth = 1, relief = tk.FLAT, pady=10, padx=20)
btnOK = tk.Button(frame, height=2,width=8, background='#eeeeee', text='OK', font=('meiryoui', 9),command=selectStartDate)
btnCancel = tk.Button(frame, height=2,width=8, background='#eeeeee', text='Cancel', font=('meiryoui', 9))
btnOK.pack(side = tk.RIGHT, padx=(10,0))
btnCancel.pack(side = tk.RIGHT)
frame.pack(fill = tk.X)
if __name__ == "__main__":
app = App()
app.mainloop()
編輯說明: 我將缺少的代碼添加到我的程式中,以便其他人可以運行它:)
uj5u.com熱心網友回復:
您可以先使用 tkinter.StringVar() 并將標簽 textvariable 設定為相同,以便能夠修改標簽的 text。
self.labelStartDateVar = tk.StringVar() # Initalizing the text variable
self.labelStartDateVar.set(startDateData.start_date) # Setting initial value of the textvariable.
# Added textvariable as labelStartDateVar
self.labelStartDate = tk.Label(subFrame2, textvariable = labelStartDateVar, font = ('meiryoui', 15))
此外,利用這篇文章(觀察者模式)中的一些知識,可以在檢測到變化時呼叫函式startDate。我們通過定義一個新類并使用一個startDateData物件作為全域物件來做到這一點,并且要獲取 startDate 本身的值,我們只需要訪問它的 start_date 屬性startDateData.start_date來設定它,需要像這樣設定相同的屬性:
startDateData.start_date = cal.get_date()
完整的代碼看起來像這樣 -:
class startDate(object):
def __init__(self):
# Setting the default value as in the OP.
self._start_date = date.today().strftime("%Y年 %m月 %d日")
self._observers = []
return
@property
def start_date(self):
return self._start_date
@start_date.setter
def start_date(self, value):
self._start_date = value
for callback in self._observers:
print('announcing change')
callback(self._start_date)
return
def bind_to(self, callback):
print('bound')
self._observers.append(callback)
startDateData = startDate() # global startDateData object.
# Define the GUI
class App(tk.Tk):
def __init__(self):
super().__init__()
# root window
self.title('Main Window')
self.geometry('620x570')
global startDateData #variable that I want to use for later data processing
###
self.labelStartDateVar = tk.StringVar()
self.labelStartDateVar.set(startDateData.start_date)
startDateData.bind_to(self.updateStartDate) # Binding the updateStartDate function to be called whenever value changes.
###
#SUB FRAME 2
self.labelStart = tk.Label(subFrame2, text='開始',font=('meiryoui', 15))
# Added textvariable as labelStartDateVar
self.labelStartDate = tk.Label(subFrame2, textvariable = self.labelStartDateVar, font = ('meiryoui', 15))
self.btnOpenCalendar1 = tk.Button(subFrame2, height=1, background='#eeeeee', text='...', font=('meiryoui', 8), command=self.changeStartDate)
self.labelStart.pack(side = tk.LEFT, ipadx=10)
self.labelStartDate.pack(side = tk.LEFT, padx=(30,10))
self.btnOpenCalendar1.pack(side = tk.LEFT)
subFrame2.pack(fill = tk.X,padx=0, pady=10)
def updateStartDate(self, startDate) :
self.labelStartDateVar.set(startDate)
return
class Window(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.title("Pick Date")
self.geometry("250x250")
# Globally fetch the startDateData object.
global startDateData
def selectStartDate():
# All binded callbacks will be called, when the value is changed here.
startDateData.start_date = cal.get_date()
cal = Calendar(self, selectmode = 'day')
cal.pack(padx=20, pady=10)
frame = tk.Frame(self, borderwidth = 1, relief = tk.FLAT, pady=10, padx=20)
btnOK = tk.Button(frame, height=2,width=8, background='#eeeeee', text='OK', font=('meiryoui', 9),command=selectStartDate)
btnCancel = tk.Button(frame, height=2,width=8, background='#eeeeee', text='Cancel', font=('meiryoui', 9))
btnOK.pack(side = tk.RIGHT, padx=(10,0))
btnCancel.pack(side = tk.RIGHT)
frame.pack(fill = tk.X)
注意:作為 OP 中提供的代碼,不足以測驗此解決方案是否有效。此外,由于提供的初始代碼似乎不完整,最后答案中給出的完整代碼也可能看起來不完整,但仍實作了 OP 中給出的代碼中存在的所有功能。
編輯:該行的先前位置startDateData = startDate()是錯誤的,因為它試圖在定義之前構造一個類的物件,現在該行已移至startDate.
編輯 2:修正了一些錯別字,正如@Mario Ariyanto 的評論中提到的那樣。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/435644.html
