Как мне добиться следующей компоновки Tkinter GUI с пакетом или сеткой? - PullRequest
3 голосов
/ 24 января 2011

Вот мой текущий макет GUI для моей игры в шашки:

Checkers game

Как вы можете видеть, он состоит из меню вверху, холста слева, где я рисуюшахматная доска, панель инструментов (рамка) в правом верхнем углу, где у меня есть различные кнопки форматирования / навигации, и текстовый виджет, который используется для аннотирования движений.В настоящее время я использую сетку для виджетов.

Вот что мне нужно сделать:

  1. Уметь отображать / скрывать полосу прокрутки в виджете Текст, когда количествотекст становится больше, чем размер виджета.(Кажется, для этого требуется макет сетки, согласно этой статье .)
  2. Измените шрифт и / или размер текста в виджете «Текст» [через диалог настроек] и не оставляйтестранные пробелы вокруг текстового виджета.(Кажется, для этого требуется компоновка пакета, поскольку виджету «Текст» можно назначать ширину и высоту только в символах, а не в пикселях ... это означает, что виджет «Текст» увеличивается или уменьшается при изменении шрифта или размера, и окно не будет настраиватьсячтобы соответствовать разметке сетки. Я пытался использовать Font.measure, чтобы настроить размер виджета «Текст» в соответствии с выбранным шрифтом, но я все еще получаю пробелы, потому что не могу изменить размер виджета до точного пикселя.)
  3. Мое окончательное решение должно быть кроссплатформенным (как Windows, так и Linux, и, надеюсь, Mac).

Какой макет я могу использовать для удовлетворения своих требований?Если ни один из них не будет работать полностью, какой макет (сетка или пакет) приблизит меня к моей цели?Спасибо!

1 Ответ

6 голосов
/ 25 января 2011

Для этого простого макета вы можете использовать grid, pack или оба.Ни один из них не имеет явного преимущества в данном конкретном случае.Оба имеют желаемое изменение размера.

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

Если вы хотите, чтобы меню было таким, как оно есть на рисунке (то есть: нестандартное, только над шахматной доской), я бы использовал похожую технику: еще один кадр слевасторона с меню, упакованным сверху, шахматная доска снизу.

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

Тем не менее, лучше использовать стандартную строку меню, что означает, что вам не нужна содержащая рамка для комбинации шахматная доска / меню

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

import Tkinter as tk
import random

class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        size = 40
        menubar = tk.Menu(self)
        menubar.add_cascade(label="Game")
        menubar.add_cascade(label="Options")
        menubar.add_cascade(label="Help")
        chessboard = tk.Canvas(width=8*size, height=8*size, borderwidth = 0,
                               highlightthickness=0)
        statusbar = tk.Label(self, borderwidth=1, relief="sunken")
        right_panel = tk.Frame(self, borderwidth = 1, relief="sunken")
        scrollbar = tk.Scrollbar(orient="vertical", borderwidth=1)
        # N.B. height is irrelevant; it will be as high as it needs to be
        text = tk.Text(background="white",width=40, height=1, borderwidth=0, yscrollcommand=scrollbar.set)
        scrollbar.config(command=text.yview)

        toolbar = tk.Frame(self)
        for i in range(10):
            b = tk.Button(self, text="B%s" % i, borderwidth=1)
            b.pack(in_=toolbar, side="left")

        self.config(menu=menubar)
        statusbar.pack(side="bottom", fill="x")
        chessboard.pack(side="left", fill="both", expand=False)
        toolbar.grid(in_=right_panel, row=0, column=0, sticky="ew")
        right_panel.pack(side="right", fill="both", expand=True)
        text.grid(in_=right_panel, row=1, column=0, sticky="nsew")
        scrollbar.grid(in_=right_panel, row=1, column=1, sticky="ns")
        right_panel.grid_rowconfigure(1, weight=1)
        right_panel.grid_columnconfigure(0, weight=1)

if __name__ == "__main__":
    app = App()
    app.mainloop()
...