Tkinter. Поля выбора: чекбокс, радиокнопки, список, ползунок

Ввод в Python не ограничивается исключительно текстом. Иногда появляется необходимость использовать только числа. Это требуется для объектов классов Spinbox и Scale, дающие возможность выбирать из тех вариантов, которые отобраны предварительно. Тем не менее, есть определенные различия в их внешнем отображении и особенностях настройки.

Давайте приведем пример программы, которая предлагает выбор чисел от 0 до 5. При этом допускаются исключительно целые числа.

import tkinter as tk




class App(tk.Tk):

    def __init__(self):

        super().__init__()

        self.spinbox = tk.Spinbox(self, from_=0, to=5)

        self.scale = tk.Scale(self, from_=0, to=5,

                              orient=tk.HORIZONTAL)

        self.btn = tk.Button(self, text="Вывести значения",

                             command=self.print_values)

        self.spinbox.pack()

        self.scale.pack()

        self.btn.pack()




    def print_values(self):

        print("Spinbox: {}".format(self.spinbox.get()))

        print("Scale: {}".format(self.scale.get()))




if __name__ == "__main__":

    app = App()

    app.mainloop()

В этой программе была также предусмотрена, функция которой – исключительно отладка. Ее задача – отобразить значение, введенное пользователем из перечня, в виде отдельной метки. Tkinter. Поля выбора: чекбокс, радиокнопки, список, ползунок

Принцип работы выбора значений

И тот, и другой класс принимает параметры from_ и to_, указывающие на пределы значений. 

Обратите внимание! Указывать нижнее подчеркивание нужно обязательно, так как from – это зарезервированное ключевое слово Python, которое используется для других целей.

Существенное преимущество класса Scale – наличие параметра resolution, позволяющее задавать точность элемента. Например, если мы установим значение 0,2, то тогда в перечне будут отображаться исключительно те числа, которые кратны этому. Например, 0.2, 0.4, 0.6 и так далее. 

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

Хорошо. А как получить значение определенного виджета? Независимо от того, какой конкретно мы используем, необходимо применять метод get(). Существенная разница между этими методами в том, что возвращаемое значение отличается. Так, Spinbox возвращает число в строчном представлении, а Scale – в виде целочисленного значения или числа с плавающей точкой в зависимости от того, какое значение было указано пользователем.

Следовательно, если мы используем Spinbox, необходимо использовать соответствующую функцию, чтобы преобразовать строку в целое число или число с плавающей точкой.

Класс Spinbox имеет такие же по факту параметры, что и стандартное поле ввода. Это textvariable и validate. Разница выражается в том, что можно использовать исключительно числовые значения.

Генерация полей с радиокнопками программными методами

Элемент класса Spinbox позволяет пользователю осуществлять выбор между несколькими классами. Это полезно при сравнительно маленьком числе взаимоисключающих опций.

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

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

import tkinter as tk




COLORS = [("Red", "red"), ("Green", "green"), ("Blue", "blue")]




class ChoiceApp(tk.Tk):

    def __init__(self):

        super().__init__()

        self.var = tk.StringVar()

        self.var.set("red")

        self.buttons = [self.create_radio(c) for c in COLORS]

        for button in self.buttons:

            button.pack(anchor=tk.W, padx=10, pady=5)




    def create_radio(self, option):

        text, value = option

        return tk.Radiobutton(self, text=text, value=value,

                              command=self.print_option,

                              variable=self.var)




    def print_option(self):

        print(self.var.get())




if __name__ == "__main__":

    app = ChoiceApp()

    app.mainloop()

Можете попробовать выполнить эту последовательность команд у себя на устройстве. После этого будет показано приложение, в котором уже выбран красный цвет.

Принцип работы радиокнопок

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

Так, как StringVar – это общая радиокнопка, они все объединяются, а пользователю доступен выбор исключительно одного варианта из них.

В нашем примере стандартно активирована кнопка с надписью Red. Но что будет, например, если установить значение StringVar, которое не будет отсылаться ни к одной из кнопок? В этом случае оно будет равняться пустой строке. Из-за этого виджет будет отображаться в неопределенном режиме. 

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

Реализация чекбоксов

Еще один вариант выбора – это несколько элементов. В таком перечне один выбранный вариант не зависит от других. Чтобы реализовать такую задачу, используется элемент класса Checkbutton.

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

import tkinter as tk


class SwitchApp(tk.Tk):

    def __init__(self):

        super().__init__()

        self.var = tk.IntVar()

        self.cb = tk.Checkbutton(self, text="Активно?",

                                 variable=self.var,

                                 command=self.print_value)

        self.cb.pack()


    def print_value(self):

        print(self.var.get())


if __name__ == "__main__":

    app = SwitchApp()

    app.mainloop()

Принцип работы чекбоксов

Аналогично кнопкам, чекбоксы могут принимать один из следующих параметров – Command и text.

С использованием параметров onvalue и offvalue можно задать те значения, которые будут выводиться в целочисленную переменную в зависимости от того, чекбокс отмечен или нет.

В целом, если не задавать иного, используются значения переменных 0 и 1. Тем не менее, возможно использование любых других целых чисел с этой целью.

Также разрешается применять другие типы переменных вместе с этим виджетом.

 

var = tk.StringVar()

var.set("OFF")

checkbutton_active = tk.Checkbutton(master, text="Активно?", variable=self.var,

                                                     onvalue="ON", offvalue="OFF",

                                                     command=update_value)

Единственное, что нельзя, – это допускать совпадения onvalue и offvalue с типом переменной Tkinter.

В этой ситуации, учитывая то, что ON и OFF – данные строчного типа, то и переменную необходимо использовать не IntVar, а StringVar. Иначе будет ошибка, если попытаться использовать строчные идентификаторы состояния чекбоксов.

Как показать перечень элементов?

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

Приведем пример кода приложения, которое реализует это решение на практике. 

import tkinter as tk




DAYS = ["Понедельник", "Вторник", "Среда", "Четверг",

        "Пятница", "Суббота", "Воскресенье"]

MODES = [tk.SINGLE, tk.BROWSE, tk.MULTIPLE, tk.EXTENDED]




class ListApp(tk.Tk):

    def __init__(self):

        super().__init__()

        self.list = tk.Listbox(self)

        self.list.insert(0, *DAYS)

        self.print_btn = tk.Button(self, text="Вывести выбор",

                                   command=self.print_selection)

        self.btns = [self.create_btn(m) for m in MODES]




        self.list.pack()

        self.print_btn.pack(fill=tk.BOTH)

        for btn in self.btns:

            btn.pack(side=tk.LEFT)




    def create_btn(self, mode):

        cmd = lambda: self.list.config(selectmode=mode)

        return tk.Button(self, command=cmd,

                         text=mode.capitalize())




    def print_selection(self):

        selection = self.list.curselection()

        print([self.list.get(i) for i in selection])




if __name__ == "__main__":

    app = ListApp()

    app.mainloop()

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

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

Tkinter. Поля выбора: чекбокс, радиокнопки, список, ползунок

Принцип работы выбора элементов из списка

После создания пустого объекта Listbox можно добавить все элементы в него. Для этого используется функция insert(). С помощью индекса 0 мы указываем, что все элементы должны указываться не в конец списка, а его начало. Далее наш перечень дней распаковывается. Тем не менее, если понадобится добавить еще какие-то элементы, то с помощью константы END это вполне можно сделать. Соответственно, они будут добавлены в конец списка, на что и указывает это ключевое слово.

self.list.insert(tk.END, «Новый пункт»)

Далее используется метод curselection(), чтобы извлечь выборку. С его помощью можно получить индексы элементов, которые были выбраны пользователем. А чтобы затем их перевести в текстовый формат, используется уже вам знакомый метод get(). Как следствие, перечень с выводами отображается в STDOUT, и там уже подлежит отладке.

Приведем пример, в котором параметр selectmode используется, чтобы дать право выбирать разное количество элементов (и другим образом настраивать поведение пользователя).

def __init__(self):

    self.frame = tk.Frame(self)

    self.scroll = tk.Scrollbar(self.frame, orient=tk.VERTICAL)

    self.list = tk.Listbox(self.frame, yscrollcommand=self.scroll.set)

    self.scroll.config(command=self.list.yview)

    # ...

    self.frame.pack()

    self.list.pack(side=tk.LEFT)

    self.scroll.pack(side=tk.LEFT, fill=tk.Y)

ОфисГуру
Adblock
detector