← Назад к курсу
Создание оконных интерфейсов в Python
В этом уроке мы рассмотрим три самые популярные библиотеки для создания графических интерфейсов (GUI) в Python: Tkinter, PyQt5 и Kivy.
1. Tkinter - стандартная библиотека Python
Tkinter входит в стандартную библиотеку Python и является наиболее простым способом создания GUI.
Базовый пример Tkinter
import tkinter as tk
from tkinter import ttk, messagebox
def on_button_click():
name = entry.get()
if name:
messagebox.showinfo("Приветствие", f"Привет, {name}!")
label_result.config(text=f"Введено: {name}")
else:
messagebox.showwarning("Ошибка", "Введите имя!")
# Создание главного окна
root = tk.Tk()
root.title("Tkinter Пример")
root.geometry("400x300")
# Создание элементов интерфейса
label = ttk.Label(root, text="Введите ваше имя:")
label.pack(pady=10)
entry = ttk.Entry(root, width=30)
entry.pack(pady=5)
button = ttk.Button(root, text="Поздороваться", command=on_button_click)
button.pack(pady=10)
label_result = ttk.Label(root, text="")
label_result.pack(pady=10)
# Запуск главного цикла
root.mainloop()
Расширенный пример с меню и вкладками
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
class TkinterApp:
def __init__(self, root):
self.root = root
self.root.title("Расширенное приложение Tkinter")
self.root.geometry("600x400")
self.create_menu()
self.create_widgets()
def create_menu(self):
menubar = tk.Menu(self.root)
self.root.config(menu=menubar)
file_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Файл", menu=file_menu)
file_menu.add_command(label="Открыть", command=self.open_file)
file_menu.add_command(label="Сохранить", command=self.save_file)
file_menu.add_separator()
file_menu.add_command(label="Выход", command=self.root.quit)
help_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Помощь", menu=help_menu)
help_menu.add_command(label="О программе", command=self.show_about)
def create_widgets(self):
# Создание вкладок
tab_control = ttk.Notebook(self.root)
# Вкладка 1: Форма
tab1 = ttk.Frame(tab_control)
tab_control.add(tab1, text="Форма")
self.create_form_tab(tab1)
# Вкладка 2: Таблица
tab2 = ttk.Frame(tab_control)
tab_control.add(tab2, text="Таблица")
self.create_table_tab(tab2)
tab_control.pack(expand=1, fill="both")
def create_form_tab(self, parent):
frame = ttk.LabelFrame(parent, text="Регистрация", padding=10)
frame.pack(fill="both", expand=True, padx=10, pady=10)
# Поля формы
ttk.Label(frame, text="Имя:").grid(row=0, column=0, sticky="w", pady=5)
self.name_entry = ttk.Entry(frame, width=30)
self.name_entry.grid(row=0, column=1, pady=5, padx=5)
ttk.Label(frame, text="Email:").grid(row=1, column=0, sticky="w", pady=5)
self.email_entry = ttk.Entry(frame, width=30)
self.email_entry.grid(row=1, column=1, pady=5, padx=5)
ttk.Label(frame, text="Возраст:").grid(row=2, column=0, sticky="w", pady=5)
self.age_spinbox = ttk.Spinbox(frame, from_=0, to=120, width=28)
self.age_spinbox.grid(row=2, column=1, pady=5, padx=5)
# Кнопки
btn_frame = ttk.Frame(frame)
btn_frame.grid(row=3, column=0, columnspan=2, pady=10)
ttk.Button(btn_frame, text="Сохранить",
command=self.save_form).pack(side="left", padx=5)
ttk.Button(btn_frame, text="Очистить",
command=self.clear_form).pack(side="left", padx=5)
def create_table_tab(self, parent):
# Таблица с данными
columns = ("Имя", "Email", "Возраст")
self.tree = ttk.Treeview(parent, columns=columns, show="headings", height=10)
for col in columns:
self.tree.heading(col, text=col)
self.tree.column(col, width=150)
# Добавление прокрутки
scrollbar = ttk.Scrollbar(parent, orient="vertical", command=self.tree.yview)
self.tree.configure(yscrollcommand=scrollbar.set)
self.tree.pack(side="left", fill="both", expand=True, padx=10, pady=10)
scrollbar.pack(side="right", fill="y")
# Добавление тестовых данных
for i in range(1, 11):
self.tree.insert("", "end", values=(f"Пользователь {i}",
f"user{i}@example.com",
20 + i))
def save_form(self):
name = self.name_entry.get()
email = self.email_entry.get()
age = self.age_spinbox.get()
if name and email and age:
self.tree.insert("", "end", values=(name, email, age))
messagebox.showinfo("Успех", "Данные сохранены!")
self.clear_form()
else:
messagebox.showwarning("Ошибка", "Заполните все поля!")
def clear_form(self):
self.name_entry.delete(0, tk.END)
self.email_entry.delete(0, tk.END)
self.age_spinbox.delete(0, tk.END)
self.age_spinbox.insert(0, "0")
def open_file(self):
file_path = filedialog.askopenfilename(
title="Выберите файл",
filetypes=[("Текстовые файлы", "*.txt"), ("Все файлы", "*.*")]
)
if file_path:
messagebox.showinfo("Файл", f"Выбран файл: {file_path}")
def save_file(self):
file_path = filedialog.asksaveasfilename(
title="Сохранить файл",
defaultextension=".txt",
filetypes=[("Текстовые файлы", "*.txt"), ("Все файлы", "*.*")]
)
if file_path:
messagebox.showinfo("Сохранение", f"Файл сохранен как: {file_path}")
def show_about(self):
messagebox.showinfo("О программе",
"Пример приложения на Tkinter\nВерсия 1.0")
if __name__ == "__main__":
root = tk.Tk()
app = TkinterApp(root)
root.mainloop()
2. PyQt5 - профессиональный фреймворк для GUI
PyQt5 - мощная библиотека для создания профессиональных приложений с современным интерфейсом.
Установка PyQt5:
pip install PyQt5
Базовый пример PyQt5
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QLabel, QLineEdit, QPushButton,
QMessageBox, QListWidget)
from PyQt5.QtCore import Qt
class PyQt5App(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# Настройка главного окна
self.setWindowTitle("PyQt5 Пример")
self.setGeometry(100, 100, 500, 400)
# Центральный виджет
central_widget = QWidget()
self.setCentralWidget(central_widget)
# Основной layout
main_layout = QVBoxLayout()
central_widget.setLayout(main_layout)
# Создание виджетов
self.label = QLabel("Добавьте элементы в список:")
main_layout.addWidget(self.label)
# Поле ввода и кнопка в горизонтальном layout
input_layout = QHBoxLayout()
self.input_field = QLineEdit()
self.input_field.setPlaceholderText("Введите текст...")
input_layout.addWidget(self.input_field)
self.add_button = QPushButton("Добавить")
self.add_button.clicked.connect(self.add_item)
input_layout.addWidget(self.add_button)
main_layout.addLayout(input_layout)
# Список элементов
self.list_widget = QListWidget()
main_layout.addWidget(self.list_widget)
# Кнопки управления
button_layout = QHBoxLayout()
self.clear_button = QPushButton("Очистить список")
self.clear_button.clicked.connect(self.clear_list)
button_layout.addWidget(self.clear_button)
self.info_button = QPushButton("Информация")
self.info_button.clicked.connect(self.show_info)
button_layout.addWidget(self.info_button)
main_layout.addLayout(button_layout)
# Статус бар
self.statusBar().showMessage("Готово")
def add_item(self):
text = self.input_field.text().strip()
if text:
self.list_widget.addItem(text)
self.input_field.clear()
self.statusBar().showMessage(f"Добавлен элемент: {text}")
else:
QMessageBox.warning(self, "Предупреждение", "Введите текст!")
def clear_list(self):
self.list_widget.clear()
self.statusBar().showMessage("Список очищен")
def show_info(self):
count = self.list_widget.count()
QMessageBox.information(self, "Информация",
f"Количество элементов в списке: {count}")
def main():
app = QApplication(sys.argv)
window = PyQt5App()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Расширенный пример PyQt5 с вкладками и таблицей
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QTabWidget, QTableWidget,
QTableWidgetItem, QLabel, QLineEdit, QPushButton,
QComboBox, QDateEdit, QMessageBox, QHeaderView)
from PyQt5.QtCore import QDate, Qt
from PyQt5.QtGui import QFont
class EmployeeManager(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
self.employees = []
def initUI(self):
self.setWindowTitle("Менеджер сотрудников")
self.setGeometry(100, 100, 800, 600)
# Центральный виджет с вкладками
self.tab_widget = QTabWidget()
self.setCentralWidget(self.tab_widget)
# Создание вкладок
self.create_add_employee_tab()
self.create_view_employees_tab()
# Статус бар
self.statusBar().showMessage("Добро пожаловать в менеджер сотрудников")
def create_add_employee_tab(self):
tab = QWidget()
self.tab_widget.addTab(tab, "Добавить сотрудника")
layout = QVBoxLayout()
tab.setLayout(layout)
# Заголовок
title = QLabel("Добавление нового сотрудника")
title_font = QFont()
title_font.setPointSize(14)
title_font.setBold(True)
title.setFont(title_font)
title.setAlignment(Qt.AlignCenter)
layout.addWidget(title)
# Форма
form_layout = QVBoxLayout()
# Имя
name_layout = QHBoxLayout()
name_label = QLabel("Имя:")
name_label.setFixedWidth(100)
self.name_input = QLineEdit()
self.name_input.setPlaceholderText("Введите имя")
name_layout.addWidget(name_label)
name_layout.addWidget(self.name_input)
form_layout.addLayout(name_layout)
# Должность
position_layout = QHBoxLayout()
position_label = QLabel("Должность:")
position_label.setFixedWidth(100)
self.position_combo = QComboBox()
self.position_combo.addItems(["Разработчик", "Дизайнер", "Менеджер",
"Тестировщик", "Аналитик"])
position_layout.addWidget(position_label)
position_layout.addWidget(self.position_combo)
form_layout.addLayout(position_layout)
# Зарплата
salary_layout = QHBoxLayout()
salary_label = QLabel("Зарплата:")
salary_label.setFixedWidth(100)
self.salary_input = QLineEdit()
self.salary_input.setPlaceholderText("Введите зарплату")
salary_layout.addWidget(salary_label)
salary_layout.addWidget(self.salary_input)
form_layout.addLayout(salary_layout)
# Дата приема
date_layout = QHBoxLayout()
date_label = QLabel("Дата приема:")
date_label.setFixedWidth(100)
self.date_input = QDateEdit()
self.date_input.setDate(QDate.currentDate())
self.date_input.setCalendarPopup(True)
date_layout.addWidget(date_label)
date_layout.addWidget(self.date_input)
form_layout.addLayout(date_layout)
layout.addLayout(form_layout)
# Кнопки
button_layout = QHBoxLayout()
self.add_button = QPushButton("Добавить сотрудника")
self.add_button.clicked.connect(self.add_employee)
self.add_button.setStyleSheet("background-color: #4CAF50; color: white;")
self.clear_button = QPushButton("Очистить форму")
self.clear_button.clicked.connect(self.clear_form)
self.clear_button.setStyleSheet("background-color: #f44336; color: white;")
button_layout.addWidget(self.add_button)
button_layout.addWidget(self.clear_button)
layout.addLayout(button_layout)
def create_view_employees_tab(self):
tab = QWidget()
self.tab_widget.addTab(tab, "Просмотр сотрудников")
layout = QVBoxLayout()
tab.setLayout(layout)
# Таблица сотрудников
self.table = QTableWidget()
self.table.setColumnCount(5)
self.table.setHorizontalHeaderLabels(["ID", "Имя", "Должность",
"Зарплата", "Дата приема"])
# Настройка таблицы
header = self.table.horizontalHeader()
header.setSectionResizeMode(1, QHeaderView.Stretch)
layout.addWidget(self.table)
# Кнопки для таблицы
button_layout = QHBoxLayout()
self.refresh_button = QPushButton("Обновить таблицу")
self.refresh_button.clicked.connect(self.refresh_table)
self.delete_button = QPushButton("Удалить выбранного")
self.delete_button.clicked.connect(self.delete_employee)
self.delete_button.setStyleSheet("background-color: #ff9800; color: white;")
button_layout.addWidget(self.refresh_button)
button_layout.addWidget(self.delete_button)
layout.addLayout(button_layout)
def add_employee(self):
name = self.name_input.text().strip()
position = self.position_combo.currentText()
salary = self.salary_input.text().strip()
date = self.date_input.date().toString("dd.MM.yyyy")
if not name:
QMessageBox.warning(self, "Ошибка", "Введите имя сотрудника!")
return
if not salary.isdigit():
QMessageBox.warning(self, "Ошибка", "Зарплата должна быть числом!")
return
# Добавление сотрудника
employee_id = len(self.employees) + 1
employee = {
'id': employee_id,
'name': name,
'position': position,
'salary': int(salary),
'date': date
}
self.employees.append(employee)
QMessageBox.information(self, "Успех",
f"Сотрудник {name} добавлен успешно!")
self.clear_form()
self.refresh_table()
self.statusBar().showMessage(f"Добавлен сотрудник: {name}")
def clear_form(self):
self.name_input.clear()
self.position_combo.setCurrentIndex(0)
self.salary_input.clear()
self.date_input.setDate(QDate.currentDate())
def refresh_table(self):
self.table.setRowCount(len(self.employees))
for row, employee in enumerate(self.employees):
self.table.setItem(row, 0, QTableWidgetItem(str(employee['id'])))
self.table.setItem(row, 1, QTableWidgetItem(employee['name']))
self.table.setItem(row, 2, QTableWidgetItem(employee['position']))
self.table.setItem(row, 3, QTableWidgetItem(str(employee['salary'])))
self.table.setItem(row, 4, QTableWidgetItem(employee['date']))
self.statusBar().showMessage(f"Загружено {len(self.employees)} сотрудников")
def delete_employee(self):
selected_row = self.table.currentRow()
if selected_row >= 0:
employee_name = self.employees[selected_row]['name']
reply = QMessageBox.question(self, "Подтверждение",
f"Удалить сотрудника {employee_name}?",
QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.Yes:
del self.employees[selected_row]
self.refresh_table()
self.statusBar().showMessage(f"Удален сотрудник: {employee_name}")
else:
QMessageBox.warning(self, "Ошибка", "Выберите сотрудника для удаления!")
def main():
app = QApplication(sys.argv)
window = EmployeeManager()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
3. Kivy - кроссплатформенная библиотека для мобильных и десктопных приложений
Kivy позволяет создавать приложения для Windows, macOS, Linux, Android и iOS.
Установка Kivy:
pip install kivy
Базовый пример Kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.popup import Popup
from kivy.core.window import Window
Window.clearcolor = (0.9, 0.9, 0.9, 1) # Светло-серый фон
class KivyApp(App):
def build(self):
# Основной layout
self.layout = BoxLayout(orientation='vertical', spacing=10, padding=20)
# Заголовок
title = Label(
text='Приложение Kivy',
font_size=24,
color=(0.2, 0.2, 0.2, 1)
)
self.layout.add_widget(title)
# Поле ввода
self.input_field = TextInput(
hint_text='Введите сообщение...',
multiline=False,
size_hint_y=None,
height=40
)
self.layout.add_widget(self.input_field)
# Кнопка
self.button = Button(
text='Показать сообщение',
size_hint_y=None,
height=50,
background_color=(0.2, 0.6, 0.8, 1)
)
self.button.bind(on_press=self.show_message)
self.layout.add_widget(self.button)
# Метка для результата
self.result_label = Label(
text='',
font_size=18,
color=(0.3, 0.3, 0.3, 1)
)
self.layout.add_widget(self.result_label)
# Кнопка очистки
clear_button = Button(
text='Очистить',
size_hint_y=None,
height=40,
background_color=(0.8, 0.3, 0.3, 1)
)
clear_button.bind(on_press=self.clear_text)
self.layout.add_widget(clear_button)
return self.layout
def show_message(self, instance):
message = self.input_field.text.strip()
if message:
self.result_label.text = f'Вы ввели: {message}'
# Показ всплывающего окна
popup_content = BoxLayout(orientation='vertical', spacing=10)
popup_content.add_widget(Label(text=f'Сообщение:\n{message}'))
close_button = Button(text='Закрыть', size_hint_y=None, height=40)
popup = Popup(
title='Ваше сообщение',
content=popup_content,
size_hint=(0.8, 0.4)
)
close_button.bind(on_press=popup.dismiss)
popup_content.add_widget(close_button)
popup.open()
else:
self.result_label.text = 'Пожалуйста, введите сообщение!'
def clear_text(self, instance):
self.input_field.text = ''
self.result_label.text = ''
if __name__ == '__main__':
KivyApp().run()
Сравнение библиотек
| Критерий | Tkinter | PyQt5 | Kivy |
|---|---|---|---|
| Сложность | Низкая | Высокая | Средняя |
| Внешний вид | Базовый | Профессиональный | Современный |
| Производительность | Хорошая | Отличная | Хорошая |
| Кроссплатформенность | Да | Да | Да (включая мобильные) |
| Документация | Хорошая | Отличная | Хорошая |
| Поддержка | Отличная | Хорошая | Хорошая |
| Лицензия | Python | GPL/Commercial | MIT |
Рекомендации по выбору:
- Tkinter - лучший выбор для начинающих, простых приложений и быстрого прототипирования.
- PyQt5 - идеален для профессиональных десктопных приложений с сложным интерфейсом.
- Kivy - оптимален для кроссплатформенных приложений, включая мобильные.
Заключение
Каждая библиотека имеет свои преимущества. Начните с Tkinter для понимания основ, затем изучите PyQt5 для создания профессиональных приложений или Kivy для мобильной разработки. Все три библиотеки активно развиваются и имеют большое сообщество пользователей.