我為 tkinter 創建了一個自定義小部件,其中布置了 5 個按鈕。該小部件在大多數情況下運行良好。問題是我無法弄清楚如何將用戶在小部件中按下的按鈕傳遞給主應用程式。自定義小部件將最后按下的按鈕存盤在一個變數中,但我無法弄清楚如何讓主應用程式看到它已被更改,而無需將按鈕釋放事件系結到 root。我想嘗試進一步構建這個自定義小部件,我希望它可以作業而不必做一些凌亂的黑客攻擊。理想情況下,在下面的示例中,當按下按鈕時,標簽應更改以反映按下的按鈕。例如,如果用戶單擊“2”按鈕,則標簽應更改為“2 X 2 = 4”。如何將按鈕上的文本直接傳遞給主應用程式使用?希望我說得夠清楚了。我希望能夠像使用 .get() 方法的任何其他 tkinter 小部件一樣從小部件中獲取值。這是我正在使用的代碼:
import tkinter as tk
from tkinter import ttk
class ButtonBar(tk.Frame):
def __init__(self, parent, width=5, btnLabels=''):
tk.Frame.__init__(self, parent)
self.btnLabels = []
self.btnNames = []
self.setLabels(btnLabels)
self.selButton = None
self.display()
def getPressedBtn(self,t):
"""
This method will return the text on the button.
"""
self.selButton = t
print(t)
def createBtnNames(self):
"""
This method will create the button names for each button. The button
name will be returned when getPressedBtn() is called.
"""
for i in range(0,5):
self.btnNames.append(self.btnLabels[i])
def display(self):
"""
This method is called after all options have been set. It will display
the ButtonBar instance.
"""
self.clear()
for i in range(len(self.btnLabels)):
self.btn = ttk.Button(self, text=self.btnLabels[i], command=lambda t=self.btnNames[i]: self.getPressedBtn(t))
self.btn.grid(row=0, column=i)
def setLabels(self, labelList):
if labelList == '':
self.btnLabels = ['1', '2', '3', '4', '5']
self.createBtnNames()
else:
btnLabelStr = list(map(str, labelList))
labelsLen = len(btnLabelStr)
def clear(self):
"""
This method clears the ButtonBar of its data.
"""
for item in self.winfo_children():
item.destroy()
root = tk.Tk()
def getButtonClicked(event):
global selBtn
print(event)
if example.winfo_exists():
selBtn = example.selButton
answer = int(selBtn) * 2
myLabel.config(text='2 X ' selBtn ' = ' str(answer))
tabLayout = ttk.Notebook(root)
tabLayout.pack(fill='both')
vmTab = tk.Frame(tabLayout)
myLabel = tk.Label(vmTab, text='2 X 0 = 0', width=50, height=10)
myLabel.pack()
vmTab.pack(fill='both')
tabLayout.add(vmTab, text='Volume Movers')
# Create the ButtonBar.
example = ButtonBar(vmTab)
selBtn = None
example.pack()
lbl = tk.Label(root, text='')
root.mainloop()
我看過其他一些關于 stackoverflow 的帖子。這個在 tkinter 中創建自定義小部件非常有幫助,但它沒有解決按鈕問題。我認為使用 Tkinter 進行子類化可能會有所幫助。我不明白如果我使用 系結事件root.bind("<ButtonRelease-1>", getButtonClicked),那么小部件作業正常。有沒有其他方法可以做到這一點?
uj5u.com熱心網友回復:
我會說你讓代碼變得比它應該的更復雜,你真的只需要創建按鈕并給它們一些作為引數傳遞的回呼。并且該回呼應至少采用一個引數,即按鈕上的文本,該文本也將傳遞給該回呼。
import tkinter as tk
from tkinter import ttk
class ButtonBar(tk.Frame):
def __init__(self, master, values: list, command=None):
tk.Frame.__init__(self, master)
for col, text in enumerate(values):
btn = ttk.Button(self, text=text)
if command is not None:
btn.config(command=lambda t=text: command(t))
btn.grid(row=0, column=col, sticky='news')
def change_label(val):
res = 2 * int(val)
new_text = f'2 X {val} = {res}'
my_label.config(text=new_text)
root = tk.Tk()
my_label = tk.Label(root, text='2 X 0 = 0')
my_label.pack(pady=100)
texts = ['1', '2', '3', '4', '5']
example = ButtonBar(root, values=texts, command=change_label)
example.pack()
root.mainloop()
您還可以將按鈕基于值串列,以便您可以指定任何值,并且它將創建具有該文本的按鈕,按下它們將呼叫帶有文本引數的給定函式。這樣你就可以像其他任何小部件一樣使用它,它需要主檔案、一些值(文本)和一個命令。然后您只需創建該回呼,它將采用該引數,然后相應地更改標簽。(我也洗掉了所有筆記本的東西,但我只是展示了如何實作你的要求)
另外:
我強烈建議遵循PEP 8 - Python 代碼風格指南。函式名和變數名應該在snake_case,類名應該在CapitalCase. 在函式和類宣告周圍有兩個空行。物件方法定義周圍有一個空行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/387098.html
標籤:Python 蟒蛇-3.x 特金特 事件处理 tkinter-button
