2015-08-05 2 views
0

Я использую tkinter для записи карточной игры, и у меня возникают проблемы с конфигурацией менеджера компоновки сетки. Я хотел бы помочь исправить мой код, чтобы отобразить кадры в нужном месте. В моем коде и иллюстрации ниже есть кадр (b2), который содержит два других (один зеленый, b2a и один красный, b2b) кадры. Я хотел бы отобразить рамку b2 в нижней части родительского кадра (фрейм b). Я пробовал различные комбинации N + S + E + W в качестве аргументов для «липких», как для кадра b2, так и для дочерних кадров b2a и b2b. Тем не менее, мне не удалось создать фрейм b2 (и, что более важно, b2a и b2b) в нужном месте (нижнее изображение ниже с правильным размещением было сделано в Illustrator).tkinter sticky не работает для некоторых фреймов

В частности, кажется, что липкие аргументы в строках 27, 36 и 37 не влияют на размещение кадров b2, b2a и b2b внутри кадра b.

from tkinter import * 
from PIL import Image, ImageTk 

def main(root): 
    cons = Frame(root) 
    cons.grid() 

    frameDict = setup_frames(cons) 
    populate_frames(frameDict) 

def setup_frames(cons): 
    frame = {} 
    # Parental Frames 
    frame['a'] = Frame(cons, borderwidth=2, relief='groove') 
    frame['b'] = Frame(cons, borderwidth=2, relief='groove') 
    frame['c'] = Frame(cons, borderwidth=2, relief='groove') 

    frame['a'].grid(row=0, column=0, sticky=N+S+E+W) 
    frame['b'].grid(row=0, column=1, sticky=N+S+E+W) 
    frame['c'].grid(row=1, column=0, columnspan=2) 

    # Progeny 0 Frames: 
    frame['b1'] = Frame(frame['b'], borderwidth=2, relief='groove') 
    frame['b2'] = Frame(frame['b'], borderwidth=2, relief='groove') 

    frame['b1'].grid(row=0, column=0, sticky=N+S+E+W) 
    frame['b2'].grid(row=1, column=0, sticky=N+S+E+W) 

    # Progeny 1 Frames: 

    frame['b2a'] = Frame(frame['b2'], borderwidth=2, relief='groove', 
         background='green') 
    frame['b2b'] = Frame(frame['b2'], borderwidth=2, relief='groove', 
         background='red') 

    frame['b2a'].grid(row=0, column=0, sticky=S) 
    frame['b2b'].grid(row=0, column=1, sticky=SW) 

    return frame 

def populate_frames(fr): 

    # Populating 'a' frame 
    aLab = Label(fr['a'], image=img[0]) 
    aLab.grid() 

    # Populating b2a & b2b frames 
    bLab = Label(fr['b2a'], image=img[1]) 
    bLab.grid(row=0, column=0) 

    bLab = Label(fr['b2b'], image=img[2]) 
    bLab.grid(row=0, column=1) 

    # Populating c1 frame 
    cLab = Label(fr['c'], image=img[3]) 
    cLab.grid() 

if __name__ == '__main__': 
    root = Tk() 
    img = [] 
    w = [40, 160, 80, 480] 
    h = [180, 60, 60, 60] 
    for i in range(4): 
     a = Image.new('RGBA', (w[i], h[i])) 
     b = ImageTk.PhotoImage(a) 
     img.append(b) 
    main(root) 

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

Может ли кто-нибудь помочь мне отобразить рамку b2 (и в конечном счете b2a и b2b) в правильном положении (Edit: внизу кадра b и охватывающий с правой стороны рамки a в правую сторону кадра c) ?

illustration of incorrect and correct frame placement

Update: Я решил обе проблемы (вертикальное размещение и горизонтальное обоснование кадра b2) с использованием весов сетки, как это было предложено Bryan. Решение проблемы вертикального размещения является простым, но я бы не предсказал решение проблемы горизонтального обоснования.

Я решил проблему вертикального размещения, указав вес = 1 на строку 0 в рамке b (в результате верхняя панель на рисунке ниже).

Я решил проблему горизонтального обоснования (в которой кадры b1 и b2 не растягивались для заполнения кадра b), присвоив весу = 1 столбцу 0 в кадре b. Очертания кадра на рисунке ниже показывают, что рамка b уже растянута с правой стороны кадра a до правой стороны кадра c. Для меня странно, что для того, чтобы разрешить дочерние кадры горизонтально, потребуется вес для единственного столбца в кадре. В любом случае, я наклеил свой рабочий код ниже. Линии 40 и 41 решили проблему, с которой я столкнулся.

from tkinter import * 
from PIL import Image, ImageTk 

def main(root): 
    cons = Frame(root) 
    cons.grid() 

    frameDict = setup_frames(cons) 
    populate_frames(frameDict) 

def setup_frames(cons): 
    frame = {} 
    # Parental Frames 
    frame['a'] = Frame(cons, borderwidth=2, relief='groove') 
    frame['b'] = Frame(cons, borderwidth=2, relief='groove') 
    frame['c'] = Frame(cons, borderwidth=2, relief='groove') 

    frame['a'].grid(row=0, column=0, sticky=N+S+E+W) 
    frame['b'].grid(row=0, column=1, sticky=N+S+E+W) 
    frame['c'].grid(row=1, column=0, columnspan=2) 

    # Progeny 0 Frames: 
    frame['b1'] = Frame(frame['b'], borderwidth=2, relief='groove') 
    frame['b2'] = Frame(frame['b'], borderwidth=2, relief='groove') 

    frame['b1'].grid(row=0, column=0, sticky=N+S+E+W) 
    frame['b2'].grid(row=1, column=0, sticky=N+S+E+W) 

    # Progeny 1 Frames: 

    frame['b2a'] = Frame(frame['b2'], borderwidth=2, relief='groove', 
         background='green') 
    frame['b2b'] = Frame(frame['b2'], borderwidth=2, relief='groove', 
         background='red') 

    frame['b2a'].grid(row=0, column=0, sticky=S) 
    frame['b2b'].grid(row=0, column=1, sticky=SW) 

    # Weighting 
    frame['b'].grid_rowconfigure(0, weight=1) 
    frame['b'].grid_columnconfigure(0, weight=1) 

    return frame 

def populate_frames(fr): 

    # Populating 'a' frame 
    aLab = Label(fr['a'], image=img[0]) 
    aLab.grid() 

    # Populating b2a & b2b frames 
    bLab = Label(fr['b2a'], image=img[1]) 
    bLab.grid(row=0, column=0) 

    bLab = Label(fr['b2b'], image=img[2]) 
    bLab.grid(row=0, column=1) 

    # Populating c1 frame 
    cLab = Label(fr['c'], image=img[3]) 
    cLab.grid() 

if __name__ == '__main__': 
    root = Tk() 
    img = [] 
    w = [40, 160, 80, 480] 
    h = [180, 60, 60, 60] 
    for i in range(4): 
     a = Image.new('RGBA', (w[i], h[i])) 
     b = ImageTk.PhotoImage(a) 
     img.append(b) 
    main(root) 

В соответствии с рекомендациями Брайана, он, кажется, хорошее правило, чтобы назначить вес, по меньшей мере, одного столбца и одной строки в каждом контейнере.

Вот до и после того, как я установил горизонтальную проблему обоснования:

before and after horizontal justification

Использование Python 3.4, Yosemite

+0

grid (row = 0) = наверху См. Раздел «Обработка изменения размера» и приведенные ниже примеры на странице http://www.tkdocs.com/tutorial/grid.html –

ответ

0

Вы должны дать некоторые строки и столбцы вес, так Tkinter умеет выделять дополнительные пространство.

Как правило, при использовании grid каждый контейнер, использующий сетку, должен содержать по меньшей мере один ряд и один вес столбца.

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

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

Похоже, что рамка C - это строка состояния, которая простирается на дно, поэтому сначала упакуйте ее. Выше того, что у вас есть две области - рамка a находится слева и выглядит фиксированной шириной, а рамка c находится вправо и занимает все лишнее пространство. Используя пакет, он будет выглядеть следующим образом:

frame['c'].pack(side="bottom", fill="x") 
frame['a'].pack(side="left", fill="y") 
frame['b'].pack(side="right", fill="both", expand=True) 

Конечно, вы можете получить точно такой же внешний вид с сеткой, но это займет еще пару строк кода, так что вы должны дать столбец 1 и строки 1 в вес.

Это должно обеспечить работу трех основных областей. Теперь все, о чем вам нужно беспокоиться, это содержимое рамки B.

Ваша диаграмма показывает, что вы хотите, чтобы b2a и b2b находились внизу фрейма b с большим количеством виджетов над ним. Это верно? Если это так, вам нужно оставить по крайней мере одну дополнительную строку над ней, чтобы заполнить дополнительное пространство.

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

Вам остается только беспокоиться о горизонтальном размещении. Непонятно, что вы ожидаете, но решение снова вращается вокруг, давая столбцы веса. Если вы хотите, чтобы оба b2a и b2b расширялись одинаково, дайте обе колонки равным весом. Если вы хотите, чтобы b2a выполнял все расширения, укажите только нулевой столбец.

+0

размещено не в том месте –

+0

Спасибо, Брайан. быть помеченным как дублированный вопрос, поскольку он, похоже, имеет тот же ответ, что и [предыдущий] (http://stackoverflow.com/questions/15530392/python-tkinter-grid-geometry-sticky-setting-not-effective) что вы ответили. Тем не менее, у меня есть проблема - я добавил 'frame ['b']. grid_rowconfigure (0, weight = 1)' и который перемещает b2 в нижнюю часть фрейма B. Но добавление 'frame [' b2 ']. grid_columnconfigure (0, weight = 1) 'все еще не позволяет кадру b2 расширяться в правую сторону кадра. – mRotten

+0

@mRotten: я обновил свой ответ несколькими примерами и дополнительными советами. –