# Technical Documentation: zhiyiYo/PyQt-Fluent-Widgets

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/zhiyiYo/PyQt-Fluent-Widgets)

### Overview (README.md)

<p align="center">
  <img width="18%" align="center" src="https://raw.githubusercontent.com/zhiyiYo/PyQt-Fluent-Widgets/master/docs/source/_static/logo.png" alt="logo">
</p>
  <h1 align="center">
  PyQt-Fluent-Widgets
</h1>
<p align="center">
  A fluent design widgets library based on PyQt5
</p>

<div align="center">

[](https://pypi.org/project/PyQt-Fluent-Widgets)
[]()
[](LICENSE)
[]()

</div>

<p align="center">
English | <a href="docs/README_zh.md">简体中文</a> | <a href="https://qfluentwidgets.com/">官网</a>
</p>




## Install
To install lite version for PyQt5:
```shell
pip install PyQt-Fluent-Widgets -i https://pypi.org/simple/
```
Or install full-featured version (`AcrylicLabel` is  available):
```shell
pip install "PyQt-Fluent-Widgets[full]" -i https://pypi.org/simple/
```

If you are using PySide2, PySide6 or PyQt6, you can download the code in [PySide2](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/PySide2), [PySide6](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/PySide6) or [PyQt6](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/PyQt6) branch.

The [Pro version](https://qfluentwidgets.com/pages/pro) library contains more advance components. You can download `PyQt-Fluent-Widgets-Pro-Gallery.zip` from the [release page](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/releases) for preview purposes.

C++ QFluentWidgets require purchasing a license from the [official website](https://qfluentwidgets.com/price). You can also download the compiled demo `C++_QFluentWidgets.zip` from the [release page](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/releases).

> [!Warning]
> Don't install PyQt-Fluent-Widgets, PyQt6-Fluent-Widgets, PySide2-Fluent-Widgets and PySide6-Fluent-Widgets at the same time, because their package names are all `qfluentwidgets`.


## Run Example
After installing PyQt-Fluent-Widgets package using pip, you can run any demo in the examples directory, for example:
```shell
cd examples/gallery
python demo.py
```

If you encounter `ImportError: cannot import name 'XXX' from 'qfluentwidgets'`, it indicates that the package version you installed is too low. You can replace the mirror source with https://pypi.org/simple and reinstall again.

## Documentation
Want to know more about PyQt-Fluent-Widgets? Please read the [help document](https://qfluentwidgets.com) 👈


## License
PyQt-Fluent-Widgets is licensed under [GPLv3](./LICENSE) for non-commercial project. For commercial use, please purchase a [commercial license](https://qfluentwidgets.com/price).

Copyright © 2021 by zhiyiYo.


## Work with Designer
[Fluent Client](https://www.youtube.com/watch?v=7UCmcsOlhTk) integrates designer plugins, supporting direct drag-and-drop usage of QFluentWidgets components in Designer. You can purchase the client from [TaoBao](https://item.taobao.com/item.htm?ft=t&id=767961666600) or [Afdian](https://afdian.com/item/6726fcc4247311ef8c6852540025c377).



## Issue Reporting
If you encounter any problems while using the library, please first check the official documentation. If the issue is confirmed to be a bug in the library, please send the following information to [shokokawaii@outlook.com](mailto:shokokawaii@outlook.com):

- Operating system information
- QFluentWidgets Library version
- Minimal reproducible code
- Steps to reproduce


## See Also
Here are some projects based on PyQt-Fluent-Widgets:
* [**zhiyiYo/Fluent-M3U8**: A cross-platform m3u8 downloader](https://fluent-m3u8.org)
* [**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)

## Reference
* [**Windows design**: Design guidelines and toolkits for creating native app experiences](https://learn.microsoft.com/zh-cn/windows/apps/design/)
* [**Microsoft/WinUI-Gallery**: An app demonstrates the controls available in WinUI and the Fluent Design System](https://github.com/microsoft/WinUI-Gallery)

---

### README Zh (`docs/README_zh.md`)

<p align="center">
  <img width="18%" align="center" src="https://raw.githubusercontent.com/zhiyiYo/PyQt-Fluent-Widgets/master/docs/source/_static/logo.png" alt="logo">
</p>
  <h1 align="center">
  PyQt-Fluent-Widgets
</h1>
<p align="center">
  基于 PyQt5 的 Fluent Design 风格组件库
</p>


<div align="center">

[](https://pypi.org/project/PyQt-Fluent-Widgets)
[]()
[](LICENSE)
[]()

</div>

<p align="center">
<a href="../README.md">English</a> | 简体中文 | <a href="https://qfluentwidgets.com/">官方网站</a>
</p>




## 安装📥
安装轻量版 (亚克力组件不可用)：
```shell
pip install PyQt-Fluent-Widgets -i https://pypi.org/simple/
```
安装完整版：
```shell
pip install "PyQt-Fluent-Widgets[full]" -i https://pypi.org/simple/
```

如果项目中使用的是 PySide2、PySide6 或者 PyQt6，需切换至 [PySide2](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/PySide2)、[PySide6](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/PySide6) 和 [PyQt6](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/PyQt6) 分支下载对应的代码。

[商用高级版](https://qfluentwidgets.com/zh/pages/pro) 组件库包含更多组件，可从 [发行页面](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/releases) 下载体验编译好的示例程序 `PyQt-Fluent-Widgets-Pro-Gallery.zip`。

C++ QFluentWidgets 组件库非开源，可从 [发行页面](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/releases) 下载体验编译好的示例程序 `C++_QFluentWidgets.zip`，价格见 [官网](https://qfluentwidgets.com/zh/price)。

> [!Warning]
> 请勿同时安装 PyQt-Fluent-Widgets、PyQt6-Fluent-Widgets、PySide2-Fluent-Widgets 和 PySide6-Fluent-Widgets，因为他们的包名都是 `qfluentwidgets`


## 运行示例▶️
使用 pip 安装好 PyQt-Fluent-Widgets 包并下载好此仓库的代码之后，就可以运行 examples 目录下的任意示例程序，比如：
```shell
cd examples/gallery
python demo.py
```

如果遇到 `ImportError: cannot import name 'XXX' from 'qfluentwidgets'`，这表明安装的包版本过低。可以按照上面的安装指令将 pypi 源替换为 https://pypi.org/simple 并重新安装.


## 许可证📄
PyQt-Fluent-Widgets 使用 [GPLv3](./LICENSE) 许可证授权非商用项目，商用项目需购买[商用许可证](https://qfluentwidgets.com/zh/price)。

组件库受软件著作权保护，软著登字第12532763号，任何盗用、破解组件库或未经授权的商业使用均被视为侵权行为。

版权所有 © 2021 by zhiyiYo.

## 在线文档📕
想要了解 PyQt-Fluent-Widgets 的正确使用姿势？请仔细阅读 [帮助文档](https://qfluentwidgets.com/zh/) 👈


## Fluent Client🚩
[Fluent Client](https://qfluentwidgets.com/zh/pages/designer) 集成了设计师插件和脚手架功能，支持在 Designer 中直接拖拽使用 QFluentWidgets 的组件，所见即所得，让现代化界面搭建如丝般顺滑！可在 [淘宝](https://item.taobao.com/item.htm?ft=t&id=767961666600) 购买使用 Fluent Client。



## 问题反馈💡
如果在使用过程中遇到问题，请先查阅官网文档。若确认问题为组件库的 bug，请将操作系统信息、组件库版本、最小复现代码和复现步骤发送至 [shokokawaii@outlook.com](mailto:shokokawaii@outlook.com)。


## 另见👀
下面是一些基于 PyQt-Fluent-Widgets 的项目：
* [**zhiyiYo/Fluent-M3U8**: 美观易用的跨平台 m3u8 下载器](https://fluent-m3u8.org)
* [**zhiyiYo/Groove**: 基于 PyQt5 的跨平台音乐播放器](https://github.com/zhiyiYo/Groove)
* [**zhiyiYo/Alpha-Gobang-Zero**: 基于强化学习的五子棋机器人](https://github.com/zhiyiYo/Alpha-Gobang-Zero)

## 参考
* [**Windows design**: Design guidelines and toolkits for creating native app experiences](https://learn.microsoft.com/zh-cn/windows/apps/design/)
* [**Microsoft/WinUI-Gallery**: An app demonstrates the controls available in WinUI and the Fluent Design System](https://github.com/microsoft/WinUI-Gallery)

---

### Requirements (`docs/requirements.txt`)

PyQt5>=5.15.0
PyQt5-Frameless-Window
darkdetect
colorthief
scipy
pillow
sphinx-markdown-tables==0.0.17
sphinx-intl
furo
sphinx-autoapi
sphinx-copybutton
sphinx_design
urllib3<2.0.0
mock==1.0.1
commonmark==0.9.1
recommonmark==0.5.0

---

### Source Designer (`docs/source/designer.rst`)

Designer
--------

In Qt Designer, there are two ways to use PyQt-Fluent-Widgets.


Using Client (Recommend)
^^^^^^^^^^^^^^^^^^^^^^^^

Fluent Client integrates designer plugins, visual Nuitka packaging, and skeleton functionality, supporting direct drag-and-drop usage of QFluentWidgets components in Designer.

What you see is what you get, making the construction of modern interfaces silky smooth! You can purchase from `TaoBao <https://item.taobao.com/item.htm?ft=t&id=767961666600>`_ or `Afdian <https://afdian.com/item/6726fcc4247311ef8c6852540025c377>`_.

.. image:: https://img.fastmirror.net/s/2024/02/18/65d22363d4a73.jpg
   :target: https://img.fastmirror.net/s/2024/02/18/65d22363d4a73.jpg
   :alt:


Promoting widget
^^^^^^^^^^^^^^^^

Right click on a widget, select the ``Promote to ...`` of context menu.

Promoting a widget indicates that it should be replaced with the specified subclass, in our case the ``qfluentwidgets.PushButton``.

.. image:: ./_static/promote_context.jpg
   :target: ./_static/promote_context.jpg
   :alt:


You will be presented with a dialog to specify the custom widget class the placeholder widget will become.

The header file is the name of the Python module used to import the class, which is ``qfluentwidgets``. Specify ``PushButton`` as the class name of the widget to replace it with.

.. image:: ./_static/promote_dialog.jpg
   :target: ./_static/promote_dialog.jpg
   :alt:


Well, the widget is now promoted to fluent push button. But you won't be able to see any changes within Qt Designer. Save the window as ``mainwindow.ui`` and compile it to python code, you will see that the ``PushButton`` is imported from ``qfluentwidgets`` package.

.. raw:: html

   <div style="position: relative; padding: 30% 45%;">
      <iframe style="position: absolute; width: 100%; height: 100%; left: 0; top: 0;" src="https://player.bilibili.com/player.html?cid=1107159421&aid=655415814&page=1&as_wide=1&high_quality=1&danmaku=0" frameborder="no" scrolling="no" allowfullscreen="true"></iframe>
   </div>





Complex example
^^^^^^^^^^^^^^^
Here is an example that uses a side navigation bar to implement multiple sub-interfaces window.

.. raw:: html

   <div style="position: relative; padding: 30% 45%;">
      <iframe style="position: absolute; width: 100%; height: 100%; left: 0; top: 0;" src="https://player.bilibili.com/player.html?cid=1193201502&aid=530806716&page=1&as_wide=1&high_quality=1&danmaku=0" frameborder="no" scrolling="no" allowfullscreen="true"></iframe>
   </div>

---

### Source Gallery (`docs/source/gallery.md`)

## Gallery

### Basic input
#### Button


#### Check Box


#### Combo Box


#### Radio Button


#### Switch Button


#### Slider


#### Hollow Handle Slider



### Dialogs
#### Color Dialog


#### Dialog


#### Message Box


#### Win10 Style Message Dialog


#### Folder List Dialog



### Menus


### Flow Layout


### Navigation


### Status & info
#### State Tool Tip


#### Tool Tip


#### Info Bar



### Material
#### Acrylic Label
<img width="60%" src="./_static/gallery/acrylic_label.png"/>

---

### Source Icon (`docs/source/icon.md`)

## Icon
Many widgets need icons, if you want PyQt-Fluent-Widgets change your icons automatically when the theme changes, then you can inherit `FluentIconBase` and overide `path()` method. Here is an example:

```python
from enum import Enum

from qfluentwidgets import getIconColor, Theme, FluentIconBase


class MyFluentIcon(FluentIconBase, Enum):
    """ Custom icons """

    ADD = "Add"
    CUT = "Cut"
    COPY = "Copy"

    def path(self, theme=Theme.AUTO):
        return f':/icons/{self.value}_{getIconColor(theme)}.svg'
```

---

### Source Index (`docs/source/index.rst`)

.. PyQt-Fluent-Widgets documentation master file, created by
   sphinx-quickstart on Tue Jan 17 15:31:54 2023.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

.. raw:: html

   <p align="center">
      <img width="18%" align="center" src="./_static/logo.png" alt="logo">
   </p>

   <h1 align="center">
      PyQt-Fluent-Widgets
   </h1>

   <hr/>

   <p align="center">
      A fluent design widgets library based on PyQt5
   </p>

   <p align="center">
      <a style="text-decoration:none">
         <img src="https://img.shields.io/badge/Platform-Win32%20|%20Linux%20|%20macOS-blue?color=#4ec820" alt="Platform Win32 | Linux | macOS"/>
      </a>

      <a style="text-decoration:none">
         <img src="https://static.pepy.tech/personalized-badge/pyqt-fluent-widgets?period=total&units=international_system&left_color=grey&right_color=brightgreen&left_text=Downloads" alt="Download"/>
      </a>

      <a style="text-decoration:none">
         <img src="https://img.shields.io/badge/License-GPLv3-blue?color=#4ec820" alt="GPLv3"/>
      </a>
   </p>

   <p align="center">
      <img src="./_static/Interface.jpg" alt="Interface">
   </p>


Welcome to PyQt-Fluent-Widgets's document!
===============================================
This document will show you all the features of PyQt-Fluent-Widgets and the best practice of it.

.. toctree::
   :maxdepth: 2
   :caption: Contents

   quick-start
   designer
   settings
   theme
   navigation
   icon
   support
   license
   gallery
   see-also

---

### Source Navigation (`docs/source/navigation.md`)

## Navigation
### Structure

PyQt Fluent Widgets provides a side navigation class `NavigationInterface`. You can use it with `QStackWidget` and put them in `QHBoxLayout`. Examples are available at [navigation2](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/master/examples/navigation2).



`NavigationInterface` contains `NavigationPanel` which is used to place navigation menu items. All navigation menu items should inherit from `NavigationWidget` and you can add them to the panel by calling `NavigationInterface.addWidget()` or `NavigationPanel.addWidget()`. PyQt-Fluent-Widgets implements subclass `NavigationPushButton` and provides a convenient method `NavigationInterface.addItem()` to add it to the panel.

If you want to customize a navigation menu item, you should inherit the `NavigationWidget` and rewrite its `paintEvent()` and `setCompacted()`(optional). Here an example shows how to create an avatar item.
```python
from qfluentwidgets import NavigationWidget


class AvatarWidget(NavigationWidget):
    """ Avatar widget """

    def __init__(self, parent=None):
        super().__init__(isSelectable=False, parent=parent)
        self.avatar = QImage('resource/shoko.png').scaled(
            24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)

    def paintEvent(self, e):
        painter = QPainter(self)
        painter.setRenderHints(
            QPainter.SmoothPixmapTransform | QPainter.Antialiasing)

        painter.setPen(Qt.NoPen)

        if self.isPressed:
            painter.setOpacity(0.7)

        # draw background
        if self.isEnter:
            c = 255 if isDarkTheme() else 0
            painter.setBrush(QColor(c, c, c, 10))
            painter.drawRoundedRect(self.rect(), 5, 5)

        # draw avatar
        painter.setBrush(QBrush(self.avatar))
        painter.translate(8, 6)
        painter.drawEllipse(0, 0, 24, 24)
        painter.translate(-8, -6)

        if not self.isCompacted:
            painter.setPen(Qt.white if isDarkTheme() else Qt.black)
            font = QFont('Segoe UI')
            font.setPixelSize(14)
            painter.setFont(font)
            painter.drawText(QRect(44, 0, 255, 36), Qt.AlignVCenter, 'zhiyiYo')
```

Now let's take a look at the parameters required for the `addWidget()` method:

```python
def addWidget(
    self,
    routeKey: str,
    widget: NavigationWidget,
    onClick=None,
    position=NavigationItemPosition.TOP,
    tooltip: str = None,
    parentRouteKey: str = None
)
```

As you can see, this method requires four parameters:

* `routeKey`: A unique name for the `widget` to be added. You can consider the sub interface in the `QStackWidget` as a web page, and the `routeKey` is the url of the web page. When you switch between sub interfaces, `NavigationPanel` will add a `routeKey` to the navigation history. When you click the return button, the `routeKey` at the top of the navigation history will pop up. If there are other `routeKeys` in the history at this time, PyQt-Fluent-Widgets will switch to the corresponding sub interface corresponding to current top `routeKey`. Otherwise, it will switch to the sub interface corresponding to `defaultRouteKey`, so you should call `NavigationInterface.setDefaultRouteKey()` before running app.
* `widget`: The widget to be added to panel.
* `onClick`: Slot function connected to the widget's `clicked` signal. If you want to switch sub interfaces when clicking `widget`, it is recommended to write this slot function as `lambda: self.stackWidget.setCurrentWidget(self.xxxInterface) `.
* `position`: Where to add the `widget` to the panel. The following values are available:
  * `NavigationItemPosition.TOP`: add `widget` to the top layout of panel.
  * `NavigationItemPosition.SCROLL`: add `widget` to the scroll layout of panel. You can scroll the widgets in scroll layout when there are too many menu items.
  * `NavigationItemPosition.BOTTOM`: add `widget` to the bottom layout of panel.
* `tooltip`: The tooltip of menu item.
* `parentRouteKey`: The route key of parent menu item, the widget of parent item must be the instance of `NavigationTreeWidgetBase`

### Display mode

The navigation panel has four display modes:

* `NavigationDisplayMode.EXPAND`: An expanded left pane on large window widths (1008px or greater).
  

* `NavigationDisplayMode.COMPACT`: A left, icon-only, nav panel on medium window widths (1007px or less).
  

* `NavigationDisplayMode.MENU`: An expanded left menu (1007px or less).
  

* `NavigationDisplayMode.MINIMAL`: Only a menu button on small window widths (you should add and manage the menu button to main window by yourself like [navigation3](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/master/examples/navigation3) does).

If you call `NavigationInterface.setExpandWidth()`, the large window width (1008px) will change accordingly.


### More examples
Here is an another style of navigation interface, and its corresponding example program is available at [navigation](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/master/examples/navigation).



Minimal display mode navigation interface is available at [navigation3](https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/master/examples/navigation3).

---

### Source Quick Start (`docs/source/quick-start.rst`)

Quick start
-----------

Install
~~~~~~~

To install lite version (``AcrylicLabel`` is not available) use pip:

.. code:: shell

   pip install PyQt-Fluent-Widgets -i https://pypi.org/simple/

Or install full-featured version use pip:

.. code:: shell

   pip install "PyQt-Fluent-Widgets[full]" -i https://pypi.org/simple/

If you are using PySide2, PySide6 or PyQt6, you can download the code in `PySide2 <https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/PySide2>`__, `PySide6 <https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/PySide6>`__ or `PyQt6 <https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/PyQt6>`__ branch.

.. warning:: Don't install PyQt-Fluent-Widgets, PyQt6-Fluent-Widgets, PySide2-Fluent-Widgets and PySide6-Fluent-Widgets at the same time, because their package names are all ``qfluentwidgets``.

Run example
~~~~~~~~~~~

After installing PyQt-Fluent-Widgets package using pip, you can run any
demo in the examples directory, for example:

.. code:: python

   cd examples/gallery
   python demo.py

.. note:: If you encounter ``ImportError: cannot import name 'XXX' from 'qfluentwidgets'``, it indicates that the package version you installed is too low. You can replace the mirror source with https://pypi.org/simple and reinstall again.

---

### Source See Also (`docs/source/see-also.md`)

## See also

Here are some projects that use PyQt-Fluent-Widgets:

- [**zhiyiYo/QMaterialWidgets**: A material design widgets library based on PySide](https://github.com/zhiyiYo/QMaterialWidgets)
  

<br>

- [**zhiyiYo/Groove**: A cross-platform music player based on PyQt5](https://github.com/zhiyiYo/Groove)
  

<br>

- [**zhiyiYo/Alpha-Gobang-Zero**: A gobang robot based on reinforcement learning](https://github.com/zhiyiYo/Alpha-Gobang-Zero)

---

### Source Settings (`docs/source/settings.rst`)

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:

.. list-table::
   :header-rows: 1

   * - 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:

.. code-block:: 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:

.. list-table::
   :header-rows: 1

   * - Class
     - Description
   * - ``HyperlinkCard``
     - Setting card with a hyper link
   * - ``ColorSettingCard``
     - Setting card with a color picker
   * - ``CustomColorSettingCard``
     - Setting card with a button to choose color
   * - ``ComboBoxSettingCard``
     - Setting card with a combo box
   * - ``RangeSettingCard``
     - Setting card with a slider
   * - ``PushSettingCard``
     - Setting card with a naive push button
   * - ``PrimaryPushSettingCard``
     - Setting card with a primary color push button
   * - ``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>`_.

---

### Source Theme (`docs/source/theme.md`)

## Theme

### Theme mode
You can use the `setTheme()` method to switch the light/dark theme of PyQt-Fluent-Widgets. The parameter of `setTheme()` accepts the following three values:
* `Theme.LIGHT`: Light theme
* `Theme.DARK`: Dark theme
* `Theme.AUTO`: Follow system theme. If the system theme cannot be detected, the light theme will be used.

When the theme changes, the config instance managed by `qconfig` (i.e., the config object passed in using the `qconfig.load()` method) will emit the `themeChanged` signal.

If you want to automatically switch the interface style when the theme changes, you can inherit `StyleSheetBase` and override the `path()` method. Suppose you have a `MainWindow` class and its qss file paths are `app/resource/qss/light/main_window.qss` and `app/resource/qss/dark/main_window.qss`, the code can be written like this:

```python
from enum import Enum
from qfluentwidgets import StyleSheetBase, Theme, isDarkTheme, qconfig


class StyleSheet(StyleSheetBase, Enum):
    """ Style sheet  """

    MAIN_WINDOW = "main_window"

    def path(self, theme=Theme.AUTO):
        theme = qconfig.theme if theme == Theme.AUTO else theme
        return f"app/resource/qss/{theme.value.lower()}/{self.value}.qss"


class MainWindow(QWidget):

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

        # apply style sheet to main window
        StyleSheet.MAIN_WINDOW.apply(self)
```


### Theme color
You can use `setThemeColor()` method to change the theme color of PyQt-Fluent-Widgets. This method accepts the following three types of parameters:
* `QColor`
* `Qt.GlobalColor`
* `str`: Hex color strings or color names, such as `#0065d5` or `red`.

When the theme color changes, the config instance managed by `qconfig` will emit the `themeColorChanged` signal.

---

### Source  Templates Python Module (`docs/source/_templates/python/module.rst`)

{% if not obj.display %}
:orphan:

{% endif %}
{{ obj.short_name }}
{{ "=" * obj.short_name|length }}

.. py:module:: {{ obj.name }}

{% if obj.docstring %}
.. autoapi-nested-parse::

   {{ obj.docstring|indent(3) }}

{% endif %}

{% block subpackages %}
{% set visible_subpackages = obj.subpackages|selectattr("display")|list %}
{% if visible_subpackages %}


.. toctree::
   :titlesonly:
   :maxdepth: 3

{% for subpackage in visible_subpackages %}
   {{ subpackage.short_name }}/index.rst
{% endfor %}


{% endif %}
{% endblock %}
{% block submodules %}
{% set visible_submodules = obj.submodules|selectattr("display")|list %}
{% if visible_submodules %}


.. toctree::
   :titlesonly:
   :maxdepth: 1

{% for submodule in visible_submodules %}
   {{ submodule.short_name }}/index.rst
{% endfor %}


{% endif %}
{% endblock %}
{% block content %}
{% if obj.all is not none %}
{% set visible_children = obj.children|selectattr("short_name", "in", obj.all)|list %}
{% elif obj.type is equalto("package") %}
{% set visible_children = obj.children|selectattr("display")|list %}
{% else %}
{% set visible_children = obj.children|selectattr("display")|rejectattr("imported")|list %}
{% endif %}
{% if visible_children %}
{{ obj.type|title }} Contents
{{ "-" * obj.type|length }}---------

{% set visible_classes = visible_children|selectattr("type", "equalto", "class")|list %}
{% set visible_functions = visible_children|selectattr("type", "equalto", "function")|list %}
{% set visible_attributes = visible_children|selectattr("type", "equalto", "data")|list %}
{% if "show-module-summary" in autoapi_options and (visible_classes or visible_functions) %}
{% block classes scoped %}
{% if visible_classes %}


.. autoapisummary::

{% for klass in visible_classes %}
   {{ klass.id }}
{% endfor %}


{% endif %}
{% endblock %}

{% block functions scoped %}
{% if visible_functions %}


.. autoapisummary::

{% for function in visible_functions %}
   {{ function.id }}
{% endfor %}


{% endif %}
{% endblock %}

{% block attributes scoped %}
{% if visible_attributes %}


.. autoapisummary::

{% for attribute in visible_attributes %}
   {{ attribute.id }}
{% endfor %}


{% endif %}
{% endblock %}
{% endif %}
{% for obj_item in visible_children %}
{{ obj_item.render()|indent(0) }}
{% endfor %}
{% endif %}
{% endblock %}

---

--- METRICS ---
- Files Extracted: 13
- Estimated Token Budget: ~7102 tokens
- Canonical Reference: https://codewiki.google/github.com/zhiyiYo/PyQt-Fluent-Widgets
