Есть несколько проблем с вашим кодом.
Возможно, самая большая проблема заключается в том, что Encoding
наследуется от tk.Tk
, MainApplication
наследуется от tk.Frame
и Encoding
(делая его одновременно корневым окном и фреймом)и затем MainApplication
создает экземпляр Encoding
. Кроме того, вы явно создаете еще один экземпляр tk.Tk()
, предоставляя вам два корневых окна. Это все должно быть распутано.
Наследование создает "это" отношение. Имея MainApplication
наследование от Encoding
, вы говорите, что MainApplication
является Encoding
объектом. Это не так в вашем коде - объект Encoding
представляет только небольшую часть приложения. Для этого вам нужна композиция , а не наследование , то есть: MainApplication
имеет Encoding
объект.
Итак, первым шагом является удаление Encoding
из списка классов, от которых наследуется MainApplication
.
Другая вещь, которая может быть удалена, это self.encoding_frame
. Я не вижу причин иметь его, так как MainApplication
сам по себе является рамкой. Вместо этого MainApplication
наследуется от ttk.LabelFrame
, а не tk.Frame
.
И, наконец, поскольку MainApplication
создает Encoding
, он должен отвечать за вызов grid
или pack
в случае Encoding
.
В целом, MainApplication
можно сократить до этого:
class MainApplication(ttk.LabelFrame):
def __init__(self, parent, *args, **kwargs):
ttk.LabelFrame.__init__(self, parent, *args, **kwargs)
self.configure(text="Main Window")
self['borderwidth'] = 3
self['relief'] = 'raised'
self.encoding = Encoding(self)
self.encoding.grid(row=0, column=0, sticky="ew")
Это не на 100% завершено, но это хорошее место для начала. Основываясь на вашем изображении, я предполагаю, что у вас будут другие классы для других частей основного приложения - виджет сообщений, виджеты ключей и окно транскрипции.
Для Encoding
, большая частьприменяется тот же совет. Поскольку это только часть приложения, оно не должно наследоваться от tk.Tk
. Вместо этого вы можете наследовать от ttk.Frame
, а затем удалить self.encoding_frame
, поскольку сам объект Encoding
уже является фреймом.
С этими изменениями Encoding
должен выглядеть примерно следующим образом. Обратите внимание, что радиокнопки имеют self
в качестве родителя. Если вы создаете надлежащие объекты, все виджеты внутри класса должны быть дочерними по отношению к самому классу или одному из его потомков. Класс, подобный этому, никогда не должен помещать ничего в parent
, кроме себя.
class Encoding(ttk.Frame):
def __init__(self, parent, *args, **kwargs):
ttk.Frame.__init__(self, parent, *args, **kwargs)
self.mode = StringVar()
self.encrypt = ttk.Radiobutton(self, text='Encrypt', variable=self.mode, value='encrypt')
self.decrypt = ttk.Radiobutton(self, text='Decrypt', variable=self.mode, value='decrypt')
self.encrypt.grid(column=0, row=0, ipadx=2, sticky=W)
self.decrypt.grid(column=0, row=1, ipadx=2, sticky=W)
Наконец, поскольку MainApplication
теперь является фреймом - вместо того, чтобы наследовать от Encoding
, который наследуется от tk.Tk
-- блок кода, который создает экземпляр MainApplication
, должен отвечать за вызов pack
или grid
. Поскольку MainApplication
является единственным виджетом, находящимся непосредственно внутри корневого окна, pack
- лучший выбор, поскольку вам не нужно настраивать вес строк и столбцов, чтобы получить правильное поведение при изменении размера окна.
Кроме того, я рекомендую создавать root
в том же блоке, а не в самом начале программы.
Ваш нижний блок кода должен выглядеть следующим образом:
if __name__ == "__main__":
root = tk.Tk()
app = MainApplication(root)
app.pack(fill="both", expand=True)
root.mainloop()