191 lines
6.5 KiB
Python
191 lines
6.5 KiB
Python
|
|
# coding:utf-8
|
||
|
|
import sys
|
||
|
|
from PySide6.QtCore import Qt, QEvent
|
||
|
|
from PySide6.QtGui import QIcon
|
||
|
|
from PySide6.QtWidgets import QApplication, QStackedWidget, QHBoxLayout, QLabel, QWidget, QVBoxLayout
|
||
|
|
|
||
|
|
from qfluentwidgets import (NavigationInterface, NavigationItemPosition, NavigationWidget, MessageBox,
|
||
|
|
isDarkTheme, setTheme, Theme, setThemeColor, NavigationToolButton, NavigationPanel)
|
||
|
|
from qfluentwidgets import FluentIcon as FIF
|
||
|
|
from qframelesswindow import FramelessWindow, StandardTitleBar
|
||
|
|
|
||
|
|
|
||
|
|
class Widget(QWidget):
|
||
|
|
|
||
|
|
def __init__(self, text: str, parent=None):
|
||
|
|
super().__init__(parent=parent)
|
||
|
|
self.label = QLabel(text, self)
|
||
|
|
self.hBoxLayout = QHBoxLayout(self)
|
||
|
|
|
||
|
|
self.label.setAlignment(Qt.AlignCenter)
|
||
|
|
self.hBoxLayout.addWidget(self.label, 1, Qt.AlignCenter)
|
||
|
|
|
||
|
|
self.setObjectName(text.replace(' ', '-'))
|
||
|
|
|
||
|
|
|
||
|
|
class NavigationBar(QWidget):
|
||
|
|
""" Navigation widget """
|
||
|
|
|
||
|
|
def __init__(self, parent=None):
|
||
|
|
super().__init__(parent=parent)
|
||
|
|
self.hBoxLayout = QHBoxLayout(self)
|
||
|
|
self.menuButton = NavigationToolButton(FIF.MENU, self)
|
||
|
|
self.navigationPanel = NavigationPanel(parent, True)
|
||
|
|
self.titleLabel = QLabel(self)
|
||
|
|
|
||
|
|
self.navigationPanel.move(0, 31)
|
||
|
|
self.hBoxLayout.setContentsMargins(5, 5, 5, 5)
|
||
|
|
self.hBoxLayout.addWidget(self.menuButton)
|
||
|
|
self.hBoxLayout.addWidget(self.titleLabel)
|
||
|
|
|
||
|
|
self.menuButton.clicked.connect(self.showNavigationPanel)
|
||
|
|
self.navigationPanel.setExpandWidth(260)
|
||
|
|
self.navigationPanel.setMenuButtonVisible(True)
|
||
|
|
self.navigationPanel.hide()
|
||
|
|
|
||
|
|
# enable acrylic effect
|
||
|
|
self.navigationPanel.setAcrylicEnabled(True)
|
||
|
|
|
||
|
|
self.window().installEventFilter(self)
|
||
|
|
|
||
|
|
def setTitle(self, title: str):
|
||
|
|
self.titleLabel.setText(title)
|
||
|
|
self.titleLabel.adjustSize()
|
||
|
|
|
||
|
|
def showNavigationPanel(self):
|
||
|
|
self.navigationPanel.show()
|
||
|
|
self.navigationPanel.raise_()
|
||
|
|
self.navigationPanel.expand()
|
||
|
|
|
||
|
|
def addItem(self, routeKey, icon, text: str, onClick, selectable=True, position= NavigationItemPosition.TOP):
|
||
|
|
def wrapper():
|
||
|
|
onClick()
|
||
|
|
self.setTitle(text)
|
||
|
|
|
||
|
|
self.navigationPanel.addItem(
|
||
|
|
routeKey, icon, text, wrapper, selectable, position)
|
||
|
|
|
||
|
|
def addSeparator(self, position=NavigationItemPosition.TOP):
|
||
|
|
self.navigationPanel.addSeparator(position)
|
||
|
|
|
||
|
|
def setCurrentItem(self, routeKey: str):
|
||
|
|
self.navigationPanel.setCurrentItem(routeKey)
|
||
|
|
self.setTitle(self.navigationPanel.widget(routeKey).text())
|
||
|
|
|
||
|
|
def eventFilter(self, obj, e: QEvent):
|
||
|
|
if obj is self.window():
|
||
|
|
if e.type() == QEvent.Resize:
|
||
|
|
self.navigationPanel.setFixedHeight(e.size().height() - 31)
|
||
|
|
|
||
|
|
return super().eventFilter(obj, e)
|
||
|
|
|
||
|
|
|
||
|
|
class Window(FramelessWindow):
|
||
|
|
|
||
|
|
def __init__(self):
|
||
|
|
super().__init__()
|
||
|
|
self.setTitleBar(StandardTitleBar(self))
|
||
|
|
|
||
|
|
# use dark theme mode
|
||
|
|
# setTheme(Theme.DARK)
|
||
|
|
|
||
|
|
# change the theme color
|
||
|
|
# setThemeColor('#0078d4')
|
||
|
|
|
||
|
|
self.vBoxLayout = QVBoxLayout(self)
|
||
|
|
self.navigationInterface = NavigationBar(self)
|
||
|
|
self.stackWidget = QStackedWidget(self)
|
||
|
|
|
||
|
|
# create sub interface
|
||
|
|
self.searchInterface = Widget('Search Interface', self)
|
||
|
|
self.musicInterface = Widget('Music Interface', self)
|
||
|
|
self.videoInterface = Widget('Video Interface', self)
|
||
|
|
self.folderInterface = Widget('Folder Interface', self)
|
||
|
|
self.settingInterface = Widget('Setting Interface', self)
|
||
|
|
|
||
|
|
self.stackWidget.addWidget(self.searchInterface)
|
||
|
|
self.stackWidget.addWidget(self.musicInterface)
|
||
|
|
self.stackWidget.addWidget(self.videoInterface)
|
||
|
|
self.stackWidget.addWidget(self.folderInterface)
|
||
|
|
self.stackWidget.addWidget(self.settingInterface)
|
||
|
|
|
||
|
|
# initialize layout
|
||
|
|
self.initLayout()
|
||
|
|
|
||
|
|
# add items to navigation interface
|
||
|
|
self.initNavigation()
|
||
|
|
|
||
|
|
self.initWindow()
|
||
|
|
|
||
|
|
def initLayout(self):
|
||
|
|
self.vBoxLayout.setSpacing(0)
|
||
|
|
self.vBoxLayout.setContentsMargins(0, self.titleBar.height(), 0, 0)
|
||
|
|
self.vBoxLayout.addWidget(self.navigationInterface)
|
||
|
|
self.vBoxLayout.addWidget(self.stackWidget)
|
||
|
|
self.vBoxLayout.setStretchFactor(self.stackWidget, 1)
|
||
|
|
|
||
|
|
def initNavigation(self):
|
||
|
|
self.addSubInterface(self.searchInterface, FIF.SEARCH, 'Search')
|
||
|
|
self.addSubInterface(self.musicInterface, FIF.MUSIC, 'Music library')
|
||
|
|
self.addSubInterface(self.videoInterface, FIF.VIDEO, 'Video library')
|
||
|
|
|
||
|
|
self.navigationInterface.addSeparator()
|
||
|
|
|
||
|
|
# add navigation items to scroll area
|
||
|
|
self.addSubInterface(self.folderInterface, FIF.FOLDER, 'Folder library', NavigationItemPosition.SCROLL)
|
||
|
|
|
||
|
|
# add item to bottom
|
||
|
|
self.addSubInterface(self.settingInterface, FIF.SETTING, 'Settings', NavigationItemPosition.BOTTOM)
|
||
|
|
|
||
|
|
self.stackWidget.currentChanged.connect(self.onCurrentInterfaceChanged)
|
||
|
|
self.stackWidget.setCurrentIndex(1)
|
||
|
|
|
||
|
|
def addSubInterface(self, w: QWidget, icon, text, position=NavigationItemPosition.TOP):
|
||
|
|
self.stackWidget.addWidget(w)
|
||
|
|
self.navigationInterface.addItem(
|
||
|
|
routeKey=w.objectName(),
|
||
|
|
icon=icon,
|
||
|
|
text=text,
|
||
|
|
onClick=lambda: self.switchTo(w),
|
||
|
|
position=position
|
||
|
|
)
|
||
|
|
|
||
|
|
def initWindow(self):
|
||
|
|
self.resize(500, 600)
|
||
|
|
self.setWindowIcon(QIcon('resource/logo.png'))
|
||
|
|
self.setWindowTitle('PyQt-Fluent-Widgets')
|
||
|
|
self.titleBar.setAttribute(Qt.WA_StyledBackground)
|
||
|
|
|
||
|
|
desktop = QApplication.screens()[0].availableGeometry()
|
||
|
|
w, h = desktop.width(), desktop.height()
|
||
|
|
self.move(w//2 - self.width()//2, h//2 - self.height()//2)
|
||
|
|
|
||
|
|
self.setQss()
|
||
|
|
|
||
|
|
def setQss(self):
|
||
|
|
color = 'dark' if isDarkTheme() else 'light'
|
||
|
|
with open(f'resource/{color}/demo.qss', encoding='utf-8') as f:
|
||
|
|
self.setStyleSheet(f.read())
|
||
|
|
|
||
|
|
def switchTo(self, widget):
|
||
|
|
self.stackWidget.setCurrentWidget(widget)
|
||
|
|
|
||
|
|
def onCurrentInterfaceChanged(self, index):
|
||
|
|
widget = self.stackWidget.widget(index)
|
||
|
|
self.navigationInterface.setCurrentItem(widget.objectName())
|
||
|
|
|
||
|
|
def showMessageBox(self):
|
||
|
|
w = MessageBox(
|
||
|
|
'This is a help message',
|
||
|
|
'You clicked a customized navigation widget. You can add more custom widgets by calling `NavigationInterface.addWidget()` 😉',
|
||
|
|
self
|
||
|
|
)
|
||
|
|
w.exec()
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
app = QApplication(sys.argv)
|
||
|
|
w = Window()
|
||
|
|
w.show()
|
||
|
|
app.exec()
|