提交 22b430c5 编写于 作者: 之一Yo's avatar 之一Yo

更新文档

上级 9b11ac09
...@@ -37,17 +37,20 @@ git clone https://github.com/zhiyiYo/PyQt-Fluent-Widgets.git ...@@ -37,17 +37,20 @@ git clone https://github.com/zhiyiYo/PyQt-Fluent-Widgets.git
python setup.py install python setup.py install
``` ```
## Run example ## Run Example
After installing PyQt-Fluent-Widgets package using pip, you can run any demo in the examples directory, for example: After installing PyQt-Fluent-Widgets package using pip, you can run any demo in the examples directory, for example:
```python ```python
cd examples/settings cd examples/settings
python demo.py python demo.py
``` ```
## Document
Want to know more about PyQt-Fluent-Widgets? Please read the [help document](https://pyqt-fluent-widgets.readthedocs.io/) 👈
## See Also ## See Also
Here are some projects that use PyQt-Fluent-Widgets: Here are some projects that use PyQt-Fluent-Widgets:
* [**zhiyiYo/Groove**: A music player based on PyQt5 and LAV Filters](https://github.com/zhiyiYo/Groove) * [**zhiyiYo/Groove**: A cross-platform music player based on PyQt5](https://github.com/zhiyiYo/Groove)
* [**zhiyiYo/Alpha-Gobang-Zero**: A gobang robot based on reinforcement learning](https://github.com/zhiyiYo/Alpha-Gobang-Zero) * [**zhiyiYo/Alpha-Gobang-Zero**: A gobang robot based on reinforcement learning](https://github.com/zhiyiYo/Alpha-Gobang-Zero)
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
project = 'PyQt-Fluent-Widgets' project = 'PyQt-Fluent-Widgets'
copyright = '2023, zhiyiYo' copyright = '2023, zhiyiYo'
author = 'zhiyiYo' author = 'zhiyiYo'
release = 'v0.1.0' release = 'v0.1.1'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
......
## Gallery
### Acrylic Label
<img width="60%" src="./_static/gallery/acrylic_label.png"/>
### Color Dialog
![](./_static/gallery/color_dialog.gif)
### Dialog
![](./_static/gallery/dialog.gif)
### Flow Layout
![](./_static/gallery/flow_layout.gif)
### Folder List Dialog
![](./_static/gallery/folder_list_dialog.gif)
### Hollow Handle Slider
![](./_static/gallery/hollow_handle_slider.gif)
### Message Dialog
![](./_static/gallery/dialog_with_mask.gif)
### State Tool Tip
![](./_static/gallery/state_tool_tip.gif)
### Switch Button
![](./_static/gallery/switch_button.gif)
### Tool Tip
![](./_static/gallery/tool_tip.gif)
...@@ -47,4 +47,6 @@ This document will show you all the features of PyQt-Fluent-Widgets and the best ...@@ -47,4 +47,6 @@ This document will show you all the features of PyQt-Fluent-Widgets and the best
:caption: Contents :caption: Contents
quick-start quick-start
settings
gallery
see-also
## See also
Here are some projects that use PyQt-Fluent-Widgets:
- [**zhiyiYo/Groove**: A cross-platform music player based on PyQt5](https://github.com/zhiyiYo/Groove)
![](./_static/Groove音乐.jpg)
<br>
- [**zhiyiYo/Alpha-Gobang-Zero**: A gobang robot based on reinforcement learning](https://github.com/zhiyiYo/Alpha-Gobang-Zero)
![](./_static/Alpha-Gobang-Zero.jpg)
\ No newline at end of file
## Settings
PyQt-Fluent-Widgets presents each configuration item as a `SettingCard` on the interface. The behavior of user on the `SettingCard` will change the value of the configuration item, and PyQt-Fluent-Widgets will update the configuration item to the json configuration file automatically.
### Config
PyQt-Fluent-Widgets uses the `ConfigItem` class to represent a configuration item and uses the `QConfig` class to read and write the value of `ConfigItem`. The `QConfig` class will automatically update the configuration file when the value of the `ConfigItem` changes.
Since the value in config file may be manually modified by the user to an invalid value, PyQt-Fluent-Widgets use `ConfigValidator` and its subclass to verify and correct the config value.
Json files only support string, boolean value, list and dict, for enumeration classes or `QColor`, we can't use `json.dump()` to write them directly into a json file, so PyQt-Fluent-Widgets provides `ConfigSerializer` and its subclass to serialize and deserialize config item from config file. For example, you can use `ColorSerializer` to serialize config items with `QColor` value type.
`ConfigItem` has the following attributes:
| Attribute | Type | Description |
| :----------: | :----------------: | ------------------------------------------------------------ |
| `group` | `str` | The group to which the config item belongs |
| `name` | `str` | Name of config item |
| `default` | `Any` | The default value of config item, it will be used when the value in the config file is illegal |
| `validator` | `ConfigValidator` | Config validator |
| `serializer` | `ConfigSerializer` | Config serializer |
| `restart` | `bool` | Whether to restart the application after updating value |
You should add config items to the class attribute of `QConfig` subclasss, then use `qconfig.load()` to load config file, for example:
```python
class MvQuality(Enum):
""" MV quality enumeration class """
FULL_HD = "Full HD"
HD = "HD"
SD = "SD"
LD = "LD"
@staticmethod
def values():
return [q.value for q in MvQuality]
class Config(QConfig):
""" Config of application """
# main window
enableAcrylic = ConfigItem("MainWindow", "EnableAcrylic", False, BoolValidator())
playBarColor = ColorConfigItem("MainWindow", "PlayBarColor", "#225C7F")
themeMode = OptionsConfigItem("MainWindow", "ThemeMode", "Light", OptionsValidator(["Light", "Dark", "Auto"]), restart=True)
recentPlaysNumber = RangeConfigItem("MainWindow", "RecentPlayNumbers", 300, RangeValidator(10, 300))
# online
onlineMvQuality = OptionsConfigItem("Online", "MvQuality", MvQuality.FULL_HD, OptionsValidator(MvQuality), EnumSerializer(MvQuality))
# create config object and initialize it
cfg = Config()
qconfig.load('config/config.json', cfg)
```
### Setting card
PyQt-Fluent-Widgets provides many kinds of setting card:
| Class | Description |
| :----------------------: | ------------------------------------------------------------ |
| `HyperlinkCard` | Setting card with a hyper link |
| `ColorSettingCard` | Setting card with a color picker |
| `RangeSettingCard` | Setting card with a slider |
| `PushSettingCard` | Setting card with a naive push button |
| `PrimaryPushSettingCard` | Setting card with a push button highlighted in the background |
| `SwitchSettingCard` | Setting card with a switch button |
| `OptionsSettingCard` | Setting card with a group of radio buttons |
| `FolderListSettingCard` | Setting card for showing and managing folder list |
You can use `SettingCardGroup.addSettingCard()` to add a setting card to the same group, and `SettingCardGroup` will adjust its layout automatically based on the height of setting cards.
For the usage of these components, see [settings_ interface.py](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/settings/setting_interface.py).
# coding:utf-8
import sys
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QApplication, QWidget
from qfluentwidgets import ColorPickerButton
class Demo(QWidget):
def __init__(self):
super().__init__()
self.button = ColorPickerButton(QColor("#12aaa2"), 'Background Color', self)
self.resize(1000, 900)
self.button.move(440, 390)
self.setStyleSheet("Demo{background:white}")
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Demo()
w.show()
app.exec_()
\ No newline at end of file
QDialog {
background-color: rgb(0, 126, 153);
}
QLabel {
background-color: transparent;
}
QLabel#titleLabel {
color: white;
font: 33px 'Microsoft YaHei Light';
font-weight: bold;
}
QLabel#contentLabel {
color: white;
font: 18px 'Microsoft YaHei';
font-weight: 400;
}
QPushButton {
color: white;
border: 3px solid white;
border-radius: 0px;
padding: 5px 35px 5px 35px;
background: rgb(0, 126, 153);
font: 18px 'Microsoft YaHei';
font-weight: bold;
}
QPushButton:hover {
background: rgb(14, 179, 214);
}
QPushButton:pressed:focus {
color: black;
background-color: white;
}
QPushButton:focus{
background-color: rgb(0, 154, 187);
}
QPushButton:disabled {
background-color: rgb(204, 204, 204);
color: rgb(122, 122, 122);
}
\ No newline at end of file
...@@ -3,7 +3,7 @@ from enum import Enum ...@@ -3,7 +3,7 @@ from enum import Enum
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtGui import QGuiApplication, QFont from PyQt5.QtGui import QGuiApplication, QFont
from qfluentwidgets import (config, QConfig, ConfigItem, OptionsConfigItem, BoolValidator, from qfluentwidgets import (qconfig, QConfig, ConfigItem, OptionsConfigItem, BoolValidator,
ColorConfigItem, OptionsValidator, RangeConfigItem, RangeValidator, ColorConfigItem, OptionsValidator, RangeConfigItem, RangeValidator,
FolderListValidator, EnumSerializer, FolderValidator) FolderListValidator, EnumSerializer, FolderValidator)
...@@ -106,4 +106,4 @@ RELEASE_URL = "https://github.com/zhiyiYo/PyQt-Fluent-Widgets/releases/latest" ...@@ -106,4 +106,4 @@ RELEASE_URL = "https://github.com/zhiyiYo/PyQt-Fluent-Widgets/releases/latest"
cfg = Config() cfg = Config()
config.load('config/config.json', cfg) qconfig.load('config/config.json', cfg)
\ No newline at end of file \ No newline at end of file
...@@ -10,7 +10,7 @@ online at https://pyqt-fluent-widgets.readthedocs.io. ...@@ -10,7 +10,7 @@ online at https://pyqt-fluent-widgets.readthedocs.io.
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
""" """
__version__ = "0.0.1" __version__ = "0.1.1"
from .components import * from .components import *
from .common import * from .common import *
......
...@@ -342,4 +342,4 @@ class QConfig(QObject): ...@@ -342,4 +342,4 @@ class QConfig(QObject):
return self._cfg._theme.lower() return self._cfg._theme.lower()
config = QConfig() qconfig = QConfig()
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
from PyQt5.QtCore import QPoint, QRect, QSize, Qt from PyQt5.QtCore import QPoint, QRect, QSize, Qt
from PyQt5.QtGui import QIcon, QIconEngine, QImage, QPainter, QPixmap from PyQt5.QtGui import QIcon, QIconEngine, QImage, QPainter, QPixmap
from .config import config from .config import qconfig
class PixmapIconEngine(QIconEngine): class PixmapIconEngine(QIconEngine):
...@@ -33,4 +33,4 @@ class Icon(QIcon): ...@@ -33,4 +33,4 @@ class Icon(QIcon):
def getIconColor(): def getIconColor():
""" get the color of icon based on theme """ """ get the color of icon based on theme """
return "white" if config.theme == 'dark' else 'black' return "white" if qconfig.theme == 'dark' else 'black'
# coding:utf-8 # coding:utf-8
from .config import config from .config import qconfig
from PyQt5.QtCore import QFile from PyQt5.QtCore import QFile
from PyQt5.QtWidgets import QWidget from PyQt5.QtWidgets import QWidget
...@@ -13,7 +13,7 @@ def getStyleSheet(file: str): ...@@ -13,7 +13,7 @@ def getStyleSheet(file: str):
file: str file: str
qss file name, without `.qss` suffix qss file name, without `.qss` suffix
""" """
f = QFile(f":/qfluentwidgets/qss/{config.theme}/{file}.qss") f = QFile(f":/qfluentwidgets/qss/{qconfig.theme}/{file}.qss")
f.open(QFile.ReadOnly) f.open(QFile.ReadOnly)
qss = str(f.readAll(), encoding='utf-8') qss = str(f.readAll(), encoding='utf-8')
f.close() f.close()
......
...@@ -7,7 +7,7 @@ from PyQt5.QtGui import (QBrush, QColor, QFont, QFontMetrics, QMouseEvent, ...@@ -7,7 +7,7 @@ from PyQt5.QtGui import (QBrush, QColor, QFont, QFontMetrics, QMouseEvent,
from PyQt5.QtWidgets import (QApplication, QFileDialog, QHBoxLayout, QLabel, from PyQt5.QtWidgets import (QApplication, QFileDialog, QHBoxLayout, QLabel,
QVBoxLayout, QWidget, QPushButton) QVBoxLayout, QWidget, QPushButton)
from ...common.config import config from ...common.config import qconfig
from ...common.icon import getIconColor from ...common.icon import getIconColor
from ...common.style_sheet import setStyleSheet from ...common.style_sheet import setStyleSheet
from .dialog import Dialog from .dialog import Dialog
...@@ -208,7 +208,7 @@ class ClickableWindow(QWidget): ...@@ -208,7 +208,7 @@ class ClickableWindow(QWidget):
painter = QPainter(self) painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing) painter.setRenderHints(QPainter.Antialiasing)
isDark = config.theme == 'dark' isDark = qconfig.theme == 'dark'
bg = 51 if isDark else 204 bg = 51 if isDark else 204
brush = QBrush(QColor(bg, bg, bg)) brush = QBrush(QColor(bg, bg, bg))
painter.setPen(Qt.NoPen) painter.setPen(Qt.NoPen)
...@@ -251,7 +251,7 @@ class FolderCard(ClickableWindow): ...@@ -251,7 +251,7 @@ class FolderCard(ClickableWindow):
QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform | QPainter.Antialiasing) QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform | QPainter.Antialiasing)
# paint text and icon # paint text and icon
color = Qt.white if config.theme == 'dark' else Qt.black color = Qt.white if qconfig.theme == 'dark' else Qt.black
painter.setPen(color) painter.setPen(color)
if self._isPressed: if self._isPressed:
self.__drawText(painter, 15, 10, 15, 9) self.__drawText(painter, 15, 10, 15, 9)
......
...@@ -4,7 +4,7 @@ from PyQt5.QtGui import QColor, QResizeEvent ...@@ -4,7 +4,7 @@ from PyQt5.QtGui import QColor, QResizeEvent
from PyQt5.QtWidgets import (QDialog, QGraphicsDropShadowEffect, from PyQt5.QtWidgets import (QDialog, QGraphicsDropShadowEffect,
QGraphicsOpacityEffect, QHBoxLayout, QWidget, QFrame) QGraphicsOpacityEffect, QHBoxLayout, QWidget, QFrame)
from ...common.config import config from ...common.config import qconfig
class MaskDialogBase(QDialog): class MaskDialogBase(QDialog):
...@@ -21,7 +21,7 @@ class MaskDialogBase(QDialog): ...@@ -21,7 +21,7 @@ class MaskDialogBase(QDialog):
self.setAttribute(Qt.WA_TranslucentBackground) self.setAttribute(Qt.WA_TranslucentBackground)
self.setGeometry(0, 0, parent.width(), parent.height()) self.setGeometry(0, 0, parent.width(), parent.height())
c = 0 if config.theme == 'dark' else 255 c = 0 if qconfig.theme == 'dark' else 255
self.windowMask.resize(self.size()) self.windowMask.resize(self.size())
self.windowMask.setStyleSheet(f'background:rgba({c}, {c}, {c}, 0.6)') self.windowMask.setStyleSheet(f'background:rgba({c}, {c}, {c}, 0.6)')
self.__hBoxLayout.addWidget(self.widget) self.__hBoxLayout.addWidget(self.widget)
......
from .setting_card import (SettingCard, SwitchSettingCard, SettingIconFactory, from .setting_card import (SettingCard, SwitchSettingCard, SettingIconFactory,
RangeSettingCard, PushSettingCard, ColorSettingCard, RangeSettingCard, PushSettingCard, ColorSettingCard,
HyperlinkCard, PrimaryPushSettingCard) HyperlinkCard, PrimaryPushSettingCard, ColorPickerButton)
from .expand_setting_card import ExpandSettingCard from .expand_setting_card import ExpandSettingCard
from .folder_list_setting_card import FolderListSettingCard from .folder_list_setting_card import FolderListSettingCard
from .options_setting_card import OptionsSettingCard from .options_setting_card import OptionsSettingCard
......
...@@ -7,7 +7,7 @@ from PyQt5.QtGui import QPixmap, QPainter ...@@ -7,7 +7,7 @@ from PyQt5.QtGui import QPixmap, QPainter
from PyQt5.QtWidgets import (QPushButton, QFileDialog, QWidget, QLabel, from PyQt5.QtWidgets import (QPushButton, QFileDialog, QWidget, QLabel,
QHBoxLayout, QToolButton) QHBoxLayout, QToolButton)
from ...common.config import ConfigItem, config from ...common.config import ConfigItem, qconfig
from ..dialog_box.dialog import Dialog from ..dialog_box.dialog import Dialog
from .expand_setting_card import ExpandSettingCard from .expand_setting_card import ExpandSettingCard
from .setting_card import SettingIconFactory as SIF from .setting_card import SettingIconFactory as SIF
...@@ -115,7 +115,7 @@ class FolderListSettingCard(ExpandSettingCard): ...@@ -115,7 +115,7 @@ class FolderListSettingCard(ExpandSettingCard):
self.addFolderButton = PushButton( self.addFolderButton = PushButton(
SIF.create(SIF.FOLDER_ADD), self.tr('Add folder'), self) SIF.create(SIF.FOLDER_ADD), self.tr('Add folder'), self)
self.folders = config.get(configItem).copy() # type:List[str] self.folders = qconfig.get(configItem).copy() # type:List[str]
self.__initWidget() self.__initWidget()
def __initWidget(self): def __initWidget(self):
...@@ -140,7 +140,7 @@ class FolderListSettingCard(ExpandSettingCard): ...@@ -140,7 +140,7 @@ class FolderListSettingCard(ExpandSettingCard):
self.__addFolderItem(folder) self.__addFolderItem(folder)
self.folders.append(folder) self.folders.append(folder)
config.set(self.configItem, self.folders) qconfig.set(self.configItem, self.folders)
self.folderChanged.emit(self.folders) self.folderChanged.emit(self.folders)
def __addFolderItem(self, folder: str): def __addFolderItem(self, folder: str):
...@@ -171,4 +171,4 @@ class FolderListSettingCard(ExpandSettingCard): ...@@ -171,4 +171,4 @@ class FolderListSettingCard(ExpandSettingCard):
self._adjustViewSize() self._adjustViewSize()
self.folderChanged.emit(self.folders) self.folderChanged.emit(self.folders)
config.set(self.configItem, self.folders) qconfig.set(self.configItem, self.folders)
\ No newline at end of file \ No newline at end of file
...@@ -3,7 +3,7 @@ from typing import List ...@@ -3,7 +3,7 @@ from typing import List
from PyQt5.QtCore import pyqtSignal from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QButtonGroup, QLabel, QRadioButton from PyQt5.QtWidgets import QButtonGroup, QLabel, QRadioButton
from ...common.config import OptionsConfigItem, config from ...common.config import OptionsConfigItem, qconfig
from .expand_setting_card import ExpandSettingCard from .expand_setting_card import ExpandSettingCard
...@@ -54,7 +54,7 @@ class OptionsSettingCard(ExpandSettingCard): ...@@ -54,7 +54,7 @@ class OptionsSettingCard(ExpandSettingCard):
button.setProperty(self.configName, option) button.setProperty(self.configName, option)
self._adjustViewSize() self._adjustViewSize()
self.setSelected(config.get(self.configItem)) self.setSelected(qconfig.get(self.configItem))
self.buttonGroup.buttonClicked.connect(self.__onButtonClicked) self.buttonGroup.buttonClicked.connect(self.__onButtonClicked)
def __onButtonClicked(self, button: QRadioButton): def __onButtonClicked(self, button: QRadioButton):
...@@ -63,7 +63,7 @@ class OptionsSettingCard(ExpandSettingCard): ...@@ -63,7 +63,7 @@ class OptionsSettingCard(ExpandSettingCard):
return return
value = button.property(self.configName) value = button.property(self.configName)
config.set(self.configItem, value) qconfig.set(self.configItem, value)
self.choiceLabel.setText(button.text()) self.choiceLabel.setText(button.text())
self.choiceLabel.adjustSize() self.choiceLabel.adjustSize()
......
...@@ -8,7 +8,7 @@ from ..widgets.switch_button import SwitchButton, IndicatorPosition ...@@ -8,7 +8,7 @@ from ..widgets.switch_button import SwitchButton, IndicatorPosition
from ..widgets.slider import Slider from ..widgets.slider import Slider
from ..widgets.label import PixmapLabel from ..widgets.label import PixmapLabel
from ...common.style_sheet import setStyleSheet, getStyleSheet from ...common.style_sheet import setStyleSheet, getStyleSheet
from ...common.config import ConfigItem, config, RangeConfigItem from ...common.config import ConfigItem, qconfig, RangeConfigItem
from ...common.icon import getIconColor from ...common.icon import getIconColor
...@@ -106,7 +106,7 @@ class SwitchSettingCard(SettingCard): ...@@ -106,7 +106,7 @@ class SwitchSettingCard(SettingCard):
self.tr('Off'), self, IndicatorPosition.RIGHT) self.tr('Off'), self, IndicatorPosition.RIGHT)
if configItem: if configItem:
self.setChecked(config.get(configItem)) self.setChecked(qconfig.get(configItem))
setStyleSheet(self.switchButton, 'setting_card') setStyleSheet(self.switchButton, 'setting_card')
...@@ -124,7 +124,7 @@ class SwitchSettingCard(SettingCard): ...@@ -124,7 +124,7 @@ class SwitchSettingCard(SettingCard):
def setChecked(self, isChecked: bool): def setChecked(self, isChecked: bool):
""" set switch button checked state """ """ set switch button checked state """
if self.configItem: if self.configItem:
config.set(self.configItem, isChecked) qconfig.set(self.configItem, isChecked)
self.switchButton.setChecked(isChecked) self.switchButton.setChecked(isChecked)
self.switchButton.setText( self.switchButton.setText(
...@@ -179,7 +179,7 @@ class RangeSettingCard(SettingCard): ...@@ -179,7 +179,7 @@ class RangeSettingCard(SettingCard):
def __onValueChanged(self, value: int): def __onValueChanged(self, value: int):
""" slider value changed slot """ """ slider value changed slot """
config.set(self.configItem, value) qconfig.set(self.configItem, value)
self.valueLabel.setNum(value) self.valueLabel.setNum(value)
self.valueLabel.adjustSize() self.valueLabel.adjustSize()
self.valueChanged.emit(value) self.valueChanged.emit(value)
...@@ -329,13 +329,13 @@ class ColorSettingCard(SettingCard): ...@@ -329,13 +329,13 @@ class ColorSettingCard(SettingCard):
super().__init__(iconPath, title, content, parent) super().__init__(iconPath, title, content, parent)
self.configItem = configItem self.configItem = configItem
self.colorPicker = ColorPickerButton( self.colorPicker = ColorPickerButton(
config.get(configItem), title, self) qconfig.get(configItem), title, self)
self.hBoxLayout.addWidget(self.colorPicker, 0, Qt.AlignRight) self.hBoxLayout.addWidget(self.colorPicker, 0, Qt.AlignRight)
self.hBoxLayout.addSpacing(20) self.hBoxLayout.addSpacing(20)
self.colorPicker.colorChanged.connect(self.__onColorChanged) self.colorPicker.colorChanged.connect(self.__onColorChanged)
def __onColorChanged(self, color: QColor): def __onColorChanged(self, color: QColor):
config.set(self.configItem, color) qconfig.set(self.configItem, color)
self.colorChanged.emit(color) self.colorChanged.emit(color)
......
...@@ -6,7 +6,7 @@ with open('README.md', encoding='utf-8') as f: ...@@ -6,7 +6,7 @@ with open('README.md', encoding='utf-8') as f:
setuptools.setup( setuptools.setup(
name="PyQt-Fluent-Widgets", name="PyQt-Fluent-Widgets",
version="0.1.0", version="0.1.1",
keywords="pyqt fluent widgets", keywords="pyqt fluent widgets",
author="zhiyiYo", author="zhiyiYo",
author_email="shokokawaii@outlook.com", author_email="shokokawaii@outlook.com",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册