Почему мои виджеты tkinter упаковываются не в то окно?

У меня есть игра, над которой я работаю, используя текст, чтобы информировать пользователя о том, что происходит в игре. Тем не менее, я использую окно Tkinter, чтобы включить ввод с помощью кнопок для более профессионального восприятия. Я также добавил несколько ярлыков, но все они упакованы в новое окно, а не в то, которое я уже сделал. Не спрашивайте об именах переменных, но это код:

def scan():
    action=str('scan')
    TSGcontrols.destroy()
    return action
def lookaround():
    action=str('look around')
    TSGcontrols.destroy()
    return action
def visoron():
    action=str('engage visor')
    global firstvisor
    if firstvisor==1:
        firstvisor=int(0)
        print ('The visor has a colour code.')
        print ('It displays a wire frame over black, based on sensor data -\nallowing you to see through walls (to a degree).')
        print ('\nColours:')
        print ('Green = inert object')
        print ('Blue = electrical signature')
        print ('Red = weapon signature')
        print ('Yellow = radiation (the darker the yellow, the deadlier exposure would be)')
        print ('White = life (the more grey, the weaker the lifesigns. Dark grey is dead.)')
        print ('Purple = unidentified\n')
    TSGcontrols.destroy()
    return action
def visoroff():
    action=str('disengage visor')
    TSGcontrols.destroy()
    return action
def personbasecreate():
    global TSGcontrols
    TSGcontrols=tkinter.Tk(screenName='/TSGcontrols',baseName='/TSGcontrols',className='/TSGcontrols')
    warning=Label(text='This is only the control panel for TSG.\nThe game\'s responses are output in the Python window.',bg='red')
    global location
    locationw=Label(text='Location: {0}'.format(location))
    controlling=Label(text='You are controlling only yourself.',bg='blue',fg='white')
    lookaround=Button(text='Look around',command=lookaround)
    visoron=Button(text='Turn visor on',command=visoron)
    visoroff=Button(text='Turn visor off',command=visoroff)
    scan=Button(text='Scan',command=scan)
    warning.pack(parent=TSGcontrols,side='top')
    locationw.pack(parent=TSGcontrols,side='top')
    controlling.pack(parent=TSGcontrols,side='top')
    lookaround.pack(side='left')
    scan.pack(side='left')
    if visor=='on':
        visoroff.pack(parent=TSGcontrols,side='right')
    else:
        visoron.pack(parent=TSGcontrols,side='right')
   groupw.pack(parent=TSGcontrols,side='bottom')

Затем позже:

addbutton1 = str('no')

while repeat==str('yes'):
    time.sleep(3)
    print ('\nChoose your action.')
    # Creating the basic window:
    personbasecreate()
    if addbutton1=='yes':
        # Adding the additional function:
        leavequarters.pack(in_=personGUI,side='left')
    action=str(personGUI.mainloop())

Но вместо виджетов, появляющихся в окне под названием «Управление TSG», они появляются в новом окне под названием «tk», поэтому, когда окно уничтожается, чтобы позволить обработать переменную «действие», оно уничтожает пустое окно и игра вылетает из-за того, что функции пытаются уничтожить несуществующее окно, выдавая ошибку:

Exception in Tkinter callback
Traceback (most recent call last):
  File "D:\Python\lib\tkinter\__init__.py", line 1489, in __call__
    return self.func(*args)
  File "D:\Python\TSG.py", line 881, in lookaround
    personGUI.destroy()
  File "D:\Python\lib\tkinter\__init__.py", line 1849, in destroy
    self.tk.call('destroy', self._w)
_tkinter.TclError: can't invoke "destroy" command:  application has been destroyed

При двойном нажатии кнопки «Осмотреться».

Есть ли способ исправить этот код или более простой способ сделать то, что я пытаюсь здесь сделать?


person Oliver Potts    schedule 07.02.2015    source источник
comment
Если вы лучше организуете свой код, по крайней мере, с одним пробелом между определениями функций, это может помочь нам разобраться в проблеме.   -  person nbro    schedule 08.02.2015
comment
Зачем вам нужны функции внутри других функций? Я ими почти не пользовался, не знаю, зачем они вам нужны.   -  person nbro    schedule 08.02.2015
comment
@ Ринзлер, наверное, нет. Я отредактирую это.   -  person Oliver Potts    schedule 08.02.2015


Ответы (1)


Часть проблемы, вероятно, заключается в следующем:

personGUI=tkinter.Tk(className='/TSG Controls')
warning=Label(text='This is only the control panel for TSG.\nThe game\'s responses are output in the Python window.',bg='red')

Обратите внимание, что вы создаете новое корневое окно, но затем создаете метку без указания родителя. Вы всегда должны указывать родителя для виджета, и вы всегда должны создавать только один экземпляр Tk для всего вашего приложения. Если вам нужно создать более одного окна, создайте корневое окно один раз, а затем для других окон вам нужно создать экземпляры tkinter.Toplevel.

person Bryan Oakley    schedule 07.02.2015
comment
Спасибо - не могли бы вы дать синтаксис для указания родителя? - person Oliver Potts; 08.02.2015
comment
@OliverPotts: укажите родителя в качестве первого аргумента при создании виджетов: warning=Label(personGUI, ...) - person Bryan Oakley; 08.02.2015
comment
Теперь выбрасывает Traceback (most recent call last): File "D:\Python\TSG.py", line 1118, in <module> personbasecreate() File "D:\Python\TSG.py", line 917, in personbasecreate warning.pack(personGUI,side='top') File "D:\Python\lib\tkinter\__init__.py", line 1927, in pack_configure + self._options(cnf, kw)) _tkinter.TclError: bad option "-container": must be -after, -anchor, -before, -expand, -fill, -in, -ipadx, -ipady, -padx, -pady, or -side - person Oliver Potts; 08.02.2015
comment
@OliverPotts: вы добавили родителя в команду pack, а не туда, где вы создаете виджет. Не добавляйте родителя в команду pack. - person Bryan Oakley; 08.02.2015
comment
@BryanOakely Ах, да, я так и сделал. Теперь он работает без сбоев (по крайней мере, я не могу исправить). Ваше здоровье. - person Oliver Potts; 08.02.2015