带有刻度文本标签的Qt滑块小部件

15
我正在寻找类似于QSlider的Qt控件,但支持文本刻度标签,就像这样:example widget 我将使用此控件作为模式切换器。你有遇到过类似的控件吗?
3个回答

19

我会使用以下附有 QLabelQSlider 来完成。请注意,您可能需要自己进行微调和调整。

main.cpp

#include <QMainWindow>
#include <QApplication>
#include <QGridLayout>
#include <QSlider>
#include <QLabel>

class MainWindow Q_DECL_FINAL : public QMainWindow
{
    Q_OBJECT
    public:
        explicit MainWindow(QWidget *parent = Q_NULLPTR) : QMainWindow(parent)
        {
            QSlider *slider = new QSlider(Qt::Horizontal, this);
            slider->setRange(1, 4);
            slider->setSingleStep(1);
            QLabel *label1 = new QLabel("Novice", this);
            QLabel *label2 = new QLabel("Intermediate", this);
            QLabel *label3 = new QLabel("Advanced", this);
            QLabel *label4 = new QLabel("Expert", this);
            QGridLayout *layout = new QGridLayout;
            layout->addWidget(slider, 0, 0, 1, 4);
            layout->addWidget(label1, 1, 0, 1, 1);
            layout->addWidget(label2, 1, 1, 1, 1);
            layout->addWidget(label3, 1, 2, 1, 1);
            layout->addWidget(label4, 1, 3, 1, 1);
            setLayout(layout);
        }
};

#include "main.moc"

int main(int argc, char **argv)
{
    QApplication application(argc, argv);
    MainWindow mainWindow;
    mainWindow.show();
    return application.exec();
}

main.pro

TEMPLATE = app
TARGET = main
QT += widgets
SOURCES += main.cpp

构建与运行

qmake && make && ./main

3

你可以在git中使用我扩展的QSlider类。


1
干得好,但与Ipapp的垂直滑块答案相同的问题。刻度标签与刻度不对齐。 - brahmin
@brahmin,你提到的问题可以很容易地通过在网格中使用两倍的列来解决,将滑块从第一列(而不是第0列)延伸到右侧第二个(而不是最右边),然后将每个标签跨越两列,最后对它们使用Qt :: AlignHCenter。如果有人感兴趣,我可以发布我的修改版@Ipapp的代码,以解决这个问题。 - mvidelgauz

2

我有类似的需求,最终通过重写paintEvent来解决它。这是一个PyQt的解决方案:


class Slider(QSlider):
    """Slider with labels (instead of tick marks) along each available position"""

    def __init__(self, parent=None):
        super(Slider, self).__init__(parent)
        # this decides the range and the labels placed along the slider
        self.values = ['one', 'two', 'three', 'four', 'five']
        self.setOrientation(Qt.Horizontal)
        self.setTickInterval(1)
        self.setTickPosition(QSlider.NoTicks)
        self.setSingleStep(1)
        self.setRange(0, len(self.values) - 1)
        self.setValue(0)

    def paintEvent(self, event):
        QSlider.paintEvent(self, event)

        rect = self.geometry()
        curr_value = str(self.value() / 1000.00)
        round_value = round(float(curr_value), 2)
        # start painter
        painter = QPainter(self)
        painter.setPen(QPen(Qt.black))

        font_metrics = QFontMetrics(self.font())
        font_width = font_metrics.boundingRect(str(round_value)).width()

        for index, value in enumerate(self.values):
            print(index, value)
            # first and last position need a slightly different offset so the text doesn't get cut
            if index == 0:
                # first position
                pos = QStyle.sliderPositionFromValue(self.minimum(), self.maximum(), index, self.width())
                painter.drawText(QPoint(pos, rect.height()), value)
            elif index == len(self.values) - 1:
                # last position
                pos = QStyle.sliderPositionFromValue(self.minimum(), self.maximum(), index, self.width())
                painter.drawText(QPoint(pos - font_width, rect.height()), value)
            else:
                pos = QStyle.sliderPositionFromValue(self.minimum(), self.maximum(), index, self.width())
                painter.drawText(QPoint(pos - font_width / 2.0, rect.height()), value)


最后看起来像这样:

enter image description here


对我来说有效。但是为了使标签位置更精确,我使用了pixelMetric。C++:QStyleOptionSlider slider; initStyleOption(&slider);const int available = style()->pixelMetric(QStyle::PM_SliderSpaceAvailable, &slider, this);const int fudge = style()->pixelMetric(QStyle::PM_SliderLength, &slider, this) / 2;const int pos = QStyle::sliderPositionFromValue(minimum(), maximum(), i, available) + fudge; - yrHeTateJlb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接