Основные вопросы Tkinter/GUI
Я загрязняю руки Python Tkinter, специально изучая ООП для графических интерфейсов и задавая несколько вопросов.
При построении такого класса:
class Keylogger(Frame):
def __init__(self, master=None):
frame = Frame.__init__(self, master)
text = Text(frame, width=20, height=5)
...
test = KeyLogger()
test.mainloop()
Какова цель основного аргумента по умолчанию: None
? Обычно я учился указывать главный виджет, такой как root = Tk()
. Есть ли время, когда главный виджет не нужен/не нужен?
Я также заметил, что мне не нужно было pack()
мой объект KeyLogger, независимо от того, имел ли он мастер или нет. Я даже не упаковал свой объект Frame. Почему это?
Затем я заметил, что если бы я изменил код в моем методе __init__
следующим образом:
def __init__(self, master=None):
Frame.__init__(self, master) # no more assignment statement
text = Text(self, width=20, height=5) # first constructor arg. changed
...
test = KeyLogger()
test.mainloop()
- Теперь мне нужно
pack()
мой объект KeyLogger, независимо от того, присутствует ли главный виджет. Что изменилось, когда я удалил оператор присваивания и просто вызвал Frame.__init__()
? Должен ли я вызвать метод pack()
внутри __init__()
или вне класса? Он работает в обоих направлениях, но я предполагаю, что есть некоторые плюсы и минусы. Спасибо!
Какова цель основного аргумента по умолчанию: None?
Нет никакой цели. Каждый виджет, кроме начального экземпляра Tk
нуждается в родительском виджетах. Если мастер- None
он будет использовать корневое окно по умолчанию, но явное всегда лучше, чем неявное, поэтому вы всегда должны явно задавать мастер.
Я также заметил, что мне не нужно было упаковывать() мой объект KeyLogger, независимо от того, имел ли он мастер или нет. Я даже не упаковал свой объект Frame. Почему это?
На это невозможно ответить. Чтобы виджет отображался, что-то должно вызывать pack
, grid
или place
(или виджет нужно вставлять в виджет или виджет). Вы, должно быть, делаете один из тех, кто где-то в коде, который вы нам не показываете.
Теперь мне нужно упаковать() мой объект KeyLogger, независимо от того, присутствует ли главный виджет. Что изменилось, когда я удалил оператор присваивания и просто вызвал Frame. init()?
Когда вы назначаете значение __init__
для frame
, кадр устанавливается на None
, то есть текстовый виджет переходит в корневое окно, а не в создаваемый фрейм. Там должен быть код, который заставляет этот виджет быть упакованным, помещенным или привязанным к сетке.
Должен ли я вызвать метод pack() внутри init() или вне класса? Он работает в обоих направлениях, но я предполагаю, что есть некоторые плюсы и минусы.
Виджет (или составной виджет, такой как этот) никогда не должен pack
(или grid
или place
) сам в своем родителе. Это создает плотную связь - новый класс должен знать что-то о своем родителе (в частности, другие ли виджеты в родительском устройстве также используют pack
, place
или grid
.
1. В этом коде, поскольку init ничего не возвращает, вы просто инициализируете текст с помощью None, например
text = Text(None, width=20, height=5)
И вам нужно использовать text.pack()
внутри __init__()
чтобы он вступил в силу.
Мастер используется как главный виджет. Виджет без него - это собственный главный виджет. Вот почему мы не даем ему мастера.
2.
В этом коде вы инициализируете экземпляр Text с экземпляром Frame, предоставляя ему параметр self. Вам нужно упаковать как внутри __init__()
и в основном процессе, чтобы они вступили в силу. подобно
from Tkinter import *
class KeyLogger(Frame):
def __init__(self, master=None):
# frame = Frame.__init__(self, master)
Frame.__init__(self, master)
# text = Text(frame, width=20, height=5)
text = Text(self, width=20, height=5)
text.pack()
test = KeyLogger()
test.pack()
test.mainloop()
Если это поможет, пожалуйста, подтвердите это как ответ, чтобы кто-то еще мог быстро найти его. Благодарю!