鱼C论坛

 找回密码
 立即注册
查看: 86|回复: 2

[已解决]帮我看看UI部分要怎么修改,感觉好丑

[复制链接]
发表于 3 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
import sys
import re
import time
import serial
import logging
from functools import partial
from PyQt5.QtWidgets import (
    QApplication, QWidget, QCheckBox, QPushButton, QLabel,
    QGridLayout, QLineEdit, QTextEdit, QVBoxLayout, QGroupBox,
    QHBoxLayout, QComboBox, QFormLayout, QSpacerItem, QSizePolicy
)
from PyQt5.QtGui import QFont
from PyQt5.QtCore import QTimer, pyqtSignal, Qt, QThread, QMetaObject, Qt
from datetime import datetime
import serial.tools.list_ports
import unittest

# 配置日志系统
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[
        logging.StreamHandler(sys.stdout),
        logging.FileHandler("auto_test_app.log", encoding='utf-8')
    ]
)

logger = logging.getLogger(__name__)


class PowerMeterThread(QThread):
    data_ready = pyqtSignal(dict)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.parent = parent
        self.running = True

    def run(self):
        while self.running:
            if not self.parent.port_states['POWER_METER']['open']:
                self.msleep(1000)
                continue

            commands = {
                'Urms': b':NUMeric:NORMal:VALue? 1\r\n',
                'Irms': b':NUMeric:NORMal:VALue? 6\r\n',
                'P': b':NUMeric:NORMal:VALue? 11\r\n'
            }

            result = {}
            try:
                for key, cmd in commands.items():
                    self.parent._clear_serial_buffer('POWER_METER')
                    self.parent.serial_ports['POWER_METER'].write(cmd)
                    time.sleep(0.1)
                    response = self.parent.serial_ports['POWER_METER'].readline()
                    self.parent._process_power_meter_response(key, response)
                    result[key] = self.parent.power_meter_data[key]

                self.data_ready.emit(result)

            except serial.SerialException as e:
                logger.error(f"Power meter error: {str(e)}")
            self.msleep(self.parent.POWER_METER_QUERY_INTERVAL)

    def stop(self):
        self.running = False
        self.wait()

class PowerTesterLogic:
    def _format_measurement(self, value, unit):
        return self.logic.format_measurement(value, unit)
   
    def _send_voltage_command(self, value, unit):
        if unit == 'mV':
            value = value / 1000.0
        # 示例发送命令到 LMCI
        # self.serial_ports['LMCI'].write(f"VOLT {value}\n".encode())
        # 示例发送命令到 LMCI
        print(f"Sent voltage command: V = {value} V")


class AutoTestApp(QWidget):
    serial_port_opened = pyqtSignal(str, bool)
    POWER_METER_QUERY_INTERVAL = 1000  # 毫秒
    SERIAL_REFRESH_INTERVAL = 2000     # 毫秒

    def __init__(self):
        super().__init__()
        self.logic = PowerTesterLogic()
        self._init_serial_ports()
        self._init_ui_state()
        self._setup_serial_parameters()
        self.initUI()
        self._setup_timers()
        self._connect_signals()

        # 日志控制变量
        self.last_power_error_time = 0
        self.power_error_count = 0

        # 初始化线程
        self.power_meter_thread = PowerMeterThread(self)
        self.power_meter_thread.data_ready.connect(self._update_power_meter_display_from_thread)

        # 启动线程
        self.power_meter_thread.start()

    def _init_serial_ports(self):
        """初始化串口相关配置"""
        self.serial_ports = {
            'LMCI': serial.Serial(baudrate=115200, timeout=1),
            'LOAD': serial.Serial(baudrate=9600, timeout=1),
            'POWER_METER': serial.Serial(baudrate=9600, timeout=1)
        }
        self.port_states = {
            typ: {'open': False, 'port': None}
            for typ in ['LMCI', 'LOAD', 'POWER_METER']
        }

    def _init_ui_state(self):
        """初始化UI状态"""
        self.load_active = False
        self.power_meter_data = {
            'Urms': None,
            'Irms': None,
            'P': None
        }
        self.custom_voltage = {'value': None, 'unit': 'V'}
        self.custom_load = {'value': None}

    def _setup_serial_parameters(self):
        """配置串口参数"""
        for port in self.serial_ports.values():
            port.bytesize = serial.EIGHTBITS
            port.parity = serial.PARITY_NONE
            port.stopbits = serial.STOPBITS_ONE
            port.rts = False

    def initUI(self):
        """初始化用户界面"""
        self.setWindowTitle('Auto Test System - Modern UI')

        screen = QApplication.primaryScreen().availableGeometry()
        width = int(screen.width() * 0.8)
        height = int(screen.height() * 0.7)
        self.resize(width, height)

        self.setStyleSheet("background-color: #f4f4f4;")

        main_layout = QVBoxLayout()
        main_layout.setSpacing(20)
        main_layout.setContentsMargins(30, 20, 30, 20)

        main_layout.addWidget(self._create_voltage_group())
        main_layout.addWidget(self._create_load_group())
        main_layout.addLayout(self._create_feedback_section())
        main_layout.addLayout(self._create_control_section())
        main_layout.addWidget(self._create_status_bar())

        self.setLayout(main_layout)

    def _create_voltage_group(self):
        group = QGroupBox("Voltage Settings")
        layout = QFormLayout()

        voltage_row = QHBoxLayout()
        self.standard_voltage_buttons = [QCheckBox(f"{v} V") for v in [120, 220, 277, 347]]
        for btn in self.standard_voltage_buttons:
            voltage_row.addWidget(btn)
        voltage_row.addStretch()

        custom_voltage_row = QHBoxLayout()
        self.custom_voltage_input = QLineEdit()
        self.voltage_unit_combo = QComboBox()
        self.voltage_unit_combo.addItems(["mV", "V"])
        send_voltage_btn = QPushButton("Send Voltage")
        send_voltage_btn.setStyleSheet(self.get_button_style("#2196F3"))

        custom_voltage_row.addWidget(self.custom_voltage_input)
        custom_voltage_row.addWidget(self.voltage_unit_combo)
        custom_voltage_row.addWidget(send_voltage_btn)

        layout.addRow("Standard Voltage:", voltage_row)
        layout.addRow("Custom Voltage:", custom_voltage_row)

        group.setLayout(layout)
        return group

    def _create_load_group(self):
        group = QGroupBox("Load Settings")
        layout = QFormLayout()

        load_row = QHBoxLayout()
        self.standard_load_buttons = [QCheckBox(f"{i} A") for i in range(1, 9)]
        for btn in self.standard_load_buttons:
            load_row.addWidget(btn)
        load_row.addStretch()

        select_all_btn = QPushButton("Select All")
        clear_all_btn = QPushButton("Clear All")
        select_all_btn.setStyleSheet(self.get_button_style("#4CAF50"))
        clear_all_btn.setStyleSheet(self.get_button_style("#f44336"))
        btn_row = QHBoxLayout()
        btn_row.addWidget(select_all_btn)
        btn_row.addWidget(clear_all_btn)

        custom_load_row = QHBoxLayout()
        self.custom_load_input = QLineEdit()
        send_load_btn = QPushButton("Send Load")
        send_load_btn.setStyleSheet(self.get_button_style("#FF9800"))
        custom_load_row.addWidget(self.custom_load_input)
        custom_load_row.addWidget(send_load_btn)

        layout.addRow("Standard Load:", load_row)
        layout.addRow("", btn_row)
        layout.addRow("Custom Load:", custom_load_row)

        group.setLayout(layout)

        select_all_btn.clicked.connect(self._select_all_loads)
        clear_all_btn.clicked.connect(self._clear_all_loads)

        return group

    def get_button_style(self, color):
        return f"""
            QPushButton {{
                background-color: {color};
                color: white;
                padding: 6px 12px;
                border: none;
                border-radius: 4px;
                font-weight: bold;
            }}
            QPushButton:hover {{
                background-color: {self.darken_color(color)};
            }}
            QPushButton:pressed {{
                background-color: {self.lighten_color(color)};
            }}
        """

    def darken_color(self, hex_color):
        r, g, b = int(hex_color[1:3], 16), int(hex_color[3:5], 16), int(hex_color[5:7], 16)
        r, g, b = max(r - 30, 0), max(g - 30, 0), max(b - 30, 0)
        return f"#{r:02X}{g:02X}{b:02X}"

    def lighten_color(self, hex_color):
        r, g, b = int(hex_color[1:3], 16), int(hex_color[3:5], 16), int(hex_color[5:7], 16)
        r, g, b = min(r + 30, 255), min(g + 30, 255), min(b + 30, 255)
        return f"#{r:02X}{g:02X}{b:02X}"

    def _create_feedback_section(self):
        layout = QHBoxLayout()

        self.system_msg_box = QTextEdit()
        self.system_msg_box.setReadOnly(True)
        self.system_msg_box.setPlaceholderText("System messages...")

        self.power_meter_box = QTextEdit()
        self.power_meter_box.setReadOnly(True)
        self.power_meter_box.setPlaceholderText("Power meter data...")

        layout.addWidget(self.system_msg_box, stretch=1)
        layout.addWidget(self.power_meter_box, stretch=1)

        return layout

    def _create_control_section(self):
        layout = QHBoxLayout()
        layout.setSpacing(10)

        serial_ctrl_layout = self._create_serial_controls()
        layout.addLayout(serial_ctrl_layout)

        load_ctrl_layout = self._create_load_control_buttons()
        layout.addLayout(load_ctrl_layout)

        layout.addStretch()

        return layout

    def _create_serial_controls(self):
        layout = QHBoxLayout()
        self.serial_combos = {typ: QComboBox() for typ in ['LMCI', 'LOAD', 'POWER_METER']}
        self._populate_serial_combos()

        for typ in ['LMCI', 'LOAD', 'POWER_METER']:
            layout.addWidget(QLabel(f"{typ}:"))
            layout.addWidget(self.serial_combos[typ])
        return layout

    def _create_load_control_buttons(self):
        layout = QHBoxLayout()
        self.load_on_btn = QPushButton("Load ON")
        self.load_off_btn = QPushButton("Load OFF")
        self.load_on_btn.setStyleSheet(self.get_button_style("#4CAF50"))
        self.load_off_btn.setStyleSheet(self.get_button_style("#f44336"))
        layout.addWidget(self.load_on_btn)
        layout.addWidget(self.load_off_btn)
        return layout

    def _create_status_bar(self):
        self.status_label = QLabel()
        self.update_datetime_label()
        return self.status_label

    def _populate_serial_combos(self):
        ports = [port.device for port in serial.tools.list_ports.comports()]
        for typ, combo in self.serial_combos.items():
            combo.clear()
            combo.addItems(ports)
            if self.port_states[typ]['open']:
                combo.setCurrentText(self.port_states[typ]['port'])

    def _setup_timers(self):
        self.datetime_timer = QTimer(self)
        self.datetime_timer.timeout.connect(self.update_datetime_label)
        self.datetime_timer.start(1000)

        self.serial_refresh_timer = QTimer(self)
        self.serial_refresh_timer.timeout.connect(self.refresh_serial_ports)
        self.serial_refresh_timer.start(self.SERIAL_REFRESH_INTERVAL)

    def _connect_signals(self):
        for btn in self.standard_voltage_buttons:
            btn.toggled.connect(self._on_voltage_selection_changed)
        self.custom_voltage_input.textChanged.connect(self._on_custom_voltage_changed)

        for btn in self.standard_load_buttons:
            btn.toggled.connect(self._on_load_selection_changed)
        self.custom_load_input.textChanged.connect(self._on_custom_load_changed)

        for typ, combo in self.serial_combos.items():
            combo.currentTextChanged.connect(partial(self._handle_serial_selection, port_type=typ))

        self.load_on_btn.clicked.connect(self._activate_load)
        self.load_off_btn.clicked.connect(self._deactivate_load)

    def _handle_serial_selection(self, port_name, port_type):
        current_port = self.port_states[port_type]['port']
        if port_name and port_name != current_port:
            self._close_serial_port(port_type)
            self._open_serial_port(port_name, port_type)

    def _open_serial_port(self, port_name, port_type):
        try:
            port = self.serial_ports[port_type]
            port.port = port_name
            port.open()
            time.sleep(0.5)

            if port.is_open:
                self.port_states[port_type].update({'open': True, 'port': port_name})
                logger.info(f"{port_type} connected: {port_name}")
                self.serial_port_opened.emit(port_type, True)
            else:
                logger.warning(f"Failed to open {port_type} port")
        except Exception as e:
            logger.error(f"{port_type} connection error: {str(e)}")

    def _close_serial_port(self, port_type):
        if self.port_states[port_type]['open']:
            try:
                self.serial_ports[port_type].close()
                self.port_states[port_type].update({'open': False, 'port': None})
                logger.info(f"{port_type} port closed")
            except Exception as e:
                logger.error(f"Error closing {port_type} port: {str(e)}")

    def refresh_serial_ports(self):
        ports = [port.device for port in serial.tools.list_ports.comports()]
        for typ, combo in self.serial_combos.items():
            current = combo.currentText()
            combo.blockSignals(True)
            combo.clear()
            combo.addItems(ports)
            if self.port_states[typ]['open']:
                combo.setCurrentText(self.port_states[typ]['port'])
            else:
                combo.setCurrentIndex(-1)
            combo.blockSignals(False)

    def _update_power_meter_display_from_thread(self, data):
        self.power_meter_data.update(data)
        self._update_power_meter_display()

    def _process_power_meter_response(self, key, response):
        try:
            decoded = response.decode().strip()
            value = float(re.search(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?", decoded).group())
            self.power_meter_data[key] = value
        except (UnicodeDecodeError, AttributeError, ValueError) as e:
            logger.warning(f"Invalid {key} data: {str(e)}")
            self.power_meter_data[key] = None

    def _clear_serial_buffer(self, port_type):
        port = self.serial_ports[port_type]
        while port.in_waiting > 0:
            port.read(port.in_waiting)

    def _update_power_meter_display(self):
        text = (
            "Power Meter:\n"
            f"Urms: {self._format_measurement(self.power_meter_data['Urms'], 'V')}\n"
            f"Irms: {self._format_measurement(self.power_meter_data['Irms'], 'A')}\n"
            f"Power: {self._format_measurement(self.power_meter_data['P'], 'W')}"
        )
        self.power_meter_box.setText(text)

    def update_datetime_label(self):
        self.status_label.setText(f"Last update: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

    def _on_voltage_selection_changed(self, checked):
        sender = self.sender()
        if checked:
            for btn in self.standard_voltage_buttons:
                if btn != sender:
                    btn.setChecked(False)
            self.custom_voltage_input.clear()
        self.custom_voltage_input.setEnabled(not any(
            btn.isChecked() for btn in self.standard_voltage_buttons))

    def _on_custom_voltage_changed(self, text):
        has_input = bool(text.strip())
        for btn in self.standard_voltage_buttons:
            btn.setEnabled(not has_input)

    def _on_load_selection_changed(self, checked):
        self.custom_load_input.setEnabled(not any(
            btn.isChecked() for btn in self.standard_load_buttons))

    def _on_custom_load_changed(self, text):
        has_input = bool(text.strip())
        for btn in self.standard_load_buttons:
            btn.setEnabled(not has_input)

    def _select_all_loads(self):
        for btn in self.standard_load_buttons:
            btn.setChecked(True)
        self.custom_load_input.clear()

    def _clear_all_loads(self):
        for btn in self.standard_load_buttons:
            btn.setChecked(False)
        self.custom_load_input.clear()

    def _send_voltage(self):
        selected = [btn.text() for btn in self.standard_voltage_buttons if btn.isChecked()]
        custom = self.custom_voltage_input.text().strip()

        if custom:
            try:
                value = float(custom)
                unit = self.voltage_unit_combo.currentText()
                self._send_voltage_command(value, unit)
                logger.info(f"Voltage set: {value} {unit}")
            except ValueError:
                logger.warning("Invalid voltage value!")
        elif selected:
            voltage = selected[0].split()[0]
            self._send_voltage_command(float(voltage), 'V')
            logger.info(f"Voltage set: {selected[0]}")
        else:
            logger.warning("No voltage selected!")

    def _send_load(self):
        selected = [btn.text() for btn in self.standard_load_buttons if btn.isChecked()]
        custom = self.custom_load_input.text().strip()

        if custom:
            try:
                value = float(custom)
                self._send_load_command(value)
                logger.info(f"Load set: {value} A")
            except ValueError:
                logger.warning("Invalid load value!")
        elif selected:
            loads = [btn.text().split()[0] for btn in self.standard_load_buttons if btn.isChecked()]
            logger.info(f"Load set: {', '.join(loads)} A")
        else:
            logger.warning("No load selected!")

    def _send_load_command(self, value):
        if not self.port_states['LOAD']['open']:
            logger.warning("LOAD port not connected!")
            return

        try:
            command = f"CURR {value}\n".encode()
            self.serial_ports['LOAD'].write(command)
            logger.info(f"Sent load command: I = {value} A")

            self.serial_ports['LOAD'].write(b"CURR?\n")
            response = self.serial_ports['LOAD'].readline().decode().strip()

            if abs(float(response) - value) < 0.01:
                logger.info("Load set successfully!")
                self.load_active = True
                self._update_load_buttons()
            else:
                logger.warning("Load setting verification failed!")

        except serial.SerialException as e:
            logger.error(f"Load communication error: {str(e)}")
        except ValueError:
            logger.warning("Invalid load response format!")

    def _activate_load(self):
        if self.port_states['LOAD']['open']:
            try:
                self.serial_ports['LOAD'].write(b"LOAD:ON\n")
                self.load_active = True
                self._update_load_buttons()
                logger.info("Load activated")
            except serial.SerialException as e:
                logger.error(f"Load activation failed: {str(e)}")
        else:
            logger.warning("LOAD port not connected!")

    def _deactivate_load(self):
        if self.port_states['LOAD']['open']:
            try:
                self.serial_ports['LOAD'].write(b"LOAD:OFF\n")
                self.load_active = False
                self._update_load_buttons()
                logger.info("Load deactivated")
            except serial.SerialException as e:
                logger.error(f"Load deactivation failed: {str(e)}")
        else:
            logger.warning("LOAD port not connected!")

    def _update_load_buttons(self):
        self.load_on_btn.setEnabled(not self.load_active)
        self.load_off_btn.setEnabled(self.load_active)

    def closeEvent(self, event):
        self.datetime_timer.stop()
        self.serial_refresh_timer.stop()
        self.power_meter_thread.stop()

        for port_type in ['LMCI', 'LOAD', 'POWER_METER']:
            self._close_serial_port(port_type)

        event.accept()



# ====================
# 单元测试部分
# ====================

class TestAutoTestApp(unittest.TestCase):
    def setUp(self):
        self.logic = PowerTesterLogic()
    def test_format_measurement(self):
        self.assertEqual(app._format_measurement(220.345, 'V'), "220.345 V")
        self.assertEqual(app._format_measurement(None, 'A'), "N/A")

class TestPowerTesterLogic(unittest.TestCase):
    def setUp(self):
        self.logic = PowerTesterLogic()

    def test_format_measurement(self):
        self.assertEqual(self.logic.format_measurement(220.345, 'V'), "220.345 V")
        self.assertEqual(self.logic.format_measurement(None, 'A'), "N/A")


if __name__ == '__main__':
    import sys
    unittest.main(exit=False)
    app = QApplication(sys.argv)
    ex = AutoTestApp()
    ex.show()
    sys.exit(app.exec_())
最佳答案
3 天前
使用ttkbootstrap
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 3 天前 | 显示全部楼层
针对UI美化问题,我建议进行以下优化(主要修改布局、颜色和控件样式):

主要修改点:
1. 使用网格布局替代表单布局,提高控件对齐精度
2. 统一按钮样式并优化悬停效果
3. 增加分组框标题样式
4. 优化文本显示区域样式
5. 添加状态指示灯
6. 调整整体配色方案


  1. def initUI(self):
  2.     self.setWindowTitle('Auto Test System')
  3.     self.setStyleSheet("""
  4.         QWidget {
  5.             font-family: 'Segoe UI', Arial;
  6.             font-size: 10pt;
  7.         }
  8.         QGroupBox {
  9.             font-weight: bold;
  10.             border: 1px solid #ccc;
  11.             border-radius: 5px;
  12.             margin-top: 1ex;
  13.             padding-top: 12px;
  14.         }
  15.         QGroupBox::title {
  16.             subcontrol-origin: margin;
  17.             subcontrol-position: top center;
  18.             padding: 0 5px;
  19.         }
  20.         QTextEdit, QLineEdit {
  21.             background-color: white;
  22.             border: 1px solid #ddd;
  23.             border-radius: 3px;
  24.             padding: 5px;
  25.         }
  26.         QPushButton {
  27.             min-height: 28px;
  28.             padding: 5px 12px;
  29.             border-radius: 4px;
  30.         }
  31.     """)

  32.     # 创建主布局
  33.     main_layout = QVBoxLayout()
  34.     main_layout.setSpacing(15)
  35.     main_layout.setContentsMargins(20, 15, 20, 15)

  36.     # 顶部控制区
  37.     top_layout = QHBoxLayout()
  38.     top_layout.addWidget(self._create_voltage_group(), 1)
  39.     top_layout.addWidget(self._create_load_group(), 1)

  40.     # 中间显示区
  41.     mid_layout = QHBoxLayout()
  42.     mid_layout.addWidget(self._create_feedback_group("System Messages", self.system_msg_box), 1)
  43.     mid_layout.addWidget(self._create_feedback_group("Power Meter", self.power_meter_box), 1)

  44.     # 底部控制区
  45.     bottom_layout = QHBoxLayout()
  46.     bottom_layout.addLayout(self._create_serial_controls())
  47.     bottom_layout.addLayout(self._create_load_control_buttons())
  48.     bottom_layout.addStretch()

  49.     # 组装主界面
  50.     main_layout.addLayout(top_layout)
  51.     main_layout.addLayout(mid_layout)
  52.     main_layout.addLayout(bottom_layout)
  53.     main_layout.addWidget(self._create_status_bar())

  54.     self.setLayout(main_layout)

  55. def _create_feedback_group(self, title, widget):
  56.     group = QGroupBox(title)
  57.     layout = QVBoxLayout()
  58.     widget.setMinimumHeight(150)
  59.     widget.setStyleSheet("font-family: 'Consolas', 'Courier New';")
  60.     layout.addWidget(widget)
  61.     group.setLayout(layout)
  62.     return group

  63. def _create_serial_controls(self):
  64.     layout = QGridLayout()
  65.     layout.setHorizontalSpacing(10)
  66.     layout.setVerticalSpacing(5)
  67.    
  68.     row = 0
  69.     for i, typ in enumerate(['LMCI', 'LOAD', 'POWER_METER']):
  70.         layout.addWidget(QLabel(f"{typ} Port:"), row, 0)
  71.         layout.addWidget(self.serial_combos[typ], row, 1)
  72.         
  73.         # 添加状态指示灯
  74.         status_light = QLabel()
  75.         status_light.setFixedSize(16, 16)
  76.         status_light.setStyleSheet("background-color: #ccc; border-radius: 8px;")
  77.         self.status_lights[typ] = status_light
  78.         layout.addWidget(status_light, row, 2)
  79.         row += 1
  80.         
  81.     return layout

  82. def get_button_style(self, color):
  83.     return f"""
  84.         QPushButton {{
  85.             background-color: {color};
  86.             color: white;
  87.             border: none;
  88.         }}
  89.         QPushButton:hover {{
  90.             background-color: #2E7D32;
  91.         }}
  92.         QPushButton:disabled {{
  93.             background-color: #BDBDBD;
  94.         }}
  95.     """
复制代码


关键优化说明:
1. 使用CSS样式统一控件外观:
   - 分组框添加圆角和标题居中
   - 按钮统一高度和圆角
   - 文本区域使用等宽字体

2. 布局优化:
   - 电压/负载设置并排显示
   - 消息框使用独立分组框
   - 串口控制使用网格布局精确对齐

3. 状态可视化:
   - 添加圆形状态指示灯(需在类中初始化 self.status_lights = {}
   - 在串口状态变化时更新指示灯颜色:
   

  1.      def _update_status_light(self, port_type, connected):
  2.          color = "#4CAF50" if connected else "#f44336"
  3.          self.status_lights[port_type].setStyleSheet(
  4.              f"background-color: {color}; border-radius: 8px;")
  5.      
复制代码


4. 配色方案:
   - 主色调:科技蓝 (#2196F3)
   - 成功状态:绿色 (#4CAF50)
   - 错误状态:红色 (#f44336)
   - 禁用状态:灰色 (#BDBDBD)

建议在代码中添加以下初始化:

  1. # 在 __init__ 中添加
  2. self.status_lights = {}  # 串口状态指示灯

  3. # 在 _open_serial_port 成功时调用
  4. self._update_status_light(port_type, True)

  5. # 在 _close_serial_port 时调用
  6. self._update_status_light(port_type, False)
复制代码


这些修改将使界面更加现代化,同时保持功能完整性。重点优化了视觉层次和操作反馈,使状态信息更直观可见。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 3 天前 | 显示全部楼层    本楼为最佳答案   
使用ttkbootstrap
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-26 16:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表