Python 2.7 为什么QSpinBox跳跃两倍于步长值

Python 2.7 为什么QSpinBox跳跃两倍于步长值,python-2.7,pyqt5,Python 2.7,Pyqt5,我有一个简单的pythonqt应用程序,我想通过matplotlib动态地绘制一些东西。我试着按照和的指示去做。除了一件事,我的spinbox在鼠标点击时更新了两次,我不明白为什么。嗯,在开发过程中,值发生了变化。connect()工作得很好,直到我达到某一点。然后调用了两次update\u figure(),显示的值跳转了两次,而不是所需的值。我试着做一个最低限度的工作示例,你可以在下面找到。如果没有update\u figue中的sleep命令,我的spinbox将正常运行,如果sleep调

我有一个简单的pythonqt应用程序,我想通过matplotlib动态地绘制一些东西。我试着按照和的指示去做。除了一件事,我的spinbox在鼠标点击时更新了两次,我不明白为什么。嗯,在开发过程中,
值发生了变化。connect()
工作得很好,直到我达到某一点。然后调用了两次
update\u figure()
,显示的值跳转了两次,而不是所需的值。我试着做一个最低限度的工作示例,你可以在下面找到。如果没有
update\u figue
中的
sleep
命令,我的spinbox将正常运行,如果
sleep
调用它两次,值将跳转两次,延迟由
sleep
给出

为什么
update\u figure
中的
sleep
会影响spinbox,或者这里发生了什么?这是我构建
connect()
的方式吗

顺便说一句:我在滑块上观察到了相同的行为

干杯

(我认为这无关紧要,但这是在openSuse Leap上)

编辑:我可以让这个例子“更简单”

以下是main.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>185</width>
    <height>107</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Fixed" vsizetype="Maximum">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="maximumSize">
   <size>
    <width>1100</width>
    <height>905</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>mini</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QSpinBox" name="spinBox_dac">
    <property name="geometry">
     <rect>
      <x>80</x>
      <y>40</y>
      <width>61</width>
      <height>28</height>
     </rect>
    </property>
    <property name="minimum">
     <number>3</number>
    </property>
    <property name="maximum">
     <number>20</number>
    </property>
    <property name="singleStep">
     <number>1</number>
    </property>
    <property name="value">
     <number>4</number>
    </property>
   </widget>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

主窗口
0
0
185
107
0
0
1100
905
迷你
80
40
61
28
3.
20
1.
4.
sleep()调用prevent qt处理鼠标释放,而
QSpinBox
认为鼠标被按下的时间足够长,可以再次增加/减少值(自动重复)

解决办法可以是:

def update_figure(self):
    for _ in xrange(10):
        QApplication.processEvents() 
        sleep(0.1)
    print "Only once :-)"
无论如何,在执行长时间操作时阻塞UI不是一个好的做法,工作通常被委托给另一个线程

编辑 这会同时影响Qt4和Qt5,但其行为有点不同

没有
setAutoRepeat
,因为在
qabstrctspinbox
中,此行为是使用样式实现的,而在
QAbstractButton
中,此行为是使用计时器实现的

解决方法是创建一个
ProxyStyle
,并设置一个很长的“自动重复”间隔

sleep()

解决办法可以是:

def update_figure(self):
    for _ in xrange(10):
        QApplication.processEvents() 
        sleep(0.1)
    print "Only once :-)"
无论如何,在执行长时间操作时阻塞UI不是一个好的做法,工作通常被委托给另一个线程

编辑 这会同时影响Qt4和Qt5,但其行为有点不同

没有
setAutoRepeat
,因为在
qabstrctspinbox
中,此行为是使用样式实现的,而在
QAbstractButton
中,此行为是使用计时器实现的

解决方法是创建一个
ProxyStyle
,并设置一个很长的“自动重复”间隔


谢谢你提供这个有趣的信息。这是一个bug还是一个特性?更重要的是,为什么QSpinBox没有setAutoRepeat()方法,而不是按钮,因为它显然有一个autorepeat?或者换句话说,我如何关闭它?不幸的是,这个耗时的过程不能像您的答案中那样拆分为for循环。将此计算推到另一个线程中是否是一个好主意,这是一个不同的问题。这只是一个qt5问题?不被视为错误,如果您看到错误报告,它标记为
无效
,请查看更新的答案。很好,5.4中似乎没有QRoxyStyle;所以我需要先更新到5.7。然后我会摆弄这个变通方法。@Ceppo93。PyQt不是Qt。
QProxyStyle
类仅在PyQt-5.5中添加(在PyQt4中可能永远不受支持)。感谢提供这些有趣的信息。这是一个bug还是一个特性?更重要的是,为什么QSpinBox没有setAutoRepeat()方法,而不是按钮,因为它显然有一个autorepeat?或者换句话说,我如何关闭它?不幸的是,这个耗时的过程不能像您的答案中那样拆分为for循环。将此计算推到另一个线程中是否是一个好主意,这是一个不同的问题。这只是一个qt5问题?不被视为错误,如果您看到错误报告,它标记为
无效
,请查看更新的答案。很好,5.4中似乎没有QRoxyStyle;所以我需要先更新到5.7。然后我会摆弄这个变通方法。@Ceppo93。PyQt不是Qt。
QProxyStyle
类仅在PyQt-5.5中添加(在PyQt4中可能永远不受支持)。
from PyQt5.uic import loadUiType
from PyQt5.QtWidgets import QApplication, QMainWindow, QProxyStyle, QStyle
import sys
from time import sleep

Ui_MainWindow, QMainWindow = loadUiType('main.ui')


class CustomStyle(QProxyStyle):
    def styleHint(self, hint, option=None, widget=None, returnData=None):
        if hint == QStyle.SH_SpinBox_KeyPressAutoRepeatRate:
            return 10**10
        elif hint == QStyle.SH_SpinBox_ClickAutoRepeatRate:
            return 10**10
        elif hint == QStyle.SH_SpinBox_ClickAutoRepeatThreshold:
            # You can use only this condition to avoid the auto-repeat,
            # but better safe than sorry ;-)
            return 10**10
        else:
            return super().styleHint(hint, option, widget, returnData)


class Main(QMainWindow, Ui_MainWindow):
    def __init__(self, ):
        super(Main, self).__init__()
        self.setupUi(self)
        self.spinBox_dac.setStyle(CustomStyle())
        self.spinBox_dac.valueChanged.connect(self.update_figure)

    def update_figure(self):
        sleep(1)
        print "Only once!"


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Main()    
    main.show()
    sys.exit(app.exec_())