我正在开发一个小工具.它有一个表盘和一个滑块,都可以修改相同的数字,尽管我希望滑块的更改率比表盘更高.可以把它看作是微调的表盘.例如,滑块以0.1为单位更改,但刻度盘以0.01为单位更改. 此外,只要我朝一个方向转动,我就想让刻度盘增加或减少数字的值.所以,如果我转完5圈,这个数字将增加50个单位(考虑到刻度盘‘轴’上有100个台阶).
我成功地实现了大部分,但有一个问题,我不知道如何解决它.
刻度盘按我希望的那样工作.它不受限制地转动.它的变化速度也比滑块慢.问题是,只有当我顺时针旋转(增加数字)时,这个速度才有效.
刻度盘增加到0.01,滑块增加到0.1.我可以通过操作刻度盘从1转到1.1(1.01,1.02...),滑块只会移动一次,但是如果我从1.1转回刻度盘,它将直接变为1,然后是0.9(跳过中间的数字).换句话说,只要我顺时针转,刻度盘的速度就会不同.
这就是代码
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout, QDial, QSlider
from PyQt5.QtCore import Qt
class DialWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self._label_number = 0.000
self.label = QLabel(str(self._label_number), self)
self.label.setAlignment(Qt.AlignCenter)
self.dial = QDial(self)
self.dial.setNotchesVisible(True)
self.dial.setWrapping(True)
self.dial.setMinimum(0)
self.dial.setMaximum(100) # 3600 for full revolutions (0-3600 = 0-360 degrees)
self.dial.valueChanged.connect(self.dial_value_changed)
self.slider = QSlider(Qt.Horizontal, self)
self.slider.setMinimum(0)
self.slider.setMaximum(80)
self.slider.valueChanged.connect(self.slider_value_changed)
self._slider_value = self.slider.value()
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.dial)
layout.addWidget(self.slider)
self.dial_value = self.dial.value()
self.setLayout(layout)
@property
def label_number(self):
return self._label_number
@label_number.setter
def label_number(self, number):
print(f' Inside label_number.setter')
if number < 0 or number > 8:
pass
else:
print(f' Changing label_number {self._label_number} --> {number}')
self._label_number = number
#print(f' Changing label text {self.label.text()} --> {str(round(number, 4))}')
self.label.setText(str(round(number, 4)))
print(f' Changing slider value: {self.slider.value()} --> {number * 10.000} ')
print(f'self.slider.setValue({number * 10.000})')
self.slider_number = number * 10.000
self.slider.setValue(self.slider_number)
print(f' Exiting label_number.setter')
def dial_value_changed(self):
print(f'Inside dial_value_changed')
# Get the current value of the dial
dial_delta = self.dial.value() - self.dial_value
print(f'Delta number of the dial: {dial_delta}')
if dial_delta == 1:
print(f'dn = {1/100}')
new_number = self.label_number + 1/100
self.label_number = new_number
elif dial_delta == -1:
print(f'dn = {1/100}')
new_number = self.label_number - 1/100
self.label_number = new_number
elif dial_delta == -100:
print(f'dn = {1/100}')
new_number = self.label_number + 1/100
self.label_number = new_number
elif dial_delta == 99:
print(f'dn = {1/100}')
new_number = self.label_number - 1/100
self.label_number = new_number
#print(f'Setting self.dial_value to {self.dial.value()}')
self.dial_value = self.dial.value()
print(f'Exiting dial_value_changed')
print()
def slider_value_changed(self, value):
print(f' Inside slider_value_changed')
print(f' {self.slider.value()}')
print(f' Value sent {value}')
#print(f' Changing self.label_number {self.label_number} --> {value / 10.0}')
self.label_number = value / 10.000
print(f' Exiting slider_value_changed')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DialWidget()
window.setWindowTitle('Dial Widget')
window.show()
sys.exit(app.exec_())
我添加了 fingerprint ,以便更好地跟踪航站楼的代码.我发现问题出在self.slider.valueChanged.connect(self.slider_value_changed)
线上.该信号仅发送整数(因为滑块的位置以整数为单位工作).
然后,我try 通过添加一个额外的属性来解决这个问题,该属性包含滑块的位置或数量,但它是一个浮点.当我try 这样做时,刻度盘在两个方向上都工作得很好,但是如果我按下它,滑块就不会移动.
class DialWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self._label_number = 0.000
self.label = QLabel(str(self._label_number), self)
self.label.setAlignment(Qt.AlignCenter)
self.dial = QDial(self)
self.dial.setNotchesVisible(True)
self.dial.setWrapping(True)
self.dial.setMinimum(0)
self.dial.setMaximum(100) # 3600 for full revolutions (0-3600 = 0-360 degrees)
self.dial.valueChanged.connect(self.dial_value_changed)
self.slider = QSlider(Qt.Horizontal, self)
self.slider.setMinimum(0)
self.slider.setMaximum(80)
self.slider.valueChanged.connect(self.slider_value_changed)
self._slider_number = self.slider.value()
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.dial)
layout.addWidget(self.slider)
self.dial_value = self.dial.value()
self.setLayout(layout)
@property
def label_number(self):
return self._label_number
@label_number.setter
def label_number(self, number):
print(f' Inside label_number.setter')
if number < 0 or number > 8:
pass
else:
print(f' Changing label_number {self._label_number} --> {number}')
self._label_number = number
#print(f' Changing label text {self.label.text()} --> {str(round(number, 4))}')
self.label.setText(str(round(number, 4)))
print(f' Changing slider value: {self.slider.value()} --> {number * 10.000} ')
print(f'self.slider.setValue({number * 10.000})')
self.slider_number = number * 10.000
self.slider.setValue(self.slider_number)
#self.slider.setValue(number * 10.000)
print(f' Exiting label_number.setter')
@property
def slider_number(self):
return self._slider_number
@slider_number.setter
def slider_number(self, number):
self._slider_number = number
def dial_value_changed(self):
print(f'Inside dial_value_changed')
# Get the current value of the dial
dial_delta = self.dial.value() - self.dial_value
print(f'Delta number of the dial: {dial_delta}')
if dial_delta == 1:
print(f'dn = {1/100}')
new_number = self.label_number + 1/100
self.label_number = new_number
elif dial_delta == -1:
print(f'dn = {1/100}')
new_number = self.label_number - 1/100
self.label_number = new_number
elif dial_delta == -100:
print(f'dn = {1/100}')
new_number = self.label_number + 1/100
self.label_number = new_number
elif dial_delta == 99:
print(f'dn = {1/100}')
new_number = self.label_number - 1/100
self.label_number = new_number
#print(f'Setting self.dial_value to {self.dial.value()}')
self.dial_value = self.dial.value()
print(f'Exiting dial_value_changed')
print()
def slider_value_changed(self, value):
print(f' Inside slider_value_changed')
print(f' {self.slider.value()}')
print(f' Value sent {value}')
#print(f' Changing self.label_number {self.label_number} --> {value / 10.0}')
value = self.slider_number
self.label_number = value / 10.000
#self.slider.setValue(self.slider_value)
print(f' Exiting slider_value_changed')
这就是我试过的.我添加了SLIDER_NUMBER作为属性. 我一整天都在试图解决这个问题.如果另一个大脑能帮助我,我将不胜感激.
EDIT (Possible Solution):个
我设法解决了我的问题,当拨盘被操作(dial_value_changed
)时,我断开了slider.valueChanged
与slider_value_changed
的连接,并在我退出功能后再次连接.这是因为当slider.valueChanged
被呼叫两次时,问题就出现了,第一次是如果数字通过移动刻度盘以0.1个单位改变,则呼叫set_number()
,而set_number()
又再次呼叫slider.valueChanged
.
def dial_value_changed(self):
dial_delta = self.dial.value() - self.dial_value
self.slider.valueChanged.disconnect()
if dial_delta == 1:
new_number = self.number + 1/10000
self.set_number(new_number)
elif dial_delta == -1:
new_number = self.number - 1/10000
self.set_number(new_number)
elif dial_delta == -100:
new_number = self.number + 1/10000
self.set_number(new_number)
elif dial_delta == 99:
new_number = self.number - 1/10000
self.set_number(new_number)
self.dial_value = self.dial.value()
self.slider.valueChanged.connect(self.slider_value_changed)