PyQt-Fluent-Widgets Documentation

A fluent design widgets library based on C++ Qt/PyQt/PySide. Make Qt Great Again.

8,140 stars Python Python 13 files ยท ~7,603 tokens #custom#fluent#fluent-design#fluentui#gui#modern#pyqt5#pyqt6
RAW Doc

File: README.md

PyQt-Fluent-Widgets

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, PySide6 or PyQt6 branch.

The Pro version library contains more advance components. You can download PyQt-Fluent-Widgets-Pro-Gallery.zip from the release page for preview purposes.

C++ QFluentWidgets require purchasing a license from the official website. You can also download the compiled demo C++_QFluentWidgets.zip from the release page.

[!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 ๐Ÿ‘ˆ

License

PyQt-Fluent-Widgets is licensed under GPLv3 for non-commercial project. For commercial use, please purchase a commercial license.

Copyright ยฉ 2021 by zhiyiYo.

Work with Designer

Fluent Client integrates designer plugins, supporting direct drag-and-drop usage of QFluentWidgets components in Designer. You can purchase the client from TaoBao or Afdian.

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 [email protected]:

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

See Also

Here are some projects based on PyQt-Fluent-Widgets:

Reference


File: CHANGELOG.md

[Binary file]


File: requirements.txt

PyQt5>=5.15.0
PyQt5-Frameless-Window>=0.8.0
darkdetect
colorthief
scipy
pillow


File: docs/README_zh.md

PyQt-Fluent-Widgets

ๅฎ‰่ฃ…๐Ÿ“ฅ

ๅฎ‰่ฃ…่ฝป้‡็‰ˆ (ไบšๅ…‹ๅŠ›็ป„ไปถไธๅฏ็”จ)๏ผš

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ใ€PySide6 ๅ’Œ PyQt6 ๅˆ†ๆ”ฏไธ‹่ฝฝๅฏนๅบ”็š„ไปฃ็ ใ€‚

ๅ•†็”จ้ซ˜็บง็‰ˆ ็ป„ไปถๅบ“ๅŒ…ๅซๆ›ดๅคš็ป„ไปถ๏ผŒๅฏไปŽ ๅ‘่กŒ้กต้ข ไธ‹่ฝฝไฝ“้ชŒ็ผ–่ฏ‘ๅฅฝ็š„็คบไพ‹็จ‹ๅบ PyQt-Fluent-Widgets-Pro-Gallery.zipใ€‚

C++ QFluentWidgets ็ป„ไปถๅบ“้žๅผ€ๆบ๏ผŒๅฏไปŽ ๅ‘่กŒ้กต้ข ไธ‹่ฝฝไฝ“้ชŒ็ผ–่ฏ‘ๅฅฝ็š„็คบไพ‹็จ‹ๅบ C++_QFluentWidgets.zip๏ผŒไปทๆ ผ่ง ๅฎ˜็ฝ‘ใ€‚

[!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 ่ฎธๅฏ่ฏๆŽˆๆƒ้žๅ•†็”จ้กน็›ฎ๏ผŒๅ•†็”จ้กน็›ฎ้œ€่ดญไนฐๅ•†็”จ่ฎธๅฏ่ฏใ€‚

็ป„ไปถๅบ“ๅ—่ฝฏไปถ่‘—ไฝœๆƒไฟๆŠค๏ผŒ่ฝฏ่‘—็™ปๅญ—็ฌฌ12532763ๅท๏ผŒไปปไฝ•็›—็”จใ€็ ด่งฃ็ป„ไปถๅบ“ๆˆ–ๆœช็ปๆŽˆๆƒ็š„ๅ•†ไธšไฝฟ็”จๅ‡่ขซ่ง†ไธบไพตๆƒ่กŒไธบใ€‚

็‰ˆๆƒๆ‰€ๆœ‰ ยฉ 2021 by zhiyiYo.

ๅœจ็บฟๆ–‡ๆกฃ๐Ÿ“•

ๆƒณ่ฆไบ†่งฃ PyQt-Fluent-Widgets ็š„ๆญฃ็กฎไฝฟ็”จๅงฟๅŠฟ๏ผŸ่ฏทไป”็ป†้˜…่ฏป ๅธฎๅŠฉๆ–‡ๆกฃ ๐Ÿ‘ˆ

Fluent Client๐Ÿšฉ

Fluent Client ้›†ๆˆไบ†่ฎพ่ฎกๅธˆๆ’ไปถๅ’Œ่„šๆ‰‹ๆžถๅŠŸ่ƒฝ๏ผŒๆ”ฏๆŒๅœจ Designer ไธญ็›ดๆŽฅๆ‹–ๆ‹ฝไฝฟ็”จ QFluentWidgets ็š„็ป„ไปถ๏ผŒๆ‰€่งๅณๆ‰€ๅพ—๏ผŒ่ฎฉ็ŽฐไปฃๅŒ–็•Œ้ขๆญๅปบๅฆ‚ไธ่ˆฌ้กบๆป‘๏ผๅฏๅœจ ๆท˜ๅฎ ่ดญไนฐไฝฟ็”จ Fluent Clientใ€‚

้—ฎ้ข˜ๅ้ฆˆ๐Ÿ’ก

ๅฆ‚ๆžœๅœจไฝฟ็”จ่ฟ‡็จ‹ไธญ้‡ๅˆฐ้—ฎ้ข˜๏ผŒ่ฏทๅ…ˆๆŸฅ้˜…ๅฎ˜็ฝ‘ๆ–‡ๆกฃใ€‚่‹ฅ็กฎ่ฎค้—ฎ้ข˜ไธบ็ป„ไปถๅบ“็š„ bug๏ผŒ่ฏทๅฐ†ๆ“ไฝœ็ณป็ปŸไฟกๆฏใ€็ป„ไปถๅบ“็‰ˆๆœฌใ€ๆœ€ๅฐๅค็Žฐไปฃ็ ๅ’Œๅค็Žฐๆญฅ้ชคๅ‘้€่‡ณ [email protected]ใ€‚

ๅฆ่ง๐Ÿ‘€

ไธ‹้ขๆ˜ฏไธ€ไบ›ๅŸบไบŽ PyQt-Fluent-Widgets ็š„้กน็›ฎ๏ผš

ๅ‚่€ƒ


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


File: docs/.readthedocs.yaml

Read the Docs configuration file for Sphinx projects

See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

Required

version: 2

Set the OS, Python version and other tools you might need

build:
os: ubuntu-22.04
tools:
python: "3.8"
# You can also specify other tool versions:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"

Build documentation in the "docs/" directory with Sphinx

sphinx:
configuration: docs/source/conf.py

You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs

builder: "dirhtml"

Fail on all warnings to avoid broken references

fail_on_warning: true

Optionally build your docs in additional formats such as PDF and ePub

formats:

- pdf

- epub

to build your documentation

See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html

python:
install:
- requirements: docs/requirements.txt


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

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

.. raw:: html


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

Flow Layout

Status & info

State Tool Tip

Tool Tip

Info Bar

Material

Acrylic Label


File: 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'

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

PyQt-Fluent-Widgets


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


File: docs/source/license.md

License

Non-commercial usage is licensed under GPLv3. For commercial purposes, please purchase on official website to support the development of this project.

Copyright ยฉ 2021 by zhiyiYo.


File: docs/source/navigation.md

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.

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 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.

Minimal display mode navigation interface is available at navigation3.


File: docs/source/quick-start.rst

Quick start

Install

text
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.


File: docs/source/see-also.md

See also

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


File: 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 """

text
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 """

text
# 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>_.


File: 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.


File: 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 %}


File: examples/text/font_icon/font/PhotoIcons.json

{
"cloud": "\ue753",
"filter": "\ue71c",
"smile": "\ue76e"
}


File: .github/FUNDING.yml

These are supported funding model platforms

github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: zhiyiYo
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://afdian.com/a/zhiyiYo']


File: .github/ISSUE_TEMPLATE/Bug.yml

name: Bug Report
title: "[Bug]: "
labels: ["bug"]

body:

  • type: markdown
    attributes:
    value: |
    Thanks for taking the time to fill out this bug report! Please searched for historical issues and check official documentation before opening this issue.
  • type: textarea
    id: what-happened
    attributes:
    label: What happened?
    placeholder: Tell us what you see!
    validations:
    required: true
  • type: input
    id: OS
    attributes:
    label: Operation System
    placeholder: ex. Windows11 23H2
    validations:
    required: true
  • type: input
    id: Python
    attributes:
    label: Python Version
    placeholder: ex. 3.8.6 64-bit
    validations:
    required: true
  • type: input
    id: PyQt
    attributes:
    label: PyQt/PySide Version
    placeholder: ex. PyQt 5.15.2
    validations:
    required: true
  • type: input
    id: PyQt-Fluent-Widgets
    attributes:
    label: PyQt/PySide-Fluent-Widgets Version
    placeholder: ex. v1.3.1
    validations:
    required: true
  • type: textarea
    id: reproduce
    attributes:
    label: How to Reproduce?
    placeholder: Steps to reproduce the behavior(you can use gif to demonstrate the problem :)
    validations:
    required: true
  • type: textarea
    id: code
    attributes:
    label: Minimum code
    render: python3
    validations:
    required: true

File: .github/workflows/publish.yml

name: Upload Python Package

on: workflow_dispatch

permissions:
contents: read

jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
branch: [master, PyQt6, PySide2, PySide6]

text
steps:
- name: Checkout branch
  uses: actions/checkout@v4
  with:
    ref: ${{ matrix.branch }}

- name: Set up Python
  uses: actions/setup-python@v3
  with:
    python-version: '3.8'

- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install build

- name: Build package
  run: python -m build

- name: Publish package
  uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
  with:
    user: __token__
    password: ${{ secrets.PYPI_API_TOKEN }}