Создание десктопных приложений на Python: графическое программирование

Раздел: Разработка на Python -> Графический интерфейс

Основы графического программирования на Python

Графическое программирование на Python позволяет создавать приложения с оконным интерфейсом. Выбор библиотеки зависит от требуемой сложности, кроссплатформенности и визуального стиля. Наиболее эффективное решение для быстрого прототипирования и обучения - встроенная библиотека Tkinter. Она идёт в комплекте с Python, не требует дополнительных установок и имеет обширную документацию.

Базовое окно с кнопкой на Tkinter

Как создать простое окно и реагировать на нажатие кнопки?

import tkinter as tk

def say_hello():
    label.config(text="Привет, мир!")

root = tk.Tk()
root.title("Моё приложение")

label = tk.Label(root, text="Текст")
label.pack()

button = tk.Button(root, text="Нажми меня", command=say_hello)
button.pack()

root.mainloop()

открыть окно python (открыть окно на python)

В этом примере создаётся окно с заголовком, меткой и кнопкой. При нажатии на кнопку текст метки изменяется. Важно: после настройки всех виджетов вызывается mainloop() - иначе окно не появится.

Типичная ошибка: изменение текста метки до вызова mainloop() может не отобразиться. Решение: все изменения выполняются после создания окна и в обработчиках событий. Ещё одна распространённая проблема - блокировка интерфейса при длительных операциях. Для этого используют метод after() или потоки.

Вариант с PyQt6: более современный интерфейс

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

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton

def say_hello():
    label.setText("Привет от PyQt")

app = QApplication(sys.argv)
window = QMainWindow()
window.setWindowTitle("PyQt окно")

label = QLabel("Текст", window)
label.move(50, 50)

button = QPushButton("Нажми", window)
button.clicked.connect(say_hello)
button.move(50, 100)

window.show()
sys.exit(app.exec())

Python окно (создание окон в python tkinter)

PyQt предоставляет множество готовых виджетов и систему сигналов и слотов. В отличие от Tkinter, требуется создание экземпляра QApplication и ручное управление координатами (или использование layout).

Проблема: PyQt6 - внешняя библиотека, её нужно устанавливать (pip install PyQt6). Ошибка: забытый вызов show() - окно не отобразится. Также важно помнить, что app.exec() блокирует выполнение, аналогично mainloop.

Вариант с Kivy: мультитач и мобильные приложения

Какая библиотека подходит для приложений с сенсорным управлением и поддержкой Android?

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout

def say_hello(instance):
    label.text = "Привет из Kivy"

class MainApp(App):
    def build(self):
        layout = BoxLayout(orientation='vertical')
        self.label = Label(text="Текст")
        button = Button(text="Нажми")
        button.bind(on_press=say_hello)
        layout.add_widget(self.label)
        layout.add_widget(button)
        return layout

if __name__ == "__main__":
    MainApp().run()

Python tkinter canvas (холст canvas в tkinter)

Kivy использует собственный язык разметки .kv, но в примере код написан на чистом Python. Приложение запускается через метод run().

Ошибка: Kivy требует Python 3.8+ и специфические зависимости на некоторых платформах. Типичная проблема - отсутствие поддерки русского шрифта; требуется установка Label с нужным шрифтом.

Вариант с Flet: веб-подобные интерфейсы

Как создать кроссплатформенное приложение с современным дизайном, используя Flutter из Python?

import flet as ft

def main(page: ft.Page):
    page.title = "Flet приложение"
    label = ft.Text("Текст")
    button = ft.ElevatedButton(text="Нажми", on_click=lambda e: setattr(label, "value", "Привет от Flet"))
    page.add(label, button)

ft.app(target=main)

Flet позволяет создавать интерфейсы в стиле Material Design. Код напоминает Flutter, но на Python. Приложение обновляется автоматически при изменении состояния.

Проблема: Flet всё ещё активно развивается, возможны изменения API. Ошибка: забытая асинхронность в обработчиках событий - для сложных операций требуется async.

- Python tkinter виджет (виджеты tkinter)
- Python file select (диалог выбора файла в python (tkinter.filedialog))
- Python tkinter игра (игра на tkinter)

Расширенные примеры графического программирования

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

Пример 1: Форма ввода с проверкой данных на Tkinter

Создадим окно с полями для имени и возраста, кнопкой отправки и проверкой корректности.

Пример
import tkinter as tk
from tkinter import messagebox

def submit():
    name = entry_name.get()
    age = entry_age.get()
    if not name:
        messagebox.showerror("Ошибка", "Имя не может быть пустым")
        return
    try:
        age_int = int(age)
        if age_int < 0:
            raise ValueError
    except ValueError:
        messagebox.showerror("Ошибка", "Возраст должен быть положительным числом")
        return
    messagebox.showinfo("Успех", f"Привет, {name}! Тебе {age} лет.")

root = tk.Tk()
root.title("Форма регистрации")

tk.Label(root, text="Имя:").grid(row=0, column=0, padx=5, pady=5)
entry_name = tk.Entry(root)
entry_name.grid(row=0, column=1, padx=5, pady=5)

tk.Label(root, text="Возраст:").grid(row=1, column=0, padx=5, pady=5)
entry_age = tk.Entry(root)
entry_age.grid(row=1, column=1, padx=5, pady=5)

tk.Button(root, text="Отправить", command=submit).grid(row=2, column=0, columnspan=2, pady=10)

root.mainloop()
Появляется окно с полями. При пустом имени или неверном возрасте - всплывающее окно ошибки.

Пример 2: Холст для рисования в Tkinter

Используем виджет Canvas для создания простого графического редактора.

Пример
import tkinter as tk

def paint(event):
    x1, y1 = (event.x - 1), (event.y - 1)
    x2, y2 = (event.x + 1), (event.y + 1)
    canvas.create_oval(x1, y1, x2, y2, fill="black", width=5)

root = tk.Tk()
root.title("Рисовалка")

canvas = tk.Canvas(root, width=400, height=400, bg="white")
canvas.pack()
canvas.bind("", paint)

root.mainloop()
Окно с белым холстом; при перемещении мыши с зажатой левой кнопкой рисуются чёрные точки.

Пример 3: Анимация круга на PyQt6

Реализуем движение круга по экрану с помощью QTimer.

Пример
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt6.QtGui import QPainter, QBrush, QColor
from PyQt6.QtCore import QTimer, Qt

class MovingCircle(QWidget):
    def __init__(self):
        super().__init__()
        self.x = 0
        self.timer = QTimer()
        self.timer.timeout.connect(self.move_circle)
        self.timer.start(30)

    def move_circle(self):
        self.x += 2
        if self.x > self.width():
            self.x = 0
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setBrush(QBrush(QColor("blue")))
        painter.drawEllipse(self.x, 50, 50, 50)

app = QApplication(sys.argv)
window = QMainWindow()
window.setWindowTitle("Анимация")
window.setCentralWidget(MovingCircle())
window.resize(400, 200)
window.show()
sys.exit(app.exec())
Синий круг движется слева направо и снова появляется слева.

Пример 4: Многопоточность в Tkinter (загрузка данных)

Демонстрация работы с длительной операцией без блокировки интерфейса.

Пример
import tkinter as tk
import threading
import time

def long_task():
    time.sleep(5)
    root.after(0, lambda: label.config(text="Задача завершена"))

def start_thread():
    thread = threading.Thread(target=long_task, daemon=True)
    thread.start()
    label.config(text="Выполняется...")

root = tk.Tk()
root.title("Многопоточность")

label = tk.Label(root, text="Нажмите кнопку")
label.pack()

tk.Button(root, text="Запустить задачу", command=start_thread).pack()

root.mainloop()
После нажатия кнопки текст меняется на 'Выполняется...', через 5 секунд - 'Задача завершена'. Интерфейс не зависает.

Пример 5: Интеграция matplotlib с Tkinter

Отобразим график функции внутри окна Tkinter.

Пример
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np

def plot_graph():
    fig = Figure(figsize=(5, 4))
    ax = fig.add_subplot(111)
    x = np.linspace(0, 2*np.pi, 100)
    y = np.sin(x)
    ax.plot(x, y)
    ax.set_title("Синусоида")
    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.draw()
    canvas.get_tk_widget().pack()

root = tk.Tk()
root.title("График в Tkinter")
tk.Button(root, text="Показать график", command=plot_graph).pack()
root.mainloop()
При нажатии на кнопку под ней появляется график синусоиды.

Графическое программирование на Python - comments

En
графическое программирование python (python)