1

I have some horizontal QSliders in my Qt application with 4-5 ticks marks. How can I add QLabels above the slider ticks to reflect the value at each of the ticks?

I suspect the best way to do this is to create a subclass of QSlider and override the paintEvent() method like this answer describes. But how would I add QLabels based on the position of the ticks?

For clarification:

I am looking for Text labels at each tick, ie if I have a slider that goes from 0 - 100 with 4 ticks, the ticks would have "0", "25", "50", and "100" above them, respectively. Your solution is still helpful, I believe I should be able to rework it using this->geometry to get the coordinates and dividing by # of ticks (which I believe I can calculate with (max - min/tick interval)

Django
  • 361
  • 2
  • 15

1 Answers1

1

There is an implementation in PySide that works properly. It displays the rounded value of each tick, you can replace it with whatever text you need by updating the QPainter::drawText callback.

Long time ago, I did port that code to C++. This is the interesting part:

void MySlider::painEvent(...) {
    QSlider::paintEvent(self, event)

    auto round_value = std::floor(value());

    auto painter = new QPainter(this);
    painter->setPen(QPen(Qt::white));

    auto font_metrics = QFontMetrics(this->font());
    auto font_width = font_metrics.boundingRect(QString::number(round_value)).width();
    auto font_height = font_metrics.boundingRect(QString::number(round_value)).height();


    auto rect = w.geometry();
    if (this->orientation() == Qt::Horizontal) {
        auto horizontal_x_pos = rect.width() - font_width - 5;
        auto horizontal_y_pos = rect.height() * 0.75;
        painter->drawText(QPoint(horizontal_x_pos, horizontal_y_pos), 
                          QString::number(round_value));

    } else if (this->orientation() == Qt::Vertical) {
        auto vertical_x_pos = rect.width() - font_width - 5;
        auto vertical_y_pos = rect.height() * 0.75;
        painter->drawText(QPoint(rect.width() / 2.0 - font_width / 2.0, rect.height() - 5), 
                          QString::number(round_value));
    } else {
        return;
    }

    painter->drawRect(rect)
}
mohabouje
  • 3,867
  • 2
  • 14
  • 28
  • interesting. I see this is writing the current Slider value, which is not exactly what I am looking for. I am looking for Text labels at each tick, ie if I have a slider that goes from 0 - 100 with 4 ticks, the ticks would have "0", "25", "50", and "100" above them, respectively. Your solution is still helpful, I believe I should be able to rework it using this->geometry to get the coordinates and dividing by # of ticks (which I believe I can calculate with (max - min/tick interval). – Django Apr 03 '19 at 14:43
  • this is very helpful thanks. I suggest in place of `auto painter = new QPainter(this);` use `QPainter painter(this);` and replace all `painter->[x]` with `painter.[x]` as I was getting a flood of error messages `QBackingStore::endPaint() called with active painter; did you forget to destroy it or call QPainter::end() on it?` – Akasha May 04 '20 at 12:42