Frame() - рамка

Для сложных интерфейсов используют отдельные области позиционирования элементов.

Фрейм - вспомогательный виджет, создание которого происходит при помощи класса Frame().

Фреймы размещают на главном окне, а уже в фреймах – виджеты:

from tkinter import *

root = Tk()
frame_top = Frame(root) # root можно не указывать
frame_top.pack()
label_1 = Label(frame_top, width=7, height=4, bg='yellow', text="1")
label_1.pack(side=LEFT)
label_2 = Label(frame_top, width=7, height=4, bg='orange', text="2")
label_2.pack(side=LEFT)

frame_bottom = Frame(root)
frame_bottom.pack()
label_3 = Label(frame_bottom, width=7, height=4, bg='lightgreen', text="3")
label_3.pack(side=LEFT)
label_4 = Label(frame_bottom, width=7, height=4, bg='lightblue', text="4")
label_4.pack(side=LEFT)

root.mainloop()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Результат выполнения:

01_frame

Кроме Frame существует похожий класс LabelFrame – фрейм с подписью. В отличие от простого фрейма у него есть свойство text:

from tkinter import *

root = Tk()

frame_top = LabelFrame(text="Верх")
frame_top.pack()
label_1 = Label(frame_top, width=7, height=4, bg='yellow', text="1")
label_1.pack(side=LEFT)
label_2 = Label(frame_top, width=7, height=4, bg='orange', text="2")
label_2.pack(side=LEFT)

frame_bottom = LabelFrame(text="Низ")
frame_bottom.pack()
label_3 = Label(frame_bottom, width=7, height=4, bg='lightgreen', text="3")
label_3.pack(side=LEFT)
label_4 = Label(frame_bottom, width=7, height=4, bg='lightblue', text="4")
label_4.pack(side=LEFT)

root.mainloop()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Результат выполнения:

02_frame

Упражнения

  1. Допишите существующий код, добавив ниже фрэйм "Footer", в котором будут горизонтально находиться две метки с надписями "5", "6".

  2. Допишите существующий код, добавив на верх фрэйм "Header", в котором будут горизонтально находиться три кнопки с надписями "File", "View", "About". Реализуйте растяжение кнопок по ширине окна.

  3. Напишите программу с четырьмя кнопками, которые будут расположены в углах окна, и при изменении размера окна.

    frame_buttons_in_coners

Горизонтальное расположение

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

frame_top.pack(side=LEFT)
frame_bottom.pack(side=LEFT)
1
2

Результат выполнения:

03_frame

Кроме side у pack() есть другие параметры-свойства. Можно задавать внутренние (ipadx и ipady) и внешние (padx и pady) отступы:

frame_top.pack(padx=100, pady=50)
frame_bottom.pack(ipadx=10, ipady=10)
1
2

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

04_frame

Когда устанавливаются внутренние отступы, то из-за того, что side прибивает виджет к левой границе, справа получаем отступ в 20 пикселей, а слева – ничего. Можно частично решить проблему, заменив внутренние отступы рамки на внешние отступы у меток. Изменим код следующим образом:

frame_bottom.pack()
label_3.pack(side=LEFT, padx=10, pady=10)
label_4.pack(side=LEFT, padx=10, pady=10)
1
2
3

Результат выполнения:

05_frame

Но тут появляется промежуток между метками. Чтобы его убрать, пришлось бы каждый виджет укладывать в свой собственный фрейм. Отсюда делаем вывод, что упаковщик tkinter удобен только для относительно простых интерфейсов.

Упражнения

Ниже приведен код часов:

from tkinter import *
import time

def tick():
    # get the current local time from the PC
    time2 = time.strftime('%H:%M:%S')

    # if time string has changed, update it
    clock.config(text=time2)

    # calls itself every 200 milliseconds to update the time
    # display as needed could use >200 ms
    clock.after(200, tick)

root = Tk()
clock = Label(root, font=('times', 20, 'bold'), bg='green')
clock.pack(fill=BOTH, expand=1)

tick()
root.mainloop()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

clock

  1. Напишите программу с часами состоящую из трех рамок:

    • рамка "Moscow time" выводит текущее время в виде: "Moscow time: 17:27:37",
    • рамка "Current time" выводит текущее время в виде: "Hour: 17 Minutes: 27 Second: 37"
    • рамка "Left time until the new day" выводит сколько часов минут и секунд осталось до нового дня.

    frame_clocks_03

  2. Для дальнейшего переиспользования кода, создайте новый файл с названием app_clock.py. Используя пример код часов измените программу следующим образом:

    • добавьте рамку с подписью часового пояса.

    time_zone_clock_02

    • Добавьте ещё пару фреймов с часами справа и слева.

    time_zone_clock_03

    • Для созданных часов: измените названия часовых поясов и их время.

    time_zone_clock_03

  3. Для дальнейшего переиспользования кода используйте файл app_calculator_fields_frame.py. Используя LabelFram() и расположите виждеты внутри используя метод pack(side=LEFT) напишите программу "Примеры" состоящую из:

    • одно-строчного текстового поля,
    • метки с отображением знака "+",
    • второго одно-строчного текстового поля,
    • кнопкой "=", при нажатии на которую результат вычисления выводиться в третье текстовое поле,
    • третьего одно-строчного тестового поля.
    • реализуйте растяжение виджетов по ширине в зависимости от ширины окна.

    frame_calc_first

    • Добавьте в программу примеры со знаками: "-", "*", "**", "/", "//", "%". Реализуйте решения этих примеров.

    frame_calc_full

    • Добавьте проверку деления на 0. С выводом сообщения об ошибке, в удобное для пользователя место. Консольный вывод сообщения об ошибке исключить.