当我按下 QSpinbox 中的箭头时,如何防止双 valueChanged 事件?

Posted

技术标签:

【中文标题】当我按下 QSpinbox 中的箭头时,如何防止双 valueChanged 事件?【英文标题】:How do I prevent double valueChanged events when I press the arrows in a QSpinbox? 【发布时间】:2017-01-10 12:33:47 【问题描述】:

可能是 Qt 错误,也可能是我的应用程序中的错误,我希望有人可以帮助我诊断此问题。

我正在构建一个带有使用 qtdesigner 和 pyuic5 构建的界面的 PyQt5 应用程序。

我必须在我的窗口中QSpinBox 小部件,我连接到这样的两种方法:

self.img1IndexBox.valueChanged.connect(self.changeImage1)
self.img2IndexBox.valueChanged.connect(self.changeImage2)

在应用程序中似乎一切正常,除了一件事:如果我将鼠标滚动到微调框上,我可以让它增加值。如果我用文本更改值,一切正常。如果我在微调框上使用键盘箭头,它工作正常。但是,如果我单击旋转框中的向上或向下箭头,我会得到两个 changeValue 事件,一个双倍增量。就像我点击了两次一样。事实上,它甚至可以从动画中看出它正在为按下创建一个事件,并在按钮返回时创建另一个事件。

这可能只是一个库错误,或者是什么导致我的程序出现这种情况?我该如何调试呢?

【问题讨论】:

【参考方案1】:

您可以通过将 spinbox enable 设置为 false 来防止这种双重情况。 然后在处理大数据后使其为true。

点击向上/向下箭头时 on_value 已更改 ui->spinbox->setEnabled(false);

然后在函数 on_valuechanged 结束之前设置为 true。 ui->spinbox->setEnabled(true);

【讨论】:

【参考方案2】:

显然问题是事件触发了一个很长的例程,这延迟了“按钮释放”事件,并且有足够的时间让系统认为用户实际上正在按住按钮,产生更多事件......但是我仍然有兴趣了解什么是一个很好的步行。是否有一种不错的 pyqt-onic 方法来为该方法启动线程?

http://www.qtcentre.org/archive/index.php/t-43078.html

【讨论】:

大多数解决方案都涉及创建一个完整的 QObject 来处理这个问题,但我正在更新 matplotlib FigureCanvasQTAgg 中的绘图,这需要很长时间。因此,最好弄清楚如何创建一个可以以更自然的方式做到这一点的小部件。 所以画布实际上有同步 draw() 和异步 draw_idle() 方法,使用这可能是要走的路。很抱歉发布这样的问题和答案,我希望将这些信息放在一起可能对某人有用。【参考方案3】:

而不是使用valueChanged.connect 使用editingFinished.connect 它将确保仅在提供值后调用该函数。

PyQt

import sys

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDoubleSpinBox, QApplication, QMainWindow, QWidget, QVBoxLayout, QLabel, QSpinBox


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    # def valueChanged(self, value):
    #     print(value)
    def valueChanged(self):
        print(f"Value changed new value is : self.spinBox.value()")

    def initUI(self):
        self.setGeometry(0, 0, 200, 100)
        self.layout = QVBoxLayout()
        self.spinBox = QSpinBox()
        self.spinBox.setAlignment(Qt.AlignCenter)
        self.spinBox.setRange(0, 1000)
        # self.spinBox.valueChanged.connect(self.valueChanged)
        self.spinBox.editingFinished.connect(self.valueChanged)
        self.layout.addWidget(self.spinBox)
        self.setLayout(self.layout)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = MainWindow()
    main.show()
    sys.exit(app.exec())

PySide

import sys

from PySide6.QtWidgets import QDoubleSpinBox, QApplication, QMainWindow, QWidget, QVBoxLayout, QLabel, QSpinBox
from PySide6.QtGui import Qt


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    # def valueChanged(self, value):
    #     print(value)
    def valueChanged(self):
        print(f"Value changed new value is : self.spinBox.value()")

    def initUI(self):
        self.setGeometry(0, 0, 200, 100)
        self.layout = QVBoxLayout()
        self.spinBox = QSpinBox()
        self.spinBox.setAlignment(Qt.AlignCenter)
        self.spinBox.setRange(0, 1000)
        # self.spinBox.valueChanged.connect(self.valueChanged)
        self.spinBox.editingFinished.connect(self.valueChanged)
        self.layout.addWidget(self.spinBox)
        self.setLayout(self.layout)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = MainWindow()
    main.show()
    sys.exit(app.exec())

【讨论】:

以上是关于当我按下 QSpinbox 中的箭头时,如何防止双 valueChanged 事件?的主要内容,如果未能解决你的问题,请参考以下文章

我希望我的引导轮播在按下键盘左右箭头时滑动

如何检测是不是按下了向上按钮

当我按下表格中的按钮时如何设置输入值?这里我使用 laravel 5.8

设置活动如何使用顶部的箭头向后导航

SwiftUI:当我按下按钮时如何打开(App-)电话设置?

当我按下要检查的项目中的按钮以删除此项目时,如何自动选择正确的列表框项目?