From c541453cae04530c0333de5f8b836a2dbdea7e14 Mon Sep 17 00:00:00 2001 From: ChinaIceF <1489423523@qq.com> Date: Tue, 10 Sep 2024 16:44:50 +0800 Subject: [PATCH 1/2] feat: impl global side drawers --- .../components/page_dialog/page_dialog.py | 34 +++++ .../components/page_page_control/__init__.py | 1 + .../page_page_control/page_control.py | 68 ++++++++++ examples/Gallery for siui/ui.py | 8 +- siui/components/page/page.py | 2 +- siui/components/slider/slider.py | 2 +- siui/templates/application/application.py | 25 +++- .../components/layer/global_drawer.py | 51 ++++++++ .../layer_left_global_drawer/__init__.py | 0 .../layer_left_global_drawer.py | 117 ++++++++++++++++++ .../layer_modal_dialog/layer_modal_dialog.py | 4 +- 11 files changed, 304 insertions(+), 8 deletions(-) create mode 100644 examples/Gallery for siui/components/page_page_control/__init__.py create mode 100644 examples/Gallery for siui/components/page_page_control/page_control.py create mode 100644 siui/templates/application/components/layer/global_drawer.py create mode 100644 siui/templates/application/components/layer/layer_left_global_drawer/__init__.py create mode 100644 siui/templates/application/components/layer/layer_left_global_drawer/layer_left_global_drawer.py diff --git a/examples/Gallery for siui/components/page_dialog/page_dialog.py b/examples/Gallery for siui/components/page_dialog/page_dialog.py index 7a99c43..dc963b7 100644 --- a/examples/Gallery for siui/components/page_dialog/page_dialog.py +++ b/examples/Gallery for siui/components/page_dialog/page_dialog.py @@ -123,6 +123,40 @@ def __init__(self, *args, **kwargs): group.addWidget(self.side_messages) + # 全局侧边抽屉 + with self.titled_widgets_group as group: + group.addTitle("全局侧边抽屉") + + # 子页面 + self.global_drawer_left = OptionCardPlaneForWidgetDemos(self) + self.global_drawer_left.setSourceCodeURL("https://github.com/ChinaIceF/PyQt-SiliconUI/blob/main/siui/components" + "/widgets/progress_bar/progress_bar.py") + self.global_drawer_left.setTitle("全局左侧抽屉") + self.global_drawer_left.setFixedWidth(800) + + self.ctrl_show_global_drawer_left = SiPushButton(self) + self.ctrl_show_global_drawer_left.resize(128, 32) + self.ctrl_show_global_drawer_left.attachment().setText("打开") + self.ctrl_show_global_drawer_left.clicked.connect( + lambda: SiGlobal.siui.windows["MAIN_WINDOW"].layerLeftGlobalDrawer().showLayer() + ) + + self.ctrl_new_page = SiPushButton(self) + self.ctrl_new_page.resize(128, 32) + self.ctrl_new_page.attachment().setText("DEBUG: 新页面") + self.ctrl_new_page.clicked.connect( + lambda: SiGlobal.siui.windows["MAIN_WINDOW"].layerMain().addPage(ExampleDialogs(self), + icon=SiGlobal.siui.iconpack.get("ic_fluent_info_filled"), + hint="关于", side="top") + ) + + self.global_drawer_left.body().addWidget(self.ctrl_show_global_drawer_left) + self.global_drawer_left.body().addWidget(self.ctrl_new_page) + self.global_drawer_left.body().addPlaceholder(12) + self.global_drawer_left.adjustSize() + + group.addWidget(self.global_drawer_left) + # 二级界面 with self.titled_widgets_group as group: group.addTitle("二级界面") diff --git a/examples/Gallery for siui/components/page_page_control/__init__.py b/examples/Gallery for siui/components/page_page_control/__init__.py new file mode 100644 index 0000000..1a90804 --- /dev/null +++ b/examples/Gallery for siui/components/page_page_control/__init__.py @@ -0,0 +1 @@ +from .page_control import ExamplePageControl \ No newline at end of file diff --git a/examples/Gallery for siui/components/page_page_control/page_control.py b/examples/Gallery for siui/components/page_page_control/page_control.py new file mode 100644 index 0000000..958904d --- /dev/null +++ b/examples/Gallery for siui/components/page_page_control/page_control.py @@ -0,0 +1,68 @@ +from PyQt5.QtCore import Qt + +from siui.components import ( + SiPushButton, + SiTitledWidgetGroup, +) +from siui.components.page import SiPage +from siui.core.globals import SiGlobal + +from ..option_card import OptionCardPlaneForWidgetDemos + + +class ExamplePageControl(SiPage): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.setPadding(64) + self.setScrollMaximumWidth(950) + self.setScrollAlignment(Qt.AlignLeft) + self.setTitle("页面控制") + + # 创建控件组 + self.titled_widgets_group = SiTitledWidgetGroup(self) + self.titled_widgets_group.setSpacing(32) + self.titled_widgets_group.setAdjustWidgetsSize(False) # 禁用调整宽度 + + # 侧边栏信息 + with self.titled_widgets_group as group: + group.addTitle("页面偏移") + + # 侧边栏信息 + self.global_shifting = OptionCardPlaneForWidgetDemos(self) + self.global_shifting.setSourceCodeURL("https://github.com/ChinaIceF/PyQt-SiliconUI/blob/main/siui/components" + "/widgets/progress_bar/progress_bar.py") + self.global_shifting.setTitle("页面偏移") + self.global_shifting.setFixedWidth(800) + + self.ctrl_shift_left = SiPushButton(self) + self.ctrl_shift_left.resize(128, 32) + self.ctrl_shift_left.attachment().setText("向左偏移") + self.ctrl_shift_left.clicked.connect( + lambda: SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(-100, 0)) + + self.ctrl_shift_right = SiPushButton(self) + self.ctrl_shift_right.resize(128, 32) + self.ctrl_shift_right.attachment().setText("向右偏移") + self.ctrl_shift_right.clicked.connect( + lambda: SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(100, 0)) + + self.ctrl_shift_restore = SiPushButton(self) + self.ctrl_shift_restore.resize(128, 32) + self.ctrl_shift_restore.attachment().setText("恢复") + self.ctrl_shift_restore.clicked.connect( + lambda: SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(0, 0)) + + self.global_shifting.body().addWidget(self.ctrl_shift_left) + self.global_shifting.body().addWidget(self.ctrl_shift_right) + self.global_shifting.body().addWidget(self.ctrl_shift_restore) + self.global_shifting.body().addPlaceholder(12) + self.global_shifting.adjustSize() + + group.addWidget(self.global_shifting) + + # 添加页脚的空白以增加美观性 + self.titled_widgets_group.addPlaceholder(64) + + # 设置控件组为页面对象 + self.setAttachment(self.titled_widgets_group) diff --git a/examples/Gallery for siui/ui.py b/examples/Gallery for siui/ui.py index c409c7e..e30091a 100644 --- a/examples/Gallery for siui/ui.py +++ b/examples/Gallery for siui/ui.py @@ -1,12 +1,13 @@ import icons from components.page_about import About +from components.page_container import ExampleContainer from components.page_dialog import ExampleDialogs +from components.page_functional import ExampleFunctional from components.page_homepage import ExampleHomepage from components.page_icons import ExampleIcons from components.page_option_cards import ExampleOptionCards +from components.page_page_control import ExamplePageControl from components.page_widgets import ExampleWidgets -from components.page_container import ExampleContainer -from components.page_functional import ExampleFunctional from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QDesktopWidget @@ -51,6 +52,9 @@ def __init__(self, *args, **kwargs): self.layerMain().addPage(ExampleDialogs(self), icon=SiGlobal.siui.iconpack.get("ic_fluent_panel_separate_window_filled"), hint="消息与二级界面", side="top") + self.layerMain().addPage(ExamplePageControl(self), + icon=SiGlobal.siui.iconpack.get("ic_fluent_wrench_screwdriver_filled"), + hint="页面控制", side="top") self.layerMain().addPage(ExampleFunctional(self), icon=SiGlobal.siui.iconpack.get("ic_fluent_puzzle_piece_filled"), hint="功能组件", side="top") diff --git a/siui/components/page/page.py b/siui/components/page/page.py index 254ffb6..d11eda4 100644 --- a/siui/components/page/page.py +++ b/siui/components/page/page.py @@ -76,11 +76,11 @@ def setTitle(self, title: str): self.title = SiLabel(self) self.title.setFont(SiGlobal.siui.fonts["L_BOLD"]) self.title.setFixedHeight(32) + self.title.setContentsMargins(64, 0, 0, 0) self.title.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.title.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged) # 添加到水平容器 - self.title_container.addPlaceholder(64) self.title_container.addWidget(self.title) self.title.setText(title) diff --git a/siui/components/slider/slider.py b/siui/components/slider/slider.py index faeceb0..a8fc60e 100644 --- a/siui/components/slider/slider.py +++ b/siui/components/slider/slider.py @@ -63,7 +63,7 @@ def setValue(self, """ super().setValue(value) self.handle.setHint(str(self.value())) - self._move_handle_according_to_value(move_to=True) + self._move_handle_according_to_value(move_to=move_to) def _move_handle_according_to_value(self, move_to=False): """ diff --git a/siui/templates/application/application.py b/siui/templates/application/application.py index 5766992..f11ae20 100644 --- a/siui/templates/application/application.py +++ b/siui/templates/application/application.py @@ -2,8 +2,12 @@ from PyQt5.QtWidgets import QMainWindow from siui.components.tooltip import ToolTipWindow +from siui.components.widgets.abstracts import SiWidget from siui.core.globals import SiGlobal from siui.templates.application.components.layer.layer_child_page.layer_child_page import LayerChildPage +from siui.templates.application.components.layer.layer_left_global_drawer.layer_left_global_drawer import ( + LayerLeftGlobalDrawer, +) from siui.templates.application.components.layer.layer_main.layer_main import LayerMain from siui.templates.application.components.layer.layer_modal_dialog.layer_modal_dialog import LayerModalDialog from siui.templates.application.components.layer.layer_right_message_sidebar.layer_right_message_sidebar import ( @@ -28,12 +32,23 @@ def __init__(self, *args, **kwargs): self.resize(1200, 700) self.setWindowTitle("Silicon Application Template") + # 层的组 + self.group_main_interface = SiWidget(self) + self.groups_ = { + "MAIN_INTERFACE": self.group_main_interface + } + # 构建界面 - self.layer_main = LayerMain(self) - self.layer_child_page = LayerChildPage(self) + self.layer_main = LayerMain(self.group_main_interface) + self.layer_child_page = LayerChildPage(self.group_main_interface) + + self.layer_left_global_drawer = LayerLeftGlobalDrawer(self) self.layer_right_message_sidebar = LayerRightMessageSidebar(self) self.layer_modal_dialog = LayerModalDialog(self) + def groups(self): + return self.groups_ + def layerMain(self): return self.layer_main @@ -46,11 +61,16 @@ def layerChildPage(self): def layerModalDialog(self): return self.layer_modal_dialog + def layerLeftGlobalDrawer(self): + return self.layer_left_global_drawer + def resizeEvent(self, event): super().resizeEvent(event) size = event.size() w, h = size.width(), size.height() + self.group_main_interface.resize(w, h) + # Set the maximum height of the sidebar to prevent performance from dropping when too many message boxes exist. self.layer_right_message_sidebar.setMaximumHeight(event.size().height()) self.layer_right_message_sidebar.adjustSize() @@ -59,3 +79,4 @@ def resizeEvent(self, event): self.layer_child_page.resize(event.size()) self.layer_right_message_sidebar.setGeometry(w - 400, 80, 400, self.layer_right_message_sidebar.height()) self.layer_modal_dialog.resize(event.size()) + self.layer_left_global_drawer.resize(event.size()) diff --git a/siui/templates/application/components/layer/global_drawer.py b/siui/templates/application/components/layer/global_drawer.py new file mode 100644 index 0000000..572b245 --- /dev/null +++ b/siui/templates/application/components/layer/global_drawer.py @@ -0,0 +1,51 @@ +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import QWidget + +from siui.components import SiLabel, SiWidget, SiTitledWidgetGroup +from siui.components.page import SiPage +from siui.templates.application.components.layer.layer import SiLayer + + +class Drawer(SiWidget): + def resizeEvent(self, event): + super().resizeEvent(event) + for child in self.children(): + if isinstance(child, QWidget): + child.resize(event.size()) + + +class SiLayerDrawer(SiLayer): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.is_opened = False + + self.drawer = Drawer(self) + self.drawer_panel = SiLabel(self.drawer) + self.drawer_page = SiPage(self.drawer) + + self.setDrawerWidth(400) + self.closeLayer() + + def isOpened(self): + return self.is_opened + + def setOpened(self, state): + self.is_opened = state + + def setDrawerWidth(self, width): + self.drawer.resize(width, self.drawer.height()) + + def showLayer(self): + super().showLayer() + self.setAttribute(Qt.WA_TransparentForMouseEvents, False) + self.setOpened(True) + + def closeLayer(self): + super().closeLayer() + self.setAttribute(Qt.WA_TransparentForMouseEvents, True) + self.setOpened(False) + + def resizeEvent(self, event): + super().resizeEvent(event) + self.drawer.resize(self.drawer.width(), event.size().height()) diff --git a/siui/templates/application/components/layer/layer_left_global_drawer/__init__.py b/siui/templates/application/components/layer/layer_left_global_drawer/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/siui/templates/application/components/layer/layer_left_global_drawer/layer_left_global_drawer.py b/siui/templates/application/components/layer/layer_left_global_drawer/layer_left_global_drawer.py new file mode 100644 index 0000000..a64b0a8 --- /dev/null +++ b/siui/templates/application/components/layer/layer_left_global_drawer/layer_left_global_drawer.py @@ -0,0 +1,117 @@ +from PyQt5.QtCore import Qt + +from siui.components import SiLabel, SiSliderH, SiTitledWidgetGroup, SiWidget +from siui.components.combobox import SiComboBox +from siui.core.color import SiColor +from siui.core.globals import SiGlobal + +from ..global_drawer import SiLayerDrawer + + +class LayerLeftGlobalDrawer(SiLayerDrawer): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.drawer.move(-self.drawer.width(), 0) + + self.drawer_widget_group = SiTitledWidgetGroup(self) + self.drawer_widget_group.setSpacing(8) + + self.drawer_page.setPadding(48) + self.drawer_page.setTitle("全局左侧抽屉") + self.drawer_page.title.setContentsMargins(32, 0, 0, 0) + self.drawer_page.setScrollAlignment(Qt.AlignLeft) + + with self.drawer_widget_group as group: + group.addTitle("全局性") + + self.text_label = SiLabel(self) + self.text_label.setTextColor(self.colorGroup().fromToken(SiColor.TEXT_D)) + self.text_label.setWordWrap(True) + self.text_label.setText("这里是全局抽屉,无论在何种情况下,该抽屉被打开时都会令界面发生侧移,保证抽屉正常展开\n\n" + "不同于其他页面,全局抽屉推荐为唯一的,全局抽屉中的控件推荐为静态的") + self.text_label.setFixedHeight(128) + + group.addWidget(self.text_label) + + with self.drawer_widget_group as group: + group.addTitle("声音") + + self.label_output_device = SiLabel(self) + self.label_output_device.setTextColor(self.colorGroup().fromToken(SiColor.TEXT_C)) + self.label_output_device.setText("输出设备") + + self.demo_output_device = SiComboBox(self) + self.demo_output_device.resize(256, 32) + self.demo_output_device.addOption("默认设备") + self.demo_output_device.addOption("RealTek(R) Output") + self.demo_output_device.addOption("姬霓太美(R) Output") + self.demo_output_device.menu().setShowIcon(False) + self.demo_output_device.menu().setIndex(0) + + self.label_slider_1 = SiLabel(self) + self.label_slider_1.setTextColor(self.colorGroup().fromToken(SiColor.TEXT_C)) + self.label_slider_1.setText("总音量") + + self.demo_slider_1 = SiSliderH(self) + self.demo_slider_1.resize(0, 16) + self.demo_slider_1.setMinimum(0) + self.demo_slider_1.setMaximum(100) + self.demo_slider_1.setValue(80, move_to=False) + + self.label_slider_2 = SiLabel(self) + self.label_slider_2.setTextColor(self.colorGroup().fromToken(SiColor.TEXT_C)) + self.label_slider_2.setText("音乐音量") + + self.demo_slider_2 = SiSliderH(self) + self.demo_slider_2.resize(0, 16) + self.demo_slider_2.setMinimum(0) + self.demo_slider_2.setMaximum(100) + self.demo_slider_2.setValue(100, move_to=False) + + self.label_slider_3 = SiLabel(self) + self.label_slider_3.setTextColor(self.colorGroup().fromToken(SiColor.TEXT_C)) + self.label_slider_3.setText("音效音量") + + self.demo_slider_3 = SiSliderH(self) + self.demo_slider_3.resize(0, 16) + self.demo_slider_3.setMinimum(0) + self.demo_slider_3.setMaximum(100) + self.demo_slider_3.setValue(61, move_to=False) + + group.addWidget(self.label_output_device) + group.addWidget(self.demo_output_device) + group.addPlaceholder(8) + group.addWidget(self.label_slider_1) + group.addWidget(self.demo_slider_1) + group.addPlaceholder(8) + group.addWidget(self.label_slider_2) + group.addWidget(self.demo_slider_2) + group.addPlaceholder(8) + group.addWidget(self.label_slider_3) + group.addWidget(self.demo_slider_3) + + group.addPlaceholder(64) + + self.drawer_page.setAttachment(self.drawer_widget_group) + + def setOpened(self, state): + super().setOpened(state) + if state: + self.drawer.moveTo(0, 0) + else: + self.drawer.moveTo(-self.drawer.width(), 0) + + def reloadStyleSheet(self): + super().reloadStyleSheet() + self.drawer_panel.setStyleSheet( + f"background-color: {self.colorGroup().fromToken(SiColor.INTERFACE_BG_C)};" + f"border-right: 1px solid {self.colorGroup().fromToken(SiColor.INTERFACE_BG_D)}" + ) + + def showLayer(self): + super().showLayer() + SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(100, 0) + + def closeLayer(self): + super().closeLayer() + SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(0, 0) diff --git a/siui/templates/application/components/layer/layer_modal_dialog/layer_modal_dialog.py b/siui/templates/application/components/layer/layer_modal_dialog/layer_modal_dialog.py index 2a89856..428033a 100644 --- a/siui/templates/application/components/layer/layer_modal_dialog/layer_modal_dialog.py +++ b/siui/templates/application/components/layer/layer_modal_dialog/layer_modal_dialog.py @@ -1,8 +1,8 @@ -from PyQt5.QtCore import Qt, QTimer -from PyQt5.QtWidgets import QApplication +from PyQt5.QtCore import Qt from siui.components import SiWidget from siui.core.silicon import Si + from ..layer import SiLayer From dfc298dd10e3f25aba8f5b2000993813e08e6701 Mon Sep 17 00:00:00 2001 From: ChinaIceF <1489423523@qq.com> Date: Tue, 10 Sep 2024 16:45:43 +0800 Subject: [PATCH 2/2] hotfix: dynamic adding pages supports --- .../application/components/page_view/page_view.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/siui/templates/application/components/page_view/page_view.py b/siui/templates/application/components/page_view/page_view.py index e402098..2ea33c5 100644 --- a/siui/templates/application/components/page_view/page_view.py +++ b/siui/templates/application/components/page_view/page_view.py @@ -90,7 +90,8 @@ def __init__(self, *args, **kwargs): # 创建容器用于放置按钮 self.container = SiDenseVContainer(self) self.container.setSpacing(8) - self.container.setAlignment(Qt.AlignCenter) + self.container.setShrinking(False) + self.container.setAlignment(Qt.AlignHCenter) # 所有按钮 self.buttons = [] @@ -103,7 +104,7 @@ def addPageButton(self, svg_data, hint, func_when_active, side="top"): :param func_when_active: 当被激活时调用的函数 :param side: 添加在哪一侧 """ - new_page_button = PageButton(self) + new_page_button = PageButton(self.container) new_page_button.setIndex(self.maximumIndex()) new_page_button.setStyleSheet("background-color: #20FF0000") new_page_button.resize(40, 40) @@ -111,12 +112,14 @@ def addPageButton(self, svg_data, hint, func_when_active, side="top"): new_page_button.attachment().setSvgSize(20, 20) new_page_button.attachment().load(svg_data) new_page_button.activated.connect(func_when_active) + new_page_button.show() # 绑定索引切换信号,当页面切换时,会使按钮切换为 checked 状态 self.indexChanged.connect(new_page_button.on_index_changed) # 新按钮添加到容器中 self.container.addWidget(new_page_button, side=side) + self.container.arrangeWidget() self.setMaximumIndex(self.maximumIndex() + 1) self.buttons.append(new_page_button)