Загрузка данных
import sys
from PyQt6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout,
QLabel, QComboBox, QDateEdit, QTimeEdit,
QDateTimeEdit, QPushButton, QTextEdit, QGroupBox,
QCheckBox, QMessageBox)
from PyQt6.QtCore import QDate, QTime, QDateTime
class FitnessTrackerApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Фитнес-трекер (Пример PyQt6)")
self.resize(400, 600)
# Основной вертикальный слой
self.main_layout = QVBoxLayout()
self.setLayout(self.main_layout)
# --- 1. Виджеты выбора даты и времени ---
self.create_datetime_widgets()
# --- 2. Виджет QComboBox и сигналы-слоты ---
self.create_combobox_widgets()
# --- 3. Дополнительные услуги (для примера логики) ---
self.create_extra_services()
# --- 4. Блок вывода результатов и очистки layout ---
self.create_output_area()
# Кнопка расчета
self.btn_calculate = QPushButton("Рассчитать стоимость")
self.btn_calculate.clicked.connect(self.calculate_cost)
self.main_layout.addWidget(self.btn_calculate)
def create_datetime_widgets(self):
group = QGroupBox("Период тренировок")
layout = QVBoxLayout()
# QDateEdit (только дата)
self.date_start = QDateEdit()
self.date_start.setDate(QDate(2026, 1, 19)) # Установка даты как на скрине
self.date_start.setCalendarPopup(True) # Включаем всплывающий календарь
layout.addWidget(QLabel("Начало цикла (QDateEdit):"))
layout.addWidget(self.date_start)
# QDateEdit (окончание)
self.date_end = QDateEdit()
self.date_end.setDate(QDate(2026, 2, 19))
self.date_end.setCalendarPopup(True)
layout.addWidget(QLabel("Окончание цикла (QDateEdit):"))
layout.addWidget(self.date_end)
# QTimeEdit (только время)
self.time_edit = QTimeEdit()
self.time_edit.setTime(QTime(10, 0)) # 10:00
layout.addWidget(QLabel("Время тренировки (QTimeEdit):"))
layout.addWidget(self.time_edit)
# QDateTimeEdit (дата и время)
self.datetime_edit = QDateTimeEdit()
self.datetime_edit.setDateTime(QDateTime.currentDateTime())
layout.addWidget(QLabel("Точное время записи (QDateTimeEdit):"))
layout.addWidget(self.datetime_edit)
group.setLayout(layout)
self.main_layout.addWidget(group)
def create_combobox_widgets(self):
group = QGroupBox("Цель тренировок")
layout = QVBoxLayout()
self.combo_goal = QComboBox()
# Добавляем элементы с данными (текст, стоимость)
self.combo_goal.addItem("Похудение (3000 руб/мес)", 3000)
self.combo_goal.addItem("Поддержание формы (2500 руб/мес)", 2500)
self.combo_goal.addItem("Набор массы (3500 руб/мес)", 3500)
# --- ПРИМЕР СИГНАЛ-СЛОТ ДЛЯ COMBOBOX ---
# Сигнал currentIndexChanged срабатывает при смене выбора
self.combo_goal.currentIndexChanged.connect(self.on_goal_changed)
layout.addWidget(QLabel("Выберите цель:"))
layout.addWidget(self.combo_goal)
group.setLayout(layout)
self.main_layout.addWidget(group)
def create_extra_services(self):
group = QGroupBox("Дополнительные услуги")
layout = QVBoxLayout()
self.check_trainer = QCheckBox("Персональный тренер (+15000 руб/мес)")
self.check_diet = QCheckBox("Индивидуальный план питания (+5000 руб)")
# Устанавливаем галочку как на втором скрине
self.check_diet.setChecked(True)
layout.addWidget(self.check_trainer)
layout.addWidget(self.check_diet)
group.setLayout(layout)
self.main_layout.addWidget(group)
def create_output_area(self):
self.group_output = QGroupBox("Стоимость фитнес-программы")
self.output_layout = QVBoxLayout() # Этот layout мы будем очищать
self.text_details = QTextEdit()
self.text_details.setReadOnly(True)
self.text_details.setMaximumHeight(100)
self.label_monthly = QLabel("Ежемесячно: 0 руб")
self.label_total = QLabel("За весь период: 0 руб")
self.label_total.setStyleSheet("font-size: 16px; font-weight: bold; color: #d32f2f;")
self.output_layout.addWidget(QLabel("Детали расчета:"))
self.output_layout.addWidget(self.text_details)
self.output_layout.addWidget(self.label_monthly)
self.output_layout.addWidget(self.label_total)
self.group_output.setLayout(self.output_layout)
self.main_layout.addWidget(self.group_output)
# --- СЛОТ (обработчик сигнала) ---
def on_goal_changed(self, index):
"""Этот метод вызывается при смене пункта в QComboBox"""
selected_text = self.combo_goal.currentText()
selected_data = self.combo_goal.currentData() # Получаем число 3000, 2500 и т.д.
print(f"Выбрана цель: {selected_text}. Базовая стоимость: {selected_data} руб.")
# Можно сразу обновить интерфейс, если нужно
# self.calculate_cost()
# --- ОЧИСТКА LAYOUT ---
def clear_layout(self, layout):
"""Рекурсивная функция для полной очистки layout"""
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.deleteLater() # Важно для удаления виджета из памяти
else:
# Если внутри лежит другой layout, очищаем и его
self.clear_layout(item.layout())
# --- ЛОГИКА РАСЧЕТА (по кнопке) ---
def calculate_cost(self):
# 1. Получаем данные
base_price = self.combo_goal.currentData()
# Считаем количество месяцев между датами
date_start = self.date_start.date()
date_end = self.date_end.date()
days_diff = date_start.daysTo(date_end)
months = max(1, round(days_diff / 30)) # Округляем до месяцев, минимум 1
# 2. Считаем доп услуги
extra_cost = 0
details = [f"Базовая программа: {base_price} руб/мес", f"Период: {months} мес"]
if self.check_trainer.isChecked():
extra_cost += 15000
details.append("Персональный тренер: +15,000 руб")
if self.check_diet.isChecked():
extra_cost += 5000
details.append("Индивидуальный план питания: +5,000 руб")
# 3. Итоговые расчеты
monthly_total = base_price + extra_cost
total_cost = monthly_total * months
# 4. Обновляем UI
self.text_details.setText("\n".join(details))
self.label_monthly.setText(f"Ежемесячно: {monthly_total:,} руб".replace(",", " "))
self.label_total.setText(f"За весь период: {total_cost:,} руб".replace(",", " "))
# Пример вызова очистки (например, по нажатию другой кнопки)
def reset_ui(self):
# ВНИМАНИЕ: Если вы очистите layout, в котором лежат виджеты,
# они исчезнут с экрана. Используйте это, если хотите
# динамически перестраивать интерфейс.
self.clear_layout(self.output_layout)
# После очистки нужно заново добавить виджеты, если они нужны
# (В данном коде мы просто очищаем, поэтому интерфейс "сломается",
# если не добавить их обратно. Это демонстрация метода).
if __name__ == "__main__":
app = QApplication(sys.argv)
window = FitnessTrackerApp()
window.show()
sys.exit(app.exec())