Python 2.7 为什么QSpinBox跳跃两倍于步长值
我有一个简单的pythonqt应用程序,我想通过matplotlib动态地绘制一些东西。我试着按照和的指示去做。除了一件事,我的spinbox在鼠标点击时更新了两次,我不明白为什么。嗯,在开发过程中,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调
值发生了变化。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_())