我是PyQt4的新手,我正在使用QSlider制作一个gui。
默认情况下,QSlider不会显示您的刻度值。我搜索并没有找到一个简单的方法来做到这一点,所以它可能还是我必须手工制作?
答案 0 :(得分:1)
可悲的是,没有简单的方法可以做到这一点。你必须手动完成它。我也必须这样做,所以你可以实现我的实现。考虑到我只重新实现了我需要的东西,我在一些方面进行了修改,并且valueChanged()API表现出了截然不同的行为。
from PyQt4 import QtCore
from PyQt4.QtGui import QSlider, QWidget, QVBoxLayout, QHBoxLayout, QLabel
__author__ = 'Andres'
class QCustomSlider(QWidget):
def __init__(self, sliderOrientation=None):
super(QCustomSlider, self).__init__()
self._slider = QSlider(sliderOrientation)
self.setLayout(QVBoxLayout())
self._labelTicksWidget = QWidget(self)
self._labelTicksWidget.setLayout(QHBoxLayout())
self._labelTicksWidget.layout().setContentsMargins(0, 0, 0, 0)
self.layout().addWidget(self._slider)
self.layout().addWidget(self._labelTicksWidget)
def setTickLabels(self, listWithLabels):
lengthOfList = len(listWithLabels)
for index, label in enumerate(listWithLabels):
label = QLabel(str(label))
label.setContentsMargins(0, 0, 0, 0)
if index > lengthOfList/3:
label.setAlignment(QtCore.Qt.AlignCenter)
if index > 2*lengthOfList/3:
label.setAlignment(QtCore.Qt.AlignRight)
self._labelTicksWidget.layout().addWidget(label)
def setRange(self, mini, maxi):
self._slider.setRange(mini, maxi)
def setPageStep(self, value):
self._slider.setPageStep(value)
def setTickInterval(self, value):
self._slider.setTickInterval(value)
def setTickPosition(self, position):
self._slider.setTickPosition(position)
def setValue(self, value):
self._slider.setValue(value)
def onValueChangedCall(self, function):
self._slider.valueChanged.connect(function)
答案 1 :(得分:0)
我已经提出了一种解决方案,该解决方案涉及在垂直或水平方向上向滑块添加标签。
结果截图:
此处的代码(请注意,PyQt4和5之间有一些导入更改)。
import sys
from PyQt5 import QtWidgets
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QStyle, QStyleOptionSlider
from PyQt5.QtCore import QRect, QPoint, Qt
class LabeledSlider(QtWidgets.QWidget):
def __init__(self, minimum, maximum, interval=1, orientation=Qt.Horizontal,
labels=None, parent=None):
super(LabeledSlider, self).__init__(parent=parent)
levels=range(minimum, maximum+interval, interval)
if labels is not None:
if not isinstance(labels, (tuple, list)):
raise Exception("<labels> is a list or tuple.")
if len(labels) != len(levels):
raise Exception("Size of <labels> doesn't match levels.")
self.levels=list(zip(levels,labels))
else:
self.levels=list(zip(levels,map(str,levels)))
if orientation==Qt.Horizontal:
self.layout=QtWidgets.QVBoxLayout(self)
elif orientation==Qt.Vertical:
self.layout=QtWidgets.QHBoxLayout(self)
else:
raise Exception("<orientation> wrong.")
# gives some space to print labels
self.left_margin=10
self.top_margin=10
self.right_margin=10
self.bottom_margin=10
self.layout.setContentsMargins(self.left_margin,self.top_margin,
self.right_margin,self.bottom_margin)
self.sl=QtWidgets.QSlider(orientation, self)
self.sl.setMinimum(minimum)
self.sl.setMaximum(maximum)
self.sl.setValue(minimum)
if orientation==Qt.Horizontal:
self.sl.setTickPosition(QtWidgets.QSlider.TicksBelow)
self.sl.setMinimumWidth(300) # just to make it easier to read
else:
self.sl.setTickPosition(QtWidgets.QSlider.TicksLeft)
self.sl.setMinimumHeight(300) # just to make it easier to read
self.sl.setTickInterval(interval)
self.sl.setSingleStep(1)
self.layout.addWidget(self.sl)
def paintEvent(self, e):
super(LabeledSlider,self).paintEvent(e)
style=self.sl.style()
painter=QPainter(self)
st_slider=QStyleOptionSlider()
st_slider.initFrom(self.sl)
st_slider.orientation=self.sl.orientation()
length=style.pixelMetric(QStyle.PM_SliderLength, st_slider, self.sl)
available=style.pixelMetric(QStyle.PM_SliderSpaceAvailable, st_slider, self.sl)
for v, v_str in self.levels:
# get the size of the label
rect=painter.drawText(QRect(), Qt.TextDontPrint, v_str)
if self.sl.orientation()==Qt.Horizontal:
# I assume the offset is half the length of slider, therefore
# + length//2
x_loc=QStyle.sliderPositionFromValue(self.sl.minimum(),
self.sl.maximum(), v, available)+length//2
# left bound of the text = center - half of text width + L_margin
left=x_loc-rect.width()//2+self.left_margin
bottom=self.rect().bottom()
# enlarge margins if clipping
if v==self.sl.minimum():
if left<=0:
self.left_margin=rect.width()//2-x_loc
if self.bottom_margin<=rect.height():
self.bottom_margin=rect.height()
self.layout.setContentsMargins(self.left_margin,
self.top_margin, self.right_margin,
self.bottom_margin)
if v==self.sl.maximum() and rect.width()//2>=self.right_margin:
self.right_margin=rect.width()//2
self.layout.setContentsMargins(self.left_margin,
self.top_margin, self.right_margin,
self.bottom_margin)
else:
y_loc=QStyle.sliderPositionFromValue(self.sl.minimum(),
self.sl.maximum(), v, available, upsideDown=True)
bottom=y_loc+length//2+rect.height()//2+self.top_margin-3
# there is a 3 px offset that I can't attribute to any metric
left=self.left_margin-rect.width()
if left<=0:
self.left_margin=rect.width()+2
self.layout.setContentsMargins(self.left_margin,
self.top_margin, self.right_margin,
self.bottom_margin)
pos=QPoint(left, bottom)
painter.drawText(pos, v_str)
return
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
frame=QtWidgets.QWidget()
ha=QtWidgets.QHBoxLayout()
frame.setLayout(ha)
w = LabeledSlider(1, 10 , 1, orientation=Qt.Horizontal)
ha.addWidget(w)
frame.show()
sys.exit(app.exec_())