Tkinter: Почему один кадр перекрывает другой? - PullRequest
2 голосов
/ 16 августа 2010

Я пытаюсь построить графический интерфейс в Python, используя Tkinter.Моя идея состоит в том, чтобы создать несколько фреймов внутри корневого фрейма.Я могу получить 2 кадра, но третий кадр накладывается на второй кадр.Я пробовал и pack (), и grid () в качестве менеджера компоновки в корневом фрейме.

Я хочу иметь фрейм "Stuff At the Top" и фрейм "Stuff At The Bottom" с 1Рамка Cat1 и от 1 до 8 рамок Cat2 между ними.Графический интерфейс должен быть в состоянии динамически перестраиваться, так как приложение обнаруживает, сколько виджетов Cat2 оно контролирует.

(Еще одна небольшая проблема. Поскольку я ввел класс Cat2Frame и переместил переменные tkFont в глобальную область, моиТочечный шрифт по-прежнему всего 9 точек.)

Вот мой фрагмент кода с продезинфицированным кодом.(Еще не дошли до нижней рамки.)

def anchor(widget, rows=0, cols=0):
    """Takes care of anchoring/stretching widgets via grid 'sticky'"""
    for r in range(rows):
        widget.rowconfigure(r, weight=1)
    for c in range(cols):
        widget.columnconfigure(c, weight=1)


font_ = None
bold_ = None
bold_12 = None

class TkinterGui():
    """Tkinter implementation of the GUI"""
    def __init__(self):
        """Create the Tkinter GUI"""
        self._top_level = None
        self._top_row   = None
        self._buildGui(_TITLE)


    def _buildGui(self, title):
        """Build the Tkinter GUI"""
        self._top_level  = Tkinter.Tk()
        font_ = tkFont.Font(family='FreeSans', size=9)
        bold_ = tkFont.Font(family='FreeSans', size=9, weight='bold')
        bold_12 = tkFont.Font(family='FreeSans', size=12, weight='bold')
        anchor(self._top_level, 4, 1)
        self._top_row = 0
        self._buildTop()
        self._top_row = 1
        self._buildCat1()
        t1 = Cat2Frame(self._top_level, "Cat2 1")
        self._top_row = 2
        t1.place_frame(self._top_row)
        t5 = Cat2Frame(self._top_level, "Cat2 5")
        self._top_row = 3
        t5.place_frame(self._top_row)
        self._top_level.title(title)


    def _buildTop(self):
        """Private method to build the Top frame of the GUI."""
        top_frame = Tkinter.Frame(self._top_level, name='top_frame')
        anchor(top_frame, 1, 3)
        top_frame.columnconfigure(0, weight=2)
        top_frame.columnconfigure(1, weight=5)
        col1_label = Tkinter.Label(top_frame
                                   , name='col1_label'
                                   , text="Col1"
                                   , font=bold_12
                                   , width=20
                                    ).grid(row=0
                                         , column=0
                                         , sticky=N+E+W+S
                                          )
        col2_label = Tkinter.Label(top_frame
                                   , name='col2_label'
                                   , text="Col2"
                                   , font=bold_12
                                   , width=40
                                    ).grid(row=0
                                         , column=1
                                         , sticky=N+E+W+S
                                          )
        top_button = Tkinter.Button(top_frame
                                    , name='top_button'
                                    , text='Top Button'
                                    , font=bold_
                                     ).grid(row=0
                                          , column=2
                                          , sticky=E
                                           )
        top_frame.grid(row=self._top_row, column=0, sticky=N+W)


    def _buildCat1(self):
        """Private method to build the Cat1 frame of the GUI"""
        cat1_frame = Tkinter.Frame(self._top_level, name='cat1_frame')
        anchor(cat1_frame, 3, 3)
        cur_row = 0
        cat1_frame.columnconfigure(2, weight=6)
        Tkinter.Label(cat1_frame
                    , name='cat1_label'
                    , text='Cat1'
                    , font=bold_
                     ).grid(row=cur_row, column=0, sticky=N+E+W+S)
        cat1_size = Tkinter.Text(cat1_frame
                                 , name='cat1_size'
                                 , state=DISABLED
                                 , font=font_
                                 , height=1
                                 , width=10
                                  ).grid(row=cur_row
                                       , column=1
                                       , sticky=E
                                        )
        cat1_status = Tkinter.Text(cat1_frame
                                   , name='cat1_status'
                                   , state=DISABLED
                                   , font=font_
                                   , height=3
                                   , width=72
                                    ).grid(row=cur_row
                                         , column=2
                                         , rowspan=3
                                         , sticky=N+E+W+S
                                          )
        cur_row += 1
        cat1_model = Tkinter.Text(cat1_frame
                                  , name='cat1_model'
                                  , state=DISABLED
                                  , font=font_
                                  , height=1
                                  , width=30
                                   ).grid(row=cur_row
                                        , column=0
                                        , columnspan=2
                                        , sticky=N+W
                                         )
        cur_row += 1
        cat1_serial = Tkinter.Text(cat1_frame
                                   , name='cat1_serial'
                                   , state=DISABLED
                                   , font=font_
                                   , height=1
                                   , width=30
                                    ).grid(row=cur_row
                                         , column=0
                                         , columnspan=2
                                         , sticky=N+W
                                          )
        cat1_frame.grid(row=self._top_row, column=0, sticky=N+W)


class Cat2Frame():
    """Class encapsulation for a Cat2 Frame in the GUI"""
    def __init__(self, parent, t_label):
        """Initialize a Cat2 Frame in the GUI"""
        self._frame = Tkinter.Frame(parent, name='cat2_frame')
        anchor(self._frame, 3, 4)
        self.cur_row = 0
        self._frame.columnconfigure(2, weight=5)

        self._label = Tkinter.Label(self._frame
                                  , name='cat2_label'
                                  , text=t_label
                                  , font=bold_
                                   )
        self._size = Tkinter.Text(self._frame
                                , name='cat2_size'
                                , state=DISABLED
                                , font=font_
                                , height=1
                                , width=10
                                 )
        self._status = Tkinter.Text(self._frame
                                  , name='cat2_status'
                                  , state=DISABLED
                                  , font=font_
                                  , height=3
                                  , width=60
                                   )
        self._control = Tkinter.IntVar()
        self._enabled = Tkinter.Radiobutton(self._frame
                                          , name='cat2_enabled'
                                          , variable=self._control
                                          , text='Enabled'
                                          , font=bold_
                                          , value=1
                                           )
        self._model = Tkinter.Text(self._frame
                                 , name='cat2_model'
                                 , state=DISABLED
                                 , font=font_
                                 , height=1
                                 , width=30
                                  )
        self._disabled = Tkinter.Radiobutton(self._frame
                                           , name='cat2_disabled'
                                           , variable=self._control
                                           , text='Disabled'
                                           , font=bold_
                                           , value=0
                                            )
        self._serial = Tkinter.Text(self._frame
                                  , name='cat2_serial'
                                  , state=DISABLED
                                  , font=font_
                                  , height=1
                                  , width=30
                                   )


    def place_frame(self, top_row):
        self._label.grid(row=self.cur_row, column=0, sticky=N+E+S+W)
        self._size.grid(row=self.cur_row, column=1, sticky=E)
        self._status.grid(row=self.cur_row, column=2, rowspan=3, sticky=N+E+W+S)
        self._enabled.grid(row=self.cur_row, column=3, sticky=W)
        self.cur_row += 1
        self._model.grid(row=self.cur_row, column=0, columnspan=2, sticky=N+W)
        self._disabled.grid(row=self.cur_row, column=3, sticky=W)
        self.cur_row += 1
        self._serial.grid(row=self.cur_row, column=0, columnspan=2, sticky=N+W)
        self.cur_row += 1
        self._frame.grid(row=top_row, column=0, sticky=N+W)

1 Ответ

3 голосов
/ 17 августа 2010

Короткий ответ на ваш код состоит в том, что вы даете одно и то же имя обоим вашим объектам Cat2Frame.Либо дайте им уникальные имена, либо не используйте атрибут имени для фрейма.

Кроме того, могу ли я предложить вам немного пересмотреть свой стиль программирования?То, как вы написали свой код, очень трудно читать.Я обнаружил, что отделение макета от создания виджета очень помогает, и, возможно, упростило поиск этой ошибки (благодаря возможности сразу увидеть весь макет, чтобы определить его правильность).

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

Я предполагаю, что вы хотите, чтобы все ваши строки были выложены в одинсетка, так что каждый ваш «фрейм» (Cat1Frame, Cat2Frame) не является реальным фреймом, поскольку сложно выровнять ячейки в отдельных виджетах.Если это не так (т. Е. Если каждый «фрейм» действительно является автономным виджетом), код можно сделать еще проще.

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

import Tkinter
from Tkinter import DISABLED

_TITLE="This is the title"

class TkinterGui():
    def __init__(self):
        self._buildGui(_TITLE)
        self.last_row = 0

    def _buildGui(self, title):
        self._top_level  = Tkinter.Tk()
        self._top_level.title(title)

        Cat1(self._top_level, label="Cat 1", row=1)
        Cat2(self._top_level, label="Cat 2.1", row=4)
        Cat2(self._top_level, label="Cat 2.2", row=7)

class Cat1:
    def __init__(self, parent, label=None, row=0):
        self._label  = Tkinter.Label(parent, text=label)
        self._size   = Tkinter.Text(parent, state=DISABLED, height=1, width=10, background="bisque")
        self._status = Tkinter.Text(parent, state=DISABLED, height=3, width=72, background="bisque")
        self._model  = Tkinter.Text(parent, state=DISABLED, height=1, width=30, background="bisque")
        self._serial = Tkinter.Text(parent, state=DISABLED, height=1, width=30, background="bisque")

        self._label.grid( row=row,   column=0, sticky="nsew")
        self._size.grid(  row=row,   column=1, sticky="nsew")
        self._status.grid(row=row,   column=2, rowspan=3, sticky="nsew")
        self._model.grid( row=row+1, column=0, columnspan=2, sticky="nsew")
        self._serial.grid(row=row+2, column=0, columnspan=2, sticky="nsew")

class Cat2:        
    def __init__(self, parent, label=None, row=0):
        self._control = Tkinter.IntVar()

        self._label    = Tkinter.Label(parent, text=label)
        self._size     = Tkinter.Text(parent, state=DISABLED, height=1, width=10, background="bisque")
        self._status   = Tkinter.Text(parent, state=DISABLED, height=3, width=72, background="bisque")
        self._model    = Tkinter.Text(parent, state=DISABLED, height=1, width=30, background="bisque")
        self._serial   = Tkinter.Text(parent, state=DISABLED, height=1, width=30, background="bisque")
        self._enabled  = Tkinter.Radiobutton(parent, variable=self._control, text="Enabled", value=1)
        self._disabled = Tkinter.Radiobutton(parent, variable=self._control, text="Disabled", value=0)

        self._label.grid(   row=row,   column=0, sticky="nsew")
        self._size.grid(    row=row,   column=1, sticky="nsew")
        self._status.grid(  row=row,   column=2, rowspan=3, sticky="nsew")
        self._model.grid(   row=row+1, column=0, columnspan=2, sticky="nsew")
        self._serial.grid(  row=row+2, column=0, columnspan=2, sticky="nsew")
        self._enabled.grid( row=row,   column=3, sticky="nsew")
        self._disabled.grid(row=row+1, column=3, sticky="nsew")


if __name__ == "__main__":
    gui=TkinterGui()
    gui._top_level.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...