简体   繁体   中英

entry does not respond correctly to buttons' binding in python

I'm trying to program a calculator in python for a while now and there is a problem with my entry that I can't solve it although I don't see any problem with it.

so here is an example for my code:

from Tkinter import *

window =Tk()
window.title("Calculator")
#creating an entry
string=StringVar
entry = Entry(window, width=40,textvariable=string )
entry.grid(row=0, column=0, columnspan=6, ipady=10)
entry.focus()


#basically I have a function for creating buttons but here I will do it the traditional way.

num_one=Button(window,text="1",width=2,height=2,padx=20,pady=20,)
num_one.grid(row=1,column=0,padx=1,pady=1)

#crating an index for the calculator
index=0
#creating a function to insert the number one to the entry in the index position and then add one to the index

def print_one(index):
    entry.insert(index,"1")

binding the num_one button to the function above

num_one.bind("Button-1",print_one(index))

Now the problem is that the string "1" should be entered to the entry only if I click n the num_one button, but when I start the program automatically the number "1" goes into the entry.

Lots of issues that I noticed in your code -

  1. string=StringVar - You need to call it like StringVar() , otherwise you are just setting StringVar class (not its object) to `string.

  2. When you do -

     num_one.bind("Button-1",print_one(index)) 

    You actually call the function first and bind the return value , you should instead bind the function object (without calling it) , Example -

     num_one.bind("<Button-1>",print_one) 
  3. For binding the function to left mouse click, you need to bind to <Button-1> (notice the < and > at the ends) not Button-1 .

  4. In your function, the first parameter you will recieve (the function that is bound) is the event object , not the next index. You can instead use something like -

     string.set(string.get() + "1") 

As Anand says, there are various problems with your current code, both in the syntax & the design.

I'm not sure why you want to track the Entry's index yourself, since the Entry widget already does that. To insert text at the current cursor position you can use Tkinter.INSERT in the entry.insert() method call.

It looks like you intend to write a separate callback function for each of the number buttons. That's unnecessary, and it could get messy.

The code below shows a way to use a single callback function for multiple buttons. We attach the button's number as an attribute to the button itself. The callback function can easily access that number because the Event object argument that the callback is called with contains the widget that activated it as an attribute.

Note that my code uses import Tkinter as tk rather than from Tkinter import * . Sure, it makes the code a little more long-winded, but it prevents name collision.

import Tkinter as tk

window = tk.Tk()
window.title("Calculator")

entry_string = tk.StringVar()
entry = tk.Entry(window, width=40, textvariable=entry_string)
entry.grid(row=0, column=0, columnspan=6, ipady=10)
entry.focus()

def button_cb(event):
    entry.insert(tk.INSERT, event.widget.number)

for i in range(10):
    y, x = divmod(9 - i, 3)
    b = tk.Button(window, text=i, width=2, height=2, padx=20, pady=20)
    b.grid(row=1+y, column=2-x, padx=1, pady=1)
    #Save this button's number so it can be accessed in the callback
    b.number = i
    b.bind("<Button-1>", button_cb)

window.mainloop()

Ideally, GUI code should go into a class, as that makes it easier for the widgets to share data, and it tends to make the code neater.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM