btn_green_selector.xml

本文探讨了在Android应用中如何根据不同的状态(启用、按压、选择)来改变图标显示样式,实现灰度和按压状态的图标变化效果。




<?xml version="1.0" encoding="utf-8" ?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_enabled="false" android:drawable="@drawable/bg_icon_gray" /> 
  <item android:state_pressed="true" android:drawable="@drawable/bg_icon_press" /> 
  <item android:state_selected="false" android:drawable="@drawable/bg_icon_n" /> 
  <item android:state_selected="true" android:drawable="@drawable/bg_icon_press" /> 
  </selector>


import sys from PyQt6.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QCheckBox, QRadioButton, QSlider, QProgressBar, QLineEdit, QComboBox, QTabWidget, QGroupBox, QListWidget, QListWidgetItem, QTableWidget, QTableWidgetItem, QFormLayout ) from PyQt6.QtCore import Qt, QSize from PyQt6.QtGui import QIcon from qt_material import apply_stylesheet, list_themes class MaterialDesignDemo(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("PyQt6 Material Design 组件展示") self.setGeometry(300, 300, 800, 600) # 主窗口部件 central_widget = QWidget() self.setCentralWidget(central_widget) # 主布局 main_layout = QVBoxLayout(central_widget) # 主题选择部分 theme_layout = QHBoxLayout() self.theme_label = QLabel("选择主题:") theme_layout.addWidget(self.theme_label) self.theme_combo = QComboBox() self.theme_combo.addItems(list_themes()) # 添加所有可用主题 self.theme_combo.currentTextChanged.connect(self.change_theme) theme_layout.addWidget(self.theme_combo) # 添加暗黑模式切换 self.dark_mode_check = QCheckBox("暗黑模式") self.dark_mode_check.stateChanged.connect(self.toggle_dark_mode) theme_layout.addWidget(self.dark_mode_check) main_layout.addLayout(theme_layout) # 选项卡组件 self.tab_widget = QTabWidget() main_layout.addWidget(self.tab_widget) # 创建各个选项卡 self.create_basic_components_tab() self.create_form_components_tab() self.create_list_table_tab() self.create_advanced_tab() # 应用默认主题 self.change_theme("dark_amber") # 状态栏 self.statusBar().showMessage("当前主题: dark_amber | 暗黑模式: 开启") def create_basic_components_tab(self): """创建基础组件选项卡""" tab = QWidget() layout = QVBoxLayout(tab) # 按钮组 btn_group = QGroupBox("按钮") btn_layout = QHBoxLayout(btn_group) btn1 = QPushButton("主要按钮") btn1.setIcon(QIcon(":material/check")) btn_layout.addWidget(btn1) btn2 = QPushButton("次要按钮") btn2.setIcon(QIcon(":material/cancel")) btn_layout.addWidget(btn2) btn3 = QPushButton("禁用按钮") btn3.setEnabled(False) btn_layout.addWidget(btn3) layout.addWidget(btn_group) # 选择组件组 select_group = QGroupBox("选择组件") select_layout = QVBoxLayout(select_group) # 复选框 check_layout = QHBoxLayout() check_layout.addWidget(QLabel("复选框:")) for i in range(3): checkbox = QCheckBox(f"选项 {i + 1}") check_layout.addWidget(checkbox) select_layout.addLayout(check_layout) # 单选框 radio_layout = QHBoxLayout() radio_layout.addWidget(QLabel("单选框:")) for i in range(3): radio = QRadioButton(f"选项 {i + 1}") radio_layout.addWidget(radio) select_layout.addLayout(radio_layout) # 开关 switch_layout = QHBoxLayout() switch_layout.addWidget(QLabel("开关:")) for i in range(3): switch = QCheckBox() switch.setStyleSheet("QCheckBox::indicator { width: 40px; height: 20px; }") switch_layout.addWidget(switch) switch_layout.addWidget(QLabel(f"开关 {i + 1}")) select_layout.addLayout(switch_layout) layout.addWidget(select_group) # 进度组件组 progress_group = QGroupBox("进度组件") progress_layout = QVBoxLayout(progress_group) # 滑块 slider_layout = QHBoxLayout() slider_layout.addWidget(QLabel("滑块:")) slider = QSlider(Qt.Orientation.Horizontal) slider.setRange(0, 100) slider.setValue(50) slider_layout.addWidget(slider) progress_layout.addLayout(slider_layout) # 进度条 progressbar_layout = QHBoxLayout() progressbar_layout.addWidget(QLabel("进度条:")) progressbar = QProgressBar() progressbar.setRange(0, 100) progressbar.setValue(75) progressbar_layout.addWidget(progressbar) progress_layout.addLayout(progressbar_layout) layout.addWidget(progress_group) self.tab_widget.addTab(tab, "基础组件") def create_form_components_tab(self): """创建表单组件选项卡""" tab = QWidget() layout = QVBoxLayout(tab) # 输入框组 input_group = QGroupBox("输入框") input_layout = QFormLayout(input_group) # 文本输入 input_layout.addRow("文本输入:", QLineEdit("示例文本")) # 密码输入 password = QLineEdit() password.setEchoMode(QLineEdit.EchoMode.Password) password.setText("password123") input_layout.addRow("密码输入:", password) # 多行文本 text_edit = QLineEdit("多行文本示例...") text_edit.setMinimumHeight(80) input_layout.addRow("多行文本:", text_edit) layout.addWidget(input_group) # 选择器组 selector_group = QGroupBox("选择器") selector_layout = QVBoxLayout(selector_group) # 下拉选择框 combo_layout = QHBoxLayout() combo_layout.addWidget(QLabel("下拉选择:")) combo = QComboBox() combo.addItems(["选项 1", "选项 2", "选项 3"]) combo_layout.addWidget(combo) selector_layout.addLayout(combo_layout) # 日期选择器 date_layout = QHBoxLayout() date_layout.addWidget(QLabel("日期选择:")) date_edit = QLineEdit("2023-06-15") date_edit.setReadOnly(True) date_layout.addWidget(date_edit) selector_layout.addLayout(date_layout) # 时间选择器 time_layout = QHBoxLayout() time_layout.addWidget(QLabel("时间选择:")) time_edit = QLineEdit("14:30") time_edit.setReadOnly(True) time_layout.addWidget(time_edit) selector_layout.addLayout(time_layout) layout.addWidget(selector_group) self.tab_widget.addTab(tab, "表单组件") def create_list_table_tab(self): """创建列表和表格选项卡""" tab = QWidget() layout = QVBoxLayout(tab) # 列表组件 list_group = QGroupBox("列表组件") list_layout = QHBoxLayout(list_group) # 简单列表 simple_list = QListWidget() for i in range(1, 6): item = QListWidgetItem(f"列表项 {i}") simple_list.addItem(item) list_layout.addWidget(simple_list) # 带图标的列表 icon_list = QListWidget() icons = [":material/email", ":material/favorite", ":material/star", ":material/settings"] for i, icon in enumerate(icons): item = QListWidgetItem(QIcon(icon), f"带图标项 {i + 1}") icon_list.addItem(item) list_layout.addWidget(icon_list) layout.addWidget(list_group) # 表格组件 table_group = QGroupBox("表格组件") table_layout = QVBoxLayout(table_group) table = QTableWidget(5, 4) table.setHorizontalHeaderLabels(["ID", "名称", "状态", "操作"]) for row in range(5): for col in range(4): if col == 0: table.setItem(row, col, QTableWidgetItem(f"{row + 1}")) elif col == 1: table.setItem(row, col, QTableWidgetItem(f"项目 {row + 1}")) elif col == 2: status = QTableWidgetItem("激活" if row % 2 == 0 else "禁用") status.setForeground(Qt.GlobalColor.green if row % 2 == 0 else Qt.GlobalColor.red) table.setItem(row, col, status) else: btn = QPushButton("操作") btn.setFixedSize(80, 30) table.setCellWidget(row, col, btn) table.resizeColumnsToContents() table_layout.addWidget(table) layout.addWidget(table_group) self.tab_widget.addTab(tab, "列表与表格") def create_advanced_tab(self): """创建高级组件选项卡""" tab = QWidget() layout = QVBoxLayout(tab) # 卡片组件 card_group = QGroupBox("卡片组件") card_layout = QHBoxLayout(card_group) # 卡片 1 card1 = QGroupBox() card1.setStyleSheet("border: 1px solid #ddd; border-radius: 8px; padding: 15px;") card1_layout = QVBoxLayout(card1) card1_layout.addWidget(QLabel("卡片标题")) card1_layout.addWidget(QLabel("卡片内容描述文本...")) card1_layout.addWidget(QPushButton("操作按钮")) card_layout.addWidget(card1) # 卡片 2 card2 = QGroupBox() card2.setStyleSheet("border: 1px solid #ddd; border-radius: 8px; padding: 15px;") card2_layout = QVBoxLayout(card2) card2_layout.addWidget(QLabel("带图标的卡片")) card2_layout.addWidget(QPushButton(QIcon(":material/favorite"), "喜欢")) card_layout.addWidget(card2) layout.addWidget(card_group) # 消息组件 message_group = QGroupBox("消息组件") message_layout = QVBoxLayout(message_group) # 不同类型的消息 message_types = [ ("信息消息", ":material/info", "#2196F3"), ("成功消息", ":material/check_circle", "#4CAF50"), ("警告消息", ":material/warning", "#FFC107"), ("错误消息", ":material/error", "#F44336") ] for text, icon, color in message_types: msg_layout = QHBoxLayout() icon_label = QLabel() icon_label.setPixmap(QIcon(icon).pixmap(24, 24)) msg_layout.addWidget(icon_label) text_label = QLabel(text) text_label.setStyleSheet(f"color: {color}; font-weight: bold;") msg_layout.addWidget(text_label) message_layout.addLayout(msg_layout) layout.addWidget(message_group) self.tab_widget.addTab(tab, "高级组件") def change_theme(self, theme_name): """切换主题""" dark_mode = self.dark_mode_check.isChecked() apply_stylesheet(app, theme=theme_name, invert_secondary=dark_mode) # 更新状态栏 self.statusBar().showMessage(f"当前主题: {theme_name} | 暗黑模式: {'开启' if dark_mode else '关闭'}") def toggle_dark_mode(self): """切换暗黑模式""" current_theme = self.theme_combo.currentText() self.change_theme(current_theme) if __name__ == "__main__": app = QApplication(sys.argv) # 列出所有可用主题 print("可用主题:") for theme in list_themes(): print(f" - {theme}") window = MaterialDesignDemo() window.show() sys.exit(app.exec()) 日期选择没有弹出对应的日期
07-26
<think> 我们正在讨论LVGL中的对象和类系统。用户的问题是关于`tp_state_btn_class`结构中`.base_class`成员被初始化为`&lv_button_class`,但实际创建的对象并不是一个按钮(button)。我们需要解释这种现象的原因。 在LVGL中,每个对象都关联一个类(class),并且类之间可以形成继承关系。每个类都有一个基类(base_class),指向其父类。这样,对象就可以继承父类的特性和方法。 具体到用户的问题: - 有一个静态类`tp_state_btn_class`,其`.base_class`被设置为`&lv_button_class`,这意味着`tp_state_btn_class`是从按钮类派生出来的。 - 但是,用户观察到实际创建的对象并不是按钮(button)。这看起来矛盾,但实际上是合理的,因为继承关系并不改变对象本身的类型,而是扩展了其行为。 原因在于:在LVGL中,对象的类型是由其自己的类(即最具体的类)决定的,而不是由基类决定的。当我们创建一个对象时,我们指定它的类(例如`tp_state_btn_class`),那么该对象就是这个类的一个实例。尽管它的基类是`lv_button_class`,但它并不是一个纯粹的按钮(button),而是按钮的一个子类(或者说定制版本)。 因此,我们可以这样理解: - 按钮(button)是`lv_button_class`的实例。 - 而`tp_state_btn_class`的对象是一种特殊类型的按钮,它继承了按钮的所有特性(因为它的基类是指向按钮类的),但它还可以有自己额外的特性(比如样式、事件处理等)。 所以,初始化对象不是一个“普通”按钮,而是一个从按钮派生出来的自定义对象。它拥有按钮的所有功能,但可能被扩展或修改。 此外,在LVGL中,当我们创建对象时,我们使用`lv_obj_create`函数并指定父对象和类。例如: ```c lv_obj_t * obj = lv_obj_class_create_obj(&tp_state_btn_class, parent); ``` 这样创建的对象就是`tp_state_btn_class`类的实例,而不是`lv_button_class`的实例。但是,由于继承关系,它仍然可以调用按钮类的方法,并且具有按钮的所有属性。 总结:对象的具体类型由其自身的类决定,但通过继承,它可以拥有基类的特性。因此,虽然`.base_class`指向按钮类,但对象是`tp_state_btn_class`的实例,所以它不是一个普通的按钮,而是一个定制版本的按钮(或者说是按钮的一个子类)。 现在,我们按照要求生成相关问题: </think> 在LVGL中,`tp_state_btn_class`的`.base_class`被初始化为`&lv_button_class`,但初始化对象不是按钮的原因在于LVGL的对象继承机制和工作原理: ### 核心原因解析 1. **继承关系** `tp_state_btn_class`通过`.base_class = &lv_button_class`声明自己继承自按钮类,但这**不会自动创建按钮实例**。继承关系仅表示: - 该自定义类将继承按钮的所有属性和方法 - 创建对象时仍需显式调用构造函数 2. **对象创建流程** ```c // 创建对象时的关键步骤: lv_obj_t * obj = lv_obj_class_create_obj(&tp_state_btn_class, parent); // 1. 分配内存 lv_obj_class_init_obj(obj); // 2. 递归初始化基类 ``` - 第一步:分配对象内存(此时对象是"空壳") - 第二步:通过`.base_class`链递归初始化所有基类: * 先初始化`lv_button_class` * 再初始化`lv_obj_class`(按钮的基类) * 最后初始化`tp_state_btn_class`自身 3. **对象身份判定** - 对象的**实际类型**由创建时指定的类指针决定 - 虽然继承自按钮类,但`LV_OBJ_CLASS(tp_state_btn_class)`才决定其最终类型标识 - 按钮特有的特性(如点击效果)需在自定义类中显式实现 ### 类比说明 | 行为 | 编程类比 | LVGL对象系统 | |---------------------|--------------------------|----------------------------| | "继承按钮能力" | 子类继承父类方法 | `.base_class = &lv_button_class` | | "成为按钮对象" | 实例化父类 | 创建时需显式调用`lv_btn_create()` | | "定制按钮行为" | 重写父类方法 | 在自定义类中覆盖事件处理函数 | ### 解决方案 若需创建真实的按钮对象: ```c // 正确创建按钮对象的两种方式: // 方式1:直接使用按钮类 lv_obj_t * btn = lv_btn_create(parent); // 方式2:通过自定义类创建时需实现按钮特性 lv_obj_t * custom_btn = lv_obj_class_create_obj(&tp_state_btn_class, parent); lv_btn_add_effect(custom_btn); // 手动添加按钮特效 ``` > 关键结论:LVGL中的类继承**只定义能力继承关系**,实际对象类型由创建时指定的类决定。`.base_class`初始化确保获得基类功能,但不改变对象的基础类型标识[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值