我有一个简单的python qt应用程序,我想通过matplotlib动态绘制一些东西。我试图按照this和that这样的说明操作。它按预期工作除了一件事,我的spinbox在点击鼠标时更新两次,我不明白为什么。好吧,在开发期间valueChanged.connect()
工作正常,直到我达到某一点。然后调用update_figure()
两次,显示的值跳过两次而不是所需的值。我试着做一个最小的工作示例,你在下面找到。如果sleep
中没有update_figue
命令,我的旋转框行为正常,sleep
会调用两次,值会跳过两次,延迟时间为sleep
。
为什么sleep
中的update_figure
会影响旋转框,或者这里发生了什么?这是我构建connect()
的方式吗?
BTW:我在滑块上观察到了相同的行为。
干杯
(我认为这不重要,但这是在openSuse Leap上)
编辑:我甚至可以让这个例子变得更简单"。
from PyQt5.uic import loadUiType
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
from time import sleep
Ui_MainWindow, QMainWindow = loadUiType('main.ui')
class Main(QMainWindow, Ui_MainWindow):
def __init__(self, ):
super(Main, self).__init__()
self.setupUi(self)
self.spinBox_dac.valueChanged.connect(self.update_figure)
def update_figure(self):
##### The following line makes the difference!
sleep(1) #####################################
##### why?
print "damn...once or twice?"
return
if __name__ == '__main__':
app = QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())
这是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 :(得分:2)
sleep()
来电阻止qt处理鼠标释放,QSpinBox
&#34;认为&#34;按下鼠标足够长的时间再次增加/减少值(自动重复)。
请参阅https://bugreports.qt.io/browse/QTBUG-33128
解决方案可能是:
def update_figure(self):
for _ in xrange(10):
QApplication.processEvents()
sleep(0.1)
print "Only once :-)"
无论如何,在执行长时间操作时阻止UI并不是一个好习惯,通常会将工作委托给另一个线程。
这会影响Qt4
和Qt5
两者,但行为略有不同。
没有setAutoRepeat
,因为在QAbstrectSpinBox
中,此行为是使用样式实现的,而QAbstractButton
中的行为是使用计时器实现的。
解决这个问题的方法是创建一个ProxyStyle
并设置一个非常长的&#34;自动重复&#34;间隔
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_())