1

I'm doing a game with tkinter and i need to allow the player to place buildings with the information of the x, the y and the orientation. I created this function :

def pageChoice():
    fenetre = Tk()
    fenetre['bg']='white'
    fenetre.title("Choose the position of your building")
    fenetre.geometry("500x600")
    Frame1 = Frame(fenetre, borderwidth=2, relief=GROOVE)
    Label(Frame1, text="choose the orientation of your building").pack(padx=10, pady=10)
    Frame1.pack(padx=30, pady=30)
    value=StringVar()
    orientation = IntVar()
    radiobutton_1 = Radiobutton(Frame1, text="Horizontal", variable=orientation, value=1)
    radiobutton_1.pack()
    radiobutton_2 = Radiobutton(Frame1, text="Vertical", variable=orientation, value=2)
    radiobutton_2.pack()

    Frame2 = Frame(fenetre, borderwidth=2, relief=GROOVE)
    Label(Frame2, text="type the coordinates of the center of your building").pack(padx=5, pady=5)
    Frame2.pack(padx=10, pady=10)
    Frame3 = Frame(Frame2, borderwidth=2, relief=GROOVE)
    Frame3['bg']='green'
    Label(Frame3, text="as x").pack(padx=10, pady=10)
    Frame3.pack(side=LEFT, padx=10, pady=30)
    Frame4 = Frame(Frame2, borderwidth=2, relief=GROOVE)
    Frame4['bg']='green'
    Label(Frame4, text="as y").pack(padx=10, pady=10)
    Frame4.pack(side=RIGHT, padx=10, pady=30)
    entree1 = Text(Frame3, width=10, height=1)
    entree1.pack()
    entree2 = Text(Frame4, width=10, height=1)
    entree2.pack()

    def printInput():
        ord = entree1.get(1.0, "end-1c")
        abs = entree2.get(1.0, "end-1c")
        print(ord, abs)
        ori = orientation.get()
        if ori == 1:
            print('horizontal')
        elif ori == 2:
            print('vertical')
        print(ori)


    bouton = Button(fenetre, text="validate", relief = RAISED, command=printInput) 
    bouton.pack()
    fenetre.mainloop()

print(pageChoix())

It works when I run it alone but when I call it with this other function, the radio button doesn't work and i cant get informations about the orientation :



MainJoueur1 = ['house','pool']

def Installation(L): # L is the list of buildings in inventory
    fenetre = Tk()
    fenetre.title("choose a building to place")
    fenetre.geometry("140x90")
    for i in range(len(L)):
        bi = Button(fenetre, text =L[i], relief=RAISED, command = pageChoix).pack()
    fenetre.mainloop()

print(Installation(MainJoueur1))

I don't get where is the problem, thanks for helping !

Bastien
  • 11
  • 1
  • What do you mean by "the radio button doesn't work"? Please describe what the function is doing in more detail. – M-Chen-3 Feb 19 '21 at 17:48
  • 2
    Calling `Tk()` more than once will cause all sorts of problems. Use `Toplevel()` instead to create additional windows. – jasonharper Feb 19 '21 at 17:49
  • The idea of the game is that the player has to create the more ecologic city he can. He starts with a wood and all along the game the player will turn this wood into a little city. Then the function called 'Installation' allows the player to choose a building among the buildings he can build, and after that the function 'pageChoix' allows he to choose the position of the building in the wood (which is an array in python language), and more preciasly he can choose the coordinates of the center of the building (absc and ord) and it's orientation (horizontal or vertical). – Bastien Feb 19 '21 at 17:56
  • See [Why are multiple instances of Tk discouraged?](https://stackoverflow.com/questions/48045401/why-are-multiple-instances-of-tk-discouraged) – martineau Feb 19 '21 at 17:59
  • I don't get why people dislike having multiple instances of `Tk()`. If you always give the tkinter objects the correct parent, it will work. In this case the variable `orientation` only exists in the first instance of `tcl` and not the other one. So changing that line to `orientation = IntVar(fenetre)` will solve the problem. – TheLizzard Feb 19 '21 at 18:02
  • @TheLizzard It will give rise to alot of implicit issues, that beginners might not be able to think of. – Delrius Euphoria Feb 19 '21 at 18:05
  • @TheLizzard: Because it's error-prone and `tkinter` is documented so well. – martineau Feb 19 '21 at 18:06
  • I would tell beginners to never assume that `tkinter` knows the parent of the tkinter objects. I have never encountered an error/problem using this approach. – TheLizzard Feb 19 '21 at 18:09
  • 1
    @TheLizzard Sad for them you are not the one teaching them, most online tutorials just shows `StringVar()` as the the initialization and nothing talks more about it. – Delrius Euphoria Feb 19 '21 at 18:13
  • You should write some documentation because that's the only way to tell beginners anything (assuming the know it exists). Here an [example](https://web.archive.org/web/20201031100214/https://effbot.org/tkinterbook/variable.htm) of what used to one of the better places to get information on the module—which not longer exists. Note that it says _nothing_ about passing the parent instance when creating variables. – martineau Feb 19 '21 at 18:13
  • @martineau I agree that most of the online tkinter documentation is incomplete. I also use effbot.org but it lacks documentation in some areas like tkinter variables and ttk. I wouldn't mind creating a detailed documentation of tkinter but it will take a lot of time (and I still need to learn some things). – TheLizzard Feb 19 '21 at 18:22

1 Answers1

0

Calling Tk() isn't a problem when all of the tkinter variables are linked correctly. The problem is that your IntVar (named orientation) is created in tcl instance and doesn't exist in the other so the other tcl instance gets confused. If you change the line:

orientation = IntVar()

to:

orientation = IntVar(fenetre)

It should work.

TheLizzard
  • 7,248
  • 2
  • 11
  • 31
  • This is one of the reasons calling `Tk()` more than once is discouraged. – martineau Feb 19 '21 at 18:03
  • Well if you always provide a parent to tkinter objects, it will never be a problem. Like in this case tkinter assumed that the main window is the parent of the `orientation` variable when OP actually wanted it to be the second window. – TheLizzard Feb 19 '21 at 18:06