带刻度标签的Python PyQt4滑块

带刻度标签的Python PyQt4滑块,python,pyqt4,Python,Pyqt4,我是PyQt4新手,我正在用QSlider制作gui 默认情况下,QSlider不会显示刻度的值。我搜索了一下,没有找到一个简单的方法来做这件事,那么这是可能的还是我必须手工做呢?遗憾的是,没有简单的方法来做这件事。您必须手动进行。我也必须这么做,这样你才能得到我的实现。考虑到我只重新实现了我所需要的,我对对齐进行了一些黑客攻击,valueChanged()API表现出非常不同的行为 from PyQt4 import QtCore from PyQt4.QtGui import QSlider

我是PyQt4新手,我正在用QSlider制作gui


默认情况下,QSlider不会显示刻度的值。我搜索了一下,没有找到一个简单的方法来做这件事,那么这是可能的还是我必须手工做呢?

遗憾的是,没有简单的方法来做这件事。您必须手动进行。我也必须这么做,这样你才能得到我的实现。考虑到我只重新实现了我所需要的,我对对齐进行了一些黑客攻击,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)

我已经制定了一个解决方案,处理添加标签到滑块,在垂直或水平方向

结果截图:

代码在这里(请注意,PyQt4和PyQT5之间存在一些导入更改)

导入系统 从PyQt5导入QtWidgets 从PyQt5.QtGui导入QPainter 从PyQt5.QtWidgets导入QStyle、QStyleOptionSlider 从PyQt5.QtCore导入QRect、QPoint、Qt 类LabeledSlider(qtwidts.QWidget): 定义初始(自身、最小、最大、间隔=1、方向=Qt.水平、, 标签=无,父项=无): super(LabeledSlider,self)。\uuuuu init\uuuuuuuuuu(父项=父项) 级别=范围(最小、最大+间隔、间隔) 如果标签不是“无”: 如果不存在(标签,(元组,列表)): 引发异常(“是列表或元组”) 如果len(标签)!=len(级别): 引发异常(“的大小与级别不匹配。”) self.levels=list(zip(级别、标签)) 其他: self.levels=list(zip(levels,map(str,levels))) 如果方向==Qt.Horizontal: self.layout=qtwidts.QVBoxLayout(self) elif方向==Qt.Vertical: self.layout=qtwidts.QHBoxLayout(self) 其他: 引发异常(“错误”) #为打印标签提供一些空间 自左_边距=10 自顶边距=10 自右翼距=10 自底_裕度=10 self.layout.setContentsMargins(self.left_边距、self.top_边距、, self.right\u margin,self.bottom\u margin) self.sl=qtwidts.QSlider(方向,self) self.sl.setMinimum(最小值) self.sl.setMaximum(最大值) self.sl.setValue(最小值) 如果方向==Qt.Horizontal: self.sl.setTickPosition(下面是qtwidts.QSlider.ticksBlow) self.sl.setMinimumWidth(300)#只是为了便于阅读 其他: self.sl.setTickPosition(qtwidts.QSlider.TicksLeft) self.sl.setMinimumHeight(300)#只是为了便于阅读 self.sl.setTickInterval(间隔) 自整定单步(1) self.layout.addWidget(self.sl) def喷漆事件(自身,e): 超级(贴标激光雷达,自我)。绘画事件(e) style=self.sl.style() 油漆工=油漆工(自身) st_滑块=QStyleOptionSlider() st_slider.initFrom(self.sl) st_slider.orientation=self.sl.orientation() 长度=style.pixelMetric(QStyle.PM_滑块长度、st_滑块、self.sl) 可用=style.pixelMetric(QStyle.PM_SliderSpaceAvailable,st_slider,self.sl) 对于v,自我水平的v_str: #获取标签的大小 rect=painter.drawText(QRect(),Qt.TextDontPrint,v_str) 如果self.sl.orientation()==Qt.Horizontal: #因此,我假设偏移量是滑块长度的一半 #+长度//2 x_loc=QStyle.sliderPositionFromValue(self.sl.minimum(), self.sl.max(),v,可用)+长度//2 #文本的左边界=中间-文本宽度的一半+L_边距 left=x_loc-rect.width()//2+self.left_边距 bottom=self.rect().bottom() #如果剪切,请放大边距 如果v==self.sl.minimum():
如果是leftI,我的意思是我有一个介于1-10之间的值范围,我希望它在刻度下方可见,这样我就可以轻松地选择我想要的值
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_())