0

For a on screen keyboard i need 26 buttons that all add one of the letters of the keyboard to a string. The first problem i got is that the string doesn't get saved after pressing a button. For example, User presses 'A', 'A' gets printed and should be stored. User now presses 'B', 'B' gets printed and 'A' is gone. The second problem is that the button only executes the function the first time. My code so far down below:

window = Tk()
window.attributes('-fullscreen', True)
window.configure(background='yellow')
master = Frame(window)
master.pack()

e = Entry(master)
e.pack()
e.focus_set()

nieuw_station = ""

def printanswer():
  global nieuw_station
  nieuw_station = e.get()
  print(nieuw_station)
  gekozen_station(nieuw_station)


invoeren = Button(master, text="Invoeren", width=10, command=printanswer)
invoeren.pack()

def letter_toevoegen(nieuw_station, letter):
    nieuw_station += letter
    print(nieuw_station)
    return nieuw_station

a = Button(master, text="A", width=1, command=letter_toevoegen(nieuw_station, "a"))
a.pack()

b = Button(master, text="B", width=1, command=letter_toevoegen(nieuw_station, "b"))
b.pack()

window.mainloop()

The expected output would be: User presses 'A', 'A' get printed & stored. Now user presses 'B', 'AB' gets printed & stored. Lastly user presses 'C', 'ABC' now gets printed & stored. Whenever the user presses the 'invoeren' button it will get send to the next function with the new string as parameter(this actually works).

Mart N
  • 133
  • 10

1 Answers1

0

You've got a few problems. First, command expects you to pass a function, but you're passing the return value of a function. One fix is to wrap it in a lambda:

a = Button(master, text="A", width=1, command=lambda: letter_toevoegen(nieuw_station, "a"))
a.pack()

Second, I don't know what nieuw_station.close() and nieuw_station.open() are doing -- Strings don't have those methods.

Third, strings are immutable, so when you do nieuw_station += letter in letter_toevoegen, that change will not persist outside the function.

One way to actually get it to persist is to use global nieuw_station -- And then you probably can't pass it to the function.


With that said, 9 times out of 10 when you see a global statement, there's a better way using classes. Here, we can make a class that adds the buttons and keeps track of the state.

class App(object):
    def __init__(self):
        self.nieuw_station = ''

    def add_buttons(self):
        a = Button(master, text="A", width=1, command=lambda: self.letter_toevoegen("a"))
        a.pack()
        # ...

    def letter_toevoegen(self, letter):
        time.sleep(2)
        self.nieuw_station += letter
        print(self.nieuw_station)
        return self.nieuw_station

Of course, we'd add printanswer in here as well and add the "print answer" button, etc. The code to use the class would look something like:

app = App()
app.add_buttons()
window.mainloop()

There are a number of variants here that you'll see floating around. (some people like App to inherit from tkinter.Tk or some other tkinter widget, others will pass the parent widget to the class so that it can know where to attach all of the elements, etc.) The point that I'm trying to show is how you can use a class as a container for the data rather than the global namespace.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • Definitely did not know that. Gonna try it this way, thank you a-lot! Great in-depth explanation btw! – Mart N Oct 28 '15 at 15:44