Search code examples
pyside6qstyle

How do I check StyleOption state in Pyside6?


So I'm trying to determine what or how can I determine particular state of StyleOption. I used the '==' operator but building a QPushbutton it seems like it returns sometimes True and sometimes False for a particular metric.

Main.py

import sys
from PySide6.QtCore import *
from PySide6.QtWidgets import *
from CustomStyle import MyStyles


# Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Widgets App")

        layout = QVBoxLayout()

        # button
        mPushBtn = QPushButton('click')
        mPushBtn.setFlat(True)
        layout.addWidget(mPushBtn)

        widget = QWidget()
        widget.setLayout(layout)

        # Set the central widget of the Window. Widget will expand
        # to take up all the space in the window by default.
        self.setCentralWidget(widget)


app = QApplication(sys.argv)
app.setStyle(MyStyles('QPushButton'))
window = MainWindow()
window.show()

app.exec()

CustomStyle.py

from typing import Optional, Union

from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from PySide6.QtCharts import *

class MyStyles(QCommonStyle):
    def __init__(self, which_widget: str) -> None:
        super().__init__(which_widget)
        self.widget_name = which_widget

        self.setObjectName('fpStyles')

    def pixelMetric(self, m: QStyle.PixelMetric, opt: Optional[QStyleOption], widget: Optional[QWidget]) -> int:
        if widget.__class__.__name__ == self.widget_name:
            print(f'PixelMetric: metric > {m.name.decode()} -- styleOption > {opt.__class__.__name__} -- widget > {widget.__class__.__name__}')
            if opt is not None: print(f'\tsize >>> {opt.rect.getRect()}')
            if opt is not None: print(f'{opt.state == QStyle.State_Enabled}')
        return super().pixelMetric(m, opt, widget)

Running the above produces following output

Output


Solution

  • The QStyle State enum is a flag:

    It stores an OR combination of StateFlag values.

    This means that you cannot use the equality comparison, because using == will return True only if the state is exactly State_Enabled.

    The correct operator is &, which will mask the bits that are equal to the given value, and that can be converted to a bool to check its truthfulness:

    print(f'{bool(opt.state & QStyle.State_Enabled)}')
    

    To clarify, State_Enable corresponds to 1 (both binary and integer, obviously), but if the state also contains another flag such as State_Raised (which is 2, or binary 10), state will be 3, or binary 11.

    3 == 1 obviously returns False, but 3 & 1 masks the rightmost bit of 3, resulting in 1, and bool(1) results True.

    Read more about bitwise operators.

    Be aware that QCommonStyle is the basis for a completely new style. You should normally use QProxyStyle.

    Note: assuming your imports are done consistently, it's usually better to use isinstance(obj, cls) instead of comparing the class name.