Files
help_lab/view.py
T
artemiy 6798fd5f63 Исправления:
- Добавлен столбец 'Разбавление (x)' для каждого реагента
- Переработана логика расчёта с учётом разбавления
- Исправлен расчёт количества растворителя
- Растворитель отображается в первой строке таблицы
- Поддержка дробных значений разбавления
2026-05-05 22:31:08 +05:00

240 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from PyQt5.QtWidgets import (QMainWindow, QVBoxLayout, QHBoxLayout,
QTableWidget, QTableWidgetItem, QPushButton,
QLabel, QDoubleSpinBox, QComboBox, QLineEdit,
QWidget, QMessageBox)
from PyQt5.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Калькулятор питательных сред")
self.setGeometry(100, 100, 1000, 600)
self._init_ui()
def _init_ui(self):
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout()
# Верхняя панель: параметры среды
top_layout = QHBoxLayout()
top_layout.addWidget(QLabel("Общее количество:"))
self.amount_input = QDoubleSpinBox()
self.amount_input.setRange(0.001, 1000000.0)
self.amount_input.setValue(1000.0)
top_layout.addWidget(self.amount_input)
self.amount_unit_combo = QComboBox()
self.amount_unit_combo.addItems(["нл", "мкл", "мл", "л"])
self.amount_unit_combo.setCurrentText("мл")
top_layout.addWidget(self.amount_unit_combo)
top_layout.addWidget(QLabel("Растворитель:"))
self.solvent_input = QLineEdit("Вода")
top_layout.addWidget(self.solvent_input)
layout.addLayout(top_layout)
# Таблица реагентов (с растворителем в первой строке)
layout.addWidget(QLabel("Состав среды:"))
self.table = QTableWidget()
self.table.setColumnCount(6) # Увеличиваем до 6 колонок
self.table.setHorizontalHeaderLabels(["Название", "%", "Единица", "Коэфф.", "Разбавление (x)", "Результат"])
layout.addWidget(self.table)
# Кнопки управления
btn_layout = QHBoxLayout()
self.add_row_btn = QPushButton("Добавить реагент")
self.remove_row_btn = QPushButton("Удалить реагент")
self.calculate_btn = QPushButton("Рассчитать")
self.save_btn = QPushButton("Сохранить")
self.load_btn = QPushButton("Загрузить")
btn_layout.addWidget(self.add_row_btn)
btn_layout.addWidget(self.remove_row_btn)
btn_layout.addWidget(self.calculate_btn)
btn_layout.addWidget(self.save_btn)
btn_layout.addWidget(self.load_btn)
layout.addLayout(btn_layout)
central_widget.setLayout(layout)
self.add_initial_rows()
def add_initial_rows(self):
"""Добавляет начальные строки: растворитель и первый реагент"""
# Добавляем строку растворителя (первая, нередактируемая)
self.add_solvent_row()
# Добавляем строку для первого реагента
self.add_new_row()
def add_solvent_row(self):
"""Добавляет строку растворителя (нередактируемая)"""
row_count = self.table.rowCount()
self.table.insertRow(row_count)
# Название растворителя (берём из поля ввода)
solvent_name = self.solvent_input.text()
solvent_item = QTableWidgetItem(solvent_name)
solvent_item.setFlags(solvent_item.flags() & ~Qt.ItemIsEditable)
solvent_item.setBackground(Qt.lightGray)
self.table.setItem(row_count, 0, solvent_item)
# Процент (будет рассчитан автоматически)
percent_item = QTableWidgetItem("")
percent_item.setFlags(percent_item.flags() & ~Qt.ItemIsEditable)
percent_item.setBackground(Qt.lightGray)
self.table.setItem(row_count, 1, percent_item)
# Единица измерения (не используется для растворителя)
unit_item = QTableWidgetItem("-")
unit_item.setFlags(unit_item.flags() & ~Qt.ItemIsEditable)
unit_item.setBackground(Qt.lightGray)
self.table.setItem(row_count, 2, unit_item)
# Коэффициент (не используется для растворителя)
coeff_item = QTableWidgetItem("-")
coeff_item.setFlags(coeff_item.flags() & ~Qt.ItemIsEditable)
coeff_item.setBackground(Qt.lightGray)
self.table.setItem(row_count, 3, coeff_item)
# Разбавление (не используется для растворителя)
dilution_item = QTableWidgetItem("-")
dilution_item.setFlags(dilution_item.flags() & ~Qt.ItemIsEditable)
dilution_item.setBackground(Qt.lightGray)
self.table.setItem(row_count, 4, dilution_item)
# Результат (будет заполнен при расчёте)
result_item = QTableWidgetItem("")
result_item.setFlags(result_item.flags() & ~Qt.ItemIsEditable)
result_item.setBackground(Qt.lightGray)
self.table.setItem(row_count, 5, result_item)
def update_solvent_name(self):
"""Обновляет название растворителя в первой строке таблицы"""
solvent_name = self.solvent_input.text()
name_item = self.table.item(0, 0)
if name_item:
name_item.setText(solvent_name)
def add_new_row(self):
"""Добавляет новую строку для реагента"""
row_count = self.table.rowCount()
self.table.insertRow(row_count)
self.table.setItem(row_count, 0, QTableWidgetItem(f"Реагент_{row_count}"))
self.table.setItem(row_count, 1, QTableWidgetItem("0.0"))
unit_combo = QComboBox()
unit_combo.addItems(["нг", "мкг", "мг", "г", "кг", "нл", "мкл", "мл", "л"])
unit_combo.setCurrentText("г")
self.table.setCellWidget(row_count, 2, unit_combo)
self.table.setItem(row_count, 3, QTableWidgetItem("1.0"))
# Разбавление - обычное текстовое поле
dilution_edit = QLineEdit("1.0")
dilution_edit.setAlignment(Qt.AlignRight)
dilution_edit.setToolTip("Во сколько раз разбавить (1 = без разбавления)")
self.table.setCellWidget(row_count, 4, dilution_edit)
self.table.setItem(row_count, 5, QTableWidgetItem(""))
def remove_selected_row(self):
"""Удаляет выделенную строку из таблицы (кроме строки растворителя)"""
selected_rows = set()
for item in self.table.selectedItems():
selected_rows.add(item.row())
# Удаляем строки в обратном порядке, пропуская строку растворителя (индекс 0)
for row in sorted(selected_rows, reverse=True):
if row > 0: # Не удаляем строку растворителя
self.table.removeRow(row)
def get_table_data(self) -> list:
"""Возвращает данные таблицы в виде списка списков (только реагенты, без растворителя)"""
data = []
# Начинаем с 1 строки (пропускаем растворитель)
for row in range(1, self.table.rowCount()):
row_data = []
# Название (колонка 0)
name_item = self.table.item(row, 0)
row_data.append(name_item.text() if name_item else "")
# Процент (колонка 1)
percent_item = self.table.item(row, 1)
row_data.append(percent_item.text() if percent_item else "0")
# Единица измерения (колонка 2 - комбобокс)
unit_widget = self.table.cellWidget(row, 2)
if unit_widget and isinstance(unit_widget, QComboBox):
row_data.append(unit_widget.currentText())
else:
row_data.append("мг")
# Коэффициент (колонка 3)
coeff_item = self.table.item(row, 3)
row_data.append(coeff_item.text() if coeff_item else "1.0")
# Разбавление (колонка 4 - spinbox)
dilution_widget = self.table.cellWidget(row, 4)
if dilution_widget and isinstance(dilution_widget, QDoubleSpinBox):
dilution_factor = dilution_widget.value()
row_data.append(dilution_factor)
else:
row_data.append(1.0)
data.append(row_data)
return data
def update_solvent_percent(self, solvent_percent: float):
"""Обновляет процент растворителя в первой строке"""
percent_item = self.table.item(0, 1)
if percent_item:
percent_item.setText(f"{solvent_percent:.2f}")
def show_error(self, message: str):
"""Показывает сообщение об ошибке"""
QMessageBox.critical(self, "Ошибка", message)
def update_results(self, results: list):
"""Обновляет столбец результатов (индекс 5) в таблице"""
# Начинаем с 1 строки (реагенты), 0 строка - растворитель
for row, amount in enumerate(results, start=1):
if row < self.table.rowCount():
formatted_amount = f"{amount:.4f}"
self.table.setItem(row, 5, QTableWidgetItem(formatted_amount))
def update_solvent_result(self, solvent_amount: float, unit: str):
"""Обновляет результат для растворителя в первой строке"""
formatted_amount = f"{solvent_amount:.4f}"
result_item = self.table.item(0, 5)
if result_item:
result_item.setText(formatted_amount)
# Также обновляем единицу измерения в колонке 2 для информации
unit_item = self.table.item(0, 2)
if unit_item:
unit_item.setText(unit)
def update_display(self, solvent: str, total_amount: float, amount_unit: str):
"""Обновляет отображение растворителя и общего количества среды"""
self.solvent_input.setText(solvent)
self.update_solvent_name()
self.amount_input.setValue(total_amount)
self.amount_unit_combo.setCurrentText(amount_unit)
def clear_results(self):
"""Очищает столбец результатов для всех строк"""
for row in range(self.table.rowCount()):
self.table.setItem(row, 5, QTableWidgetItem(""))
# Очищаем процент растворителя
percent_item = self.table.item(0, 1)
if percent_item:
percent_item.setText("")
# Очищаем единицу измерения растворителя
unit_item = self.table.item(0, 2)
if unit_item:
unit_item.setText("-")