Рассмотрим пример создания графического интерфейса (GUI) на Python. В качестве "жертвы" напишем простенькую программу - решатель квадратных уравнений. Наше задание мы разобъем на несколько частей.
Часть первая: функция решения квадратного уравнения.
Напомним, что квадратным является уравнение вида:
ax2 + bx + c = 0
Есть несколько способов решить квадратное уравнение, мы выберем решение через дискриминант.
Формула дискриминанта:
D = b2 - 4ac.
Используя эту формулу мы можем вывести решение. Если дискриминант больше или равен нулю, то корни уравнения высчитываются по формуле:
x1,2 = (-b ± √D) ÷ (2a)
Если же дискриминант меньше нуля, то уравнение не имеет решений.
Превратим данные формулы в код:
def solver(a,b,c):
""" Решает квадратное уравнение и выводит отформатированный ответ """ # находим дискриминант
D = b*b - 4*a*c
if D >= 0:
x1 = (-b + sqrt(D)) / (2*a)
x2 = (-b - sqrt(D)) / (2*a)
text = "The discriminant is: %s \n X1 is: %s \n X2 is: %s \n" % (D, x1, x2)
else:
text = "The discriminant is: %s \n This equation has no solutions" % D
return text
Чтобы все работало не забудьте импортировать функцию sqrt из модуля math.
from math import sqrt
Поскольку мы будем выводить результат в специально созданном виджете - мы сразу же вставляем полученный ответ в отформатированную строку и возвращаем ее.
Теперь пора переходить к созданию графической оболочки для нашего приложения.
Часть вторая: создаем GUI для программы
Для простоты будем создавать GUI встроенными средствами Python, поэтому импортируем все из библиотеки Tkinter:
from Tkinter import *
В Python версии 3.х название модуля следует писать с маленькой буквы - tkinter.
Далее создаем само окно и размещаем на нем необходимые виджеты:
# родительский элемент
root = Tk()
# устанавливаем название окна
root.title("Quadratic calculator")
# устанавливаем минимальный размер окна
root.minsize(325,230)
# выключаем возможность изменять окно
root.resizable(width=False, height=False)
# создаем рабочую область
frame = Frame(root)
frame.grid()
# поле для ввода первого аргумента уравнения (a)
a = Entry(frame, width=3)
a.grid(row=1,column=1,padx=(10,0))
# текст после первого аргумента
a_lab = Label(frame, text="x**2+").grid(row=1,column=2)
# поле для ввода второго аргумента уравнения (b)
b = Entry(frame, width=3)
b.grid(row=1,column=3)
# текст после второго аргумента
b_lab = Label(frame, text="x+").grid(row=1, column=4)
# поле для ввода третьего аргумента уравнения (с)
c = Entry(frame, width=3)
c.grid(row=1, column=5)
# текст после третьего аргумента
c_lab = Label(frame, text="= 0").grid(row=1, column=6)
# кнопка решить
but = Button(frame, text="Solve").grid(row=1, column=7, padx=(10,0))
# место для вывода решения уравнения
output = Text(frame, bg="lightblue", font="Arial 12", width=35, height=10)
output.grid(row=2, columnspan=8)
# запускаем главное окно
root.mainloop()
Если вы в точности повторили указанный код, то после запуска скрипта у вас получится примерно следующее окно:
Отлично, программа работает. Осталось объяснить Python как связать эти две части.
Часть третья: объединяем все воедино
Задача перед нами стоит следующая - написать функцию, которая будет брать числа из полей для ввода, передавать их функции решения квадратного уравнения и выводить результат в поле для вывода. Конечно, все это можно реализовать в одной функции, но лучше разделить на несколько:
Функция вставки информации:
def inserter(value):
""" Inserts specified value into text widget """
output.delete("0.0","end")
output.insert("0.0",value)
Функция inserter предельно проста: очищает поле для ввода и вставляет туда переданный ей аргумент value.
Напишем функцию обработки введенной информации. Назовем ее handler:
def handler():
""" Get the content of entries and passes result to the output area """
try:
# make sure that we entered correct values
a_val = float(a.get())
b_val = float(b.get())
c_val = float(c.get())
inserter(solver(a_val, b_val, c_val))
except ValueError:
inserter("Make sure you entered 3 numbers")
В зависимости от данных введенных в поля для ввода передает функции inserter либо результат решения уравнения, либо сообщение о неверно введенных данных.
Чтобы все работало, следует изменить строку создания виджета Button следующим образом:
but = Button(frame, text="Solve", command=handler).grid(row=1, column=7, padx=(10,0))
Теперь можно спокойно пользоваться нашей программой:
Часть четвертая: необязательная
Можно добавить немного удобства для нашей программы. Проблема в том, что каждый раз вводя новые значения нам приходится удалять старые, что не очень комфортно. Напишем функцию, которая будет очищать поле для ввода после клика по нему.
def clear(event):
""" Clears entry form """
caller = event.widget
caller.delete("0", "end")
Таким образом мы очищаем виджет, вызвавший данную функцию. Чтобы все работало, добавьте следующие строки после создания виджетов, но до размещения. Например, после строки a = Entry(... , но до строки a.grid(...
a.bind("<FocusIn>", clear)
b.bind("<FocusIn>", clear)
c.bind("<FocusIn>", clear)
Готово. Программа работает, Вы великолепны!