PySide6 QCheckBox stateChanged() generates state event int instead of Qt.CheckState

huangapple go评论79阅读模式
英文:

PySide6 QCheckBox stateChanged() generates state event int instead of Qt.CheckState

问题

以下是翻译好的部分:

"PySide6 6.4.1 PIP on Ubuntu and Windows contains a QCheckBox with stateChanged() API call to generate an event when the checkbox state changes."

"QCheckBox的生成的事件参数state的类型是int而不是枚举CheckState`:"

"下面的测试用例演示了不起作用的复选框事件状态:"

"我不知道如何将Qt.CheckedQt.PartiallyCheckedQt.Unchecked转换为int。"

"使用if state == int(Qt.Checked)进行强制转换会生成以下错误:"

"TypeError: int() argument must be a string, a bytes-like object or a real number, not 'CheckState'"

"这是否是预期行为?"

英文:

PySide6 6.4.1 PIP on Ubuntu and Windows contains a QCheckBox with stateChanged() API call to generate an event when the checkbox state changes.

The QCheckBox generated event argument state is type int instead of enum CheckState:

Testcase below demonstrates not working checkbox event state:

from PySide6.QtWidgets import QApplication, QWidget, QCheckBox
from PySide6.QtCore import Qt
import sys

class Window(QWidget):
    def __init__(self):
        super().__init__()

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('QCheckBox')

        checkbox = QCheckBox('Show title', self)
        checkbox.move(20, 20)
        checkbox.toggle()
        checkbox.setTristate(True)
        checkbox.stateChanged.connect(self.onCheckboxChange)

    def onCheckboxChange(self, state):
        # state = int and not Qt.Checked or Qt.Unchecked
        # This is not matching with the documentation

        print('Qt.Checked type: {}'.format(type(Qt.Checked)))
        print('Event: {}, type: {}'.format(state, type(state)))

        # Always setting title to UNKNOWN as this is an incorrect type comparison
        if state == Qt.Unchecked:
            self.setWindowTitle('Unchecked')
        elif state == Qt.PartiallyChecked:
            self.setWindowTitle('PartiallyChecked')
        elif state == Qt.Checked:
            self.setWindowTitle('Checked')
        else:
            self.setWindowTitle('UNKNOWN')

def main():
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

if __name__ == '__main__':
    main()

Output:

# When unchecking checkbox:
Qt.Checked type: <enum 'CheckState'>
Event: 0, type: <class 'int'>    <= Expected Qt.Unchecked:

# When partially checking checkbox:
Qt.Checked type: <enum 'CheckState'>
Event: 1, type: <class 'int'>    <= Expected Qt.PartiallyChecked:

# When checking checkbox:
Qt.Checked type: <enum 'CheckState'>
Event: 2, type: <class 'int'>    <= Expected Qt.Checked:

I don't know how to convert the Qt.Checked , Qt.PartiallyChecked or Qt.Unchecked to an int.
Casting with if state == int(Qt.Checked) generates:

  • TypeError: int() argument must be a string, a bytes-like object or a real number, not 'CheckState'

Is this expected behavior?

答案1

得分: 0

这是正确的,也是预期的行为。

如果您仔细阅读文档,您会发现 stateChanged 参数的类型确实是int

PySide6.QtWidgets.QCheckBox.stateChanged(arg__1)
   参数
       arg__1 - int

尽管这可能看起来令人意外和不一致,但这就是我们现在的情况。我不知道为什么,但我怀疑这是由于历史原因。

从Qt6开始,Python绑定(PySide和PyQt)都已经切换到了实际的Python枚举,这可能会引发一些混淆。

现在,只有继承自enum.IntEnum的枚举才能进行int()转换,而这对于 Qt.CheckState 并不成立,但对于其他一些枚举(例如,Qt.ItemDataRole)是成立的。

如果您想要比较stateChanged的结果,那么可以将值转换为枚举:

if Qt.CheckState(state) == Qt.Checked:

或者获取枚举的 value

if state == Qt.Checked.value:

关于术语的一些重要说明:1. stateChanged 是一个 信号,而不是一个 "API 调用"(事实上,信号甚至不可调用);2. 信号不是事件,至少在Qt术语中是这样:事件是由系统(或合成)生成的事件,通常是由系统生成,要么是由用户交互引发的,要么是由系统本身引发的。

英文:

It is not wrong, and it is the expected behavior.

If you read the documentation more carefully, the type of the argument is int for stateChanged:

> PySide6.QtWidgets.QCheckBox.stateChanged(arg__1)
>     PARAMETERS
>         arg__1 - int

While it might seem unexpected and inconsistent, that's what we have. I don't know why, but my suspect is that it's for historical reasons.

Starting with Qt6, both python bindings (PySide and PyQt) have switched to actual python enums, and this can create some level of confusion.

int() conversion is now only possible for enums that actually inherit from enum.IntEnum, which is not the case for Qt.CheckState, but it is for some others (for example, Qt.ItemDataRole).

If you want to compare the result of stateChanged, then either convert the value to the enum:

if Qt.CheckState(state) == `Qt.Checked`:

Otherwise get the value:

if state == Qt.Checked.value:

<sup>Some important notes about terminology: 1. stateChanged is a signal, not an "API call" (in fact, signals are not even callable); 2. signals are not events, at least in Qt terms: events are system (or synthesized) events that are normally generated by the system, either by user interaction or caused by the system itself;</sup>

答案2

得分: 0

stateChanged signal发送一个整数,如文档所示,因此行为符合预期。解决方法是转换为Qt.CheckState:

def onCheckboxChange(self, state_int):
    state = Qt.CheckState(state_int)
英文:

The stateChanged signal sends an int as indicated in the docs, so the behavior is as expected. The solution is to convert to Qt.CheckState:

def onCheckboxChange(self, state_int):
    state = Qt.CheckState(state_int)

huangapple
  • 本文由 发表于 2023年1月9日 05:01:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051257.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定