From 18071e8d2b3ba1c22f340af1486de30490a13d40 Mon Sep 17 00:00:00 2001 From: MarcusStill <69536339+MarcusStill@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:54:58 +0000 Subject: [PATCH] Modernize PySide6 UI with Windows 10/11 flat design and fix deprecations - Added `files/style.qss` implementing a clean, flat aesthetic using Segoe UI and an accent color. - Updated `main.py` to globally load and apply the new `.qss` file. - Replaced deprecated `.exec_()` with `.exec()` on QDialog instances for full PySide6 compatibility. - Safely removed invalid `window.exec_()` call on `QMainWindow` instance. --- files/style.qss | 210 ++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 22 +++-- 2 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 files/style.qss diff --git a/files/style.qss b/files/style.qss new file mode 100644 index 0000000..b3e137e --- /dev/null +++ b/files/style.qss @@ -0,0 +1,210 @@ +/* + PyMASL Windows 10/11 Flat Design QSS Theme + Font: Segoe UI + Accent Color: #0078D4 +*/ + +* { + font-family: "Segoe UI", "San Francisco", "Helvetica Neue", Arial, sans-serif; + font-size: 14px; + color: #1a1a1a; +} + +QMainWindow, QDialog, QWidget { + background-color: #f3f3f3; +} + +/* Button */ +QPushButton { + background-color: #ffffff; + border: 1px solid #cccccc; + border-radius: 4px; + padding: 6px 12px; + color: #1a1a1a; +} + +QPushButton:hover { + background-color: #e5e5e5; + border-color: #b3b3b3; +} + +QPushButton:pressed { + background-color: #cccccc; + border-color: #999999; +} + +QPushButton:disabled { + background-color: #f9f9f9; + color: #a0a0a0; + border-color: #e0e0e0; +} + +/* Primary/Accent Button behavior can be set via custom properties if needed, + but globally we give them a subtle clean look. */ + +/* LineEdit / TextEdit / DateEdit / ComboBox */ +QLineEdit, QTextEdit, QPlainTextEdit, QDateEdit, QComboBox, QSpinBox, QDoubleSpinBox { + background-color: #ffffff; + border: 1px solid #cccccc; + border-radius: 4px; + padding: 4px; + color: #1a1a1a; +} + +QLineEdit:focus, QTextEdit:focus, QDateEdit:focus, QComboBox:focus, QSpinBox:focus { + border: 1px solid #0078D4; +} + +QLineEdit:disabled, QDateEdit:disabled, QComboBox:disabled { + background-color: #f0f0f0; + color: #8c8c8c; +} + +/* ComboBox Dropdown */ +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 20px; + border-left: 1px solid transparent; +} + +QComboBox QAbstractItemView { + background-color: #ffffff; + border: 1px solid #cccccc; + selection-background-color: #0078D4; + selection-color: #ffffff; +} + +/* Table */ +QTableWidget, QTableView { + background-color: #ffffff; + border: 1px solid #cccccc; + gridline-color: #e0e0e0; + selection-background-color: #0078D4; + selection-color: #ffffff; +} + +QHeaderView::section { + background-color: #f9f9f9; + padding: 4px; + border: none; + border-right: 1px solid #e0e0e0; + border-bottom: 1px solid #e0e0e0; + font-weight: bold; +} + +/* Scrollbars */ +QScrollBar:vertical { + border: none; + background-color: #f3f3f3; + width: 12px; + margin: 0px 0px 0px 0px; +} +QScrollBar::handle:vertical { + background-color: #c1c1c1; + min-height: 20px; + border-radius: 6px; + margin: 2px; +} +QScrollBar::handle:vertical:hover { + background-color: #a8a8a8; +} +QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { + border: none; + background: none; + height: 0px; +} + +QScrollBar:horizontal { + border: none; + background-color: #f3f3f3; + height: 12px; + margin: 0px 0px 0px 0px; +} +QScrollBar::handle:horizontal { + background-color: #c1c1c1; + min-width: 20px; + border-radius: 6px; + margin: 2px; +} +QScrollBar::handle:horizontal:hover { + background-color: #a8a8a8; +} +QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { + border: none; + background: none; + width: 0px; +} + +/* CheckBox and RadioButton - intentionally leaving indicators native */ +QCheckBox, QRadioButton { + spacing: 5px; +} + +/* GroupBox */ +QGroupBox { + border: 1px solid #cccccc; + border-radius: 4px; + margin-top: 10px; +} +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + padding: 0 3px; + left: 10px; + color: #0078D4; +} + +/* TabWidget */ +QTabWidget::pane { + border: 1px solid #cccccc; + background-color: #ffffff; +} +QTabBar::tab { + background-color: #e5e5e5; + border: 1px solid #cccccc; + border-bottom: none; + padding: 6px 15px; + margin-right: 2px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +QTabBar::tab:selected { + background-color: #ffffff; + border: 1px solid #cccccc; + border-bottom: 1px solid #ffffff; +} +QTabBar::tab:hover:!selected { + background-color: #dcdcdc; +} + +/* MenuBar */ +QMenuBar { + background-color: #f3f3f3; +} +QMenuBar::item { + padding: 4px 10px; +} +QMenuBar::item:selected { + background-color: #e5e5e5; +} +QMenu { + background-color: #ffffff; + border: 1px solid #cccccc; +} +QMenu::item { + padding: 6px 20px 6px 20px; +} +QMenu::item:selected { + background-color: #0078D4; + color: #ffffff; +} + +/* Status Bar */ +QStatusBar { + background-color: #f3f3f3; + border-top: 1px solid #cccccc; +} +QStatusBar::item { + border: none; +} diff --git a/main.py b/main.py index c7f54d0..453ed82 100644 --- a/main.py +++ b/main.py @@ -222,7 +222,6 @@ def show_main_window(): f"PyMASL ver. {system.software_version}. Пользователь: {user_full_name}. БД: {system.database}" ) window.main_button_all_sales() - window.exec_() @@ -429,7 +428,7 @@ def edit_client_in_sale(self) -> None: # Сохраняем параметры данных об уже существующем клиенте system.client_update = 1 logger.info(f"Обновляем инф. клиента {system.client_id}") - client.exec_() + client.exec() def adding_new_client_to_sale(self) -> None: """ @@ -2344,7 +2343,7 @@ def open_pay_form(self, txt): # Передаем текст в форму PayForm pay.setText(txt) - res: int = pay.exec_() + res: int = pay.exec() # если пользователь нажал крестик или кнопку Escape, # то по-умолчанию возвращается QDialog.Rejected if res == QDialog.Rejected: @@ -2523,7 +2522,7 @@ def get_slip(self) -> None: slip.ui.lineEdit.setText(rrn_value) slip.ui.textEdit.setText(load_slip) slip.show() - slip.exec_() + slip.exec() class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): @@ -2835,7 +2834,7 @@ def main_edit_client(self) -> None: # Сохраняем параметры данных об уже существующем клиенте system.client_update = 1 logger.info(f"Обновляем информацию о клиенте") - client.exec_() + client.exec() def main_filter_clear(self) -> None: """ @@ -3130,7 +3129,7 @@ def main_search_selected_sale(self) -> None: system.sale_id = int(sale_number) system.sale_tickets = client_in_sale logger.debug(f"Билеты сохраненной продажи: {system.sale_tickets}") - sale.exec_() + sale.exec() @logger_wraps(entry=True, exit=True, level="DEBUG") def main_button_all_sales(self) -> None: @@ -3316,7 +3315,7 @@ def main_open_sale(self) -> None: system.sale_id = None system.sale_status = 0 # Т.е. новая продажа system.sale_tickets = None - sale.exec_() + sale.exec() def main_get_statistic(self) -> None: """ @@ -3556,6 +3555,15 @@ class Payment: if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) app.setStyle("Fusion") + + # Load and apply QSS style + style_path = Path(__file__).parent / "files" / "style.qss" + try: + with open(style_path, "r", encoding="utf-8") as f: + app.setStyleSheet(f.read()) + except Exception as e: + logger.error(f"Failed to load style sheet from {style_path}: {e}") + auth = AuthForm() auth.show() auth.ui.label_9.setText(system.database)