2011-09-04 23 views
6

Tôi có một khung Tkinter và một nút gắn liền với nó:Tkinter ràng buộc một hàm với đối số cho một widget

from tkinter import * 

def rand_func(a,b,c,effects): 
    print (a+b+c) 

root=Tk() 
frame=Frame(root) 
frame.bind("<Return>",lambda a=10, b=20, c=30: rand_func(a,b,c)) 
frame.pack() 

button=Button(frame, text="click me", command=lambda a=1,b=2,c=3,eff=None:rand_func(a,b,c)) 
button.pack() 

root.mainloop() 

Tôi muốn các chức năng tương tự được thực hiện khi người dùng nhấn vào và khi ông nhấn nút. Đáng buồn thay, đoạn mã trên đưa ra một lỗi ở khung gắn kết. Có ai biết giải pháp cho vấn đề này không?

Trả lời

12

Khi bạn tạo một ràng buộc với bind, Tkinter tự động thêm một cuộc tranh cãi rằng có thông tin về sự kiện này. Bạn sẽ cần tính đến điều đó theo định nghĩa rand_func hoặc cách bạn gọi nó.

Đối số này là không được bao gồm khi bạn sử dụng thuộc tính command. Bạn phải cẩn thận để tính toán đối số bổ sung này hoặc trong cách bạn gọi hàm trong mỗi trường hợp hoặc trong cách hàm giải thích các tham số của nó.

Đây là một giải pháp sử dụng lambda trong ràng buộc để chấp nhận sự kiện bổ sung chỉ khi sử dụng lệnh bind, nhưng không chuyển cho lệnh cuối cùng.

import tkinter as tk 

class SampleApp(tk.Tk): 
    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 
     self.frame = tk.Frame(self) 
     self.frame.pack() 
     self.button = tk.Button(self.frame, text="click me", 
          command=lambda a=1, b=2, c=3: 
           self.rand_func(a, b, c)) 
     self.button.pack() 
     self.frame.bind("<Return>", 
         lambda event, a=10, b=20, c=30: 
          self.rand_func(a, b, c)) 
     # make sure the frame has focus so the binding will work 
     self.frame.focus_set() 

    def rand_func(self, a, b, c): 
     print "self:", self, "a:", a, "b:", b, "c:", c 
     print (a+b+c) 

app = SampleApp() 
app.mainloop() 

Điều đó đang được nói, hiếm khi ràng buộc vào khung là điều đúng đắn phải làm. Thông thường một khung hình sẽ không có tiêu điểm bàn phím, và trừ khi nó có tiêu điểm thì ràng buộc sẽ không bao giờ cháy. Nếu bạn đang thiết lập một ràng buộc toàn cục, bạn nên liên kết với thẻ ràng buộc "tất cả" (sử dụng phương thức bind_all) hoặc với tiện ích con.

+0

Cảm ơn rất nhiều, như bạn đã đề xuất bind_all là những gì tôi cần; –

+0

Điều quan trọng cần lưu ý là việc tự động thêm đối số có thông tin về event_ chỉ áp dụng cho các cuộc gọi bị ràng buộc bởi phương thức 'bind'. Những ràng buộc với tùy chọn 'command' (trong constructor hoặc với' configure() ') không nhận được đối tượng sự kiện như vậy. Sự khác biệt này không dễ dàng phát hiện trong tài liệu (ít nhất là tôi không tìm thấy bất kỳ tài liệu nào), nhưng đây là [xác nhận] (https://stackoverflow.com/questions/36726716/what-is-the-difference-between- command-and-bind-in-tkinter) –

+1

@ o'rety: Tôi đã cập nhật câu trả lời để giải quyết các thắc mắc của bạn. –

1

Làm thế nào về:

from Tkinter import * 

def rand_func(eff=None,a=1,b=2,c=3): 
    print (a+b+c) 

root=Tk() 
root.bind("<Return>",lambda eff:rand_func(eff,a=10,b=20,c=30)) 

frame=Frame(root) 
frame.pack() 

button=Button(frame, text="click me", command=lambda:rand_func(None,1,2,3)) 
button.pack() 

root.mainloop() 
+0

Quên để viết mã mà các đối số khác nhau, chỉnh sửa câu hỏi –

Các vấn đề liên quan