0

This is my first foray into tkinter. I used an object-oriented approach for my application, but cannot get variable values displayed in tkinter labels. I am using python 3.7.1.

I have tried many suggestions from other posts, such as converting my strings to tkinter's StringVar() and displaying those, both with 'text=...' and 'textvariable=...' but so far everything has proven to be unfruitful.

import tkinter as tk

class NPCApp(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        self.profession = None

        for F in (StartPage, PageOne):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, stick="nsew")

        self.show_frame(StartPage)


    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

    def setProfession(self, given_profession):
        self.profession = given_profession

    def getProfession(self):
        return self.profession


class StartPage(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)
        tk.Label(self, text="Choose a profession for your NPC:").pack(pady=10, padx=10)

        tk.Radiobutton(self, text="Herbalist/Alchemist", variable=controller.profession, value="Herbalist", command=lambda: controller.setProfession("Herbalist")).pack()
        tk.Radiobutton(self, text="Blacksmith", variable=controller.profession, value="Smith", command=lambda: controller.setProfession("Smith")).pack()
        tk.Radiobutton(self, text="Shopkeeper", variable=controller.profession, value="Shopkeep", command=lambda: controller.setProfession("Shopkeep")).pack()
        tk.Radiobutton(self, text="Innkeep", variable=controller.profession, value="Innkeep", command=lambda: controller.setProfession("Innkeep")).pack()
        tk.Radiobutton(self, text="Officer of the city watch", variable=controller.profession, value="Officer", command=lambda: controller.setProfession("Officer")).pack()
        tk.Radiobutton(self, text="Member of the city watch", variable=controller.profession, value="Soldier", command=lambda: controller.setProfession("Soldier")).pack()
        tk.Radiobutton(self, text="Member of a council of elders", variable=controller.profession, value="Councilmember", command=lambda: controller.setProfession("Councilmember")).pack()
        tk.Radiobutton(self, text="Regular citizen", variable=controller.profession, value="Citizen", command=lambda: controller.setProfession("Citizen")).pack()
        tk.Radiobutton(self, text="Foreign human", variable=controller.profession, value="Foreigner", command=lambda: controller.setProfession("Foreigner")).pack()

        tk.Button(self, text="To Page One",
                            command=lambda: controller.show_frame(PageOne)).pack()


class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        tk.Label(self, text=controller.getProfession()).pack(pady=10, padx=10)

        tk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(StartPage)).pack()


app = NPCApp()
app.mainloop()

What you can see here is my application. You use the Radiobuttons to choose from a selection of NPC professions and the corresponding value is set internally, which is tested and works fine. However, displaying said value on PageOne in the label does not work. The page shows a blank followed by the 'Back to Home'-button, but should show the chosen profession and then said button beneath it.

Help me Stack Overflow, you are my only hope.

10
  • There might be somethong wrong with set profession? Have you printed profession to see what value it becomes once it's set?
    – WiseDev
    Commented Jun 13, 2019 at 11:26
  • I have done that, and it displays the value on the CLI just fine.
    – DaveMitHut
    Commented Jun 13, 2019 at 11:27
  • For me it displays None. I'm almost sure your lambda functions are incorrect. You are not supposed to pass an argument directly in your lambda callback.
    – WiseDev
    Commented Jun 13, 2019 at 11:29
  • If I add a button to PageOne with the following code, it prints the right values all the time: tk.Button(self, text="Print Value", command=lambda: print (controller.getProfession())).pack()
    – DaveMitHut
    Commented Jun 13, 2019 at 11:31
  • what I mean is your callback needs to be anonymous. i.e. something like command=controller.getProfession , so without calling it. It only needs be called once you click on it (hence the callback)
    – WiseDev
    Commented Jun 13, 2019 at 11:34

1 Answer 1

1

I suggest you make the getProfession return a StringVar and change setProfession to set that StringVar (create it in the __init__. Then you can create your tk.Label with textvariable=controller.getProfession() and the label text will be updated from the StringVar whenever you call setProfession.

class NCApp(tk.Tk):
    def __init__(...):
        self.profession = tk.StringVar()
        ...
    def setProfession(self, given_profession):
        self.profession.set(given_profession)
    def getProfession(self):
        return self.profession

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.label = tk.Label(self, textvariable=controller.getProfession())
        self.label.pack(pady=10, padx=10)
        ...
1
  • Thank you very much patthoyts, I guess what I tried with StringVar() was wrong then, because this worked! Thanks again!
    – DaveMitHut
    Commented Jun 13, 2019 at 11:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.