Placing a label next to a slider handle



  • Hi,
    I've been trying to place a label with the value next to the slider handle, in a way that it moves with it. I've tried the following code but the label is not positioned exactly by the handle.
    @
    #include "widget.h"

    Widget::Widget(QWidget *parent)
    : QWidget(parent)
    {
    main_layout = new QHBoxLayout(this);
    main_layout->setContentsMargins(0, 0, 0, 0);
    main_layout->setMargin(0);
    main_layout->setSpacing(0);
    slider = new QSlider(Qt::Vertical,this);
    slider->setMaximum(100);
    slider->setMinimum(0);
    slider->setTracking(true);
    label= new QLabel(this);
    label->setText("label");
    main_layout->addWidget(slider,0,Qt::AlignLeft);
    main_layout->addWidget(label,0,Qt::AlignBottom);
    updateLabel(0);
    setLayout(main_layout);
    connect(slider, SIGNAL(valueChanged(int)), this, SLOT (updateLabel(int)));
    }

    void Widget::updateLabel(int value)
    {
    int height0 = (100-value)*(slider->height())/100;
    int height= QStyle::sliderPositionFromValue(0,100,slider->value(),slider->height(), true);
    label->move(slider->width(), height);
    }

    void Widget::resizeEvent(QResizeEvent* ev)
    {
    updateLabel(slider->sliderPosition());
    }

    Widget::~Widget()
    {
    }
    @

    It's ok if the slider is close to the top, but it goes wrong as I slide it down. Here are some screenshots:
    !http://i.imgur.com/gTrlC3k.png(a)!
    !http://i.imgur.com/f9Lx4UQ.png(b)!

    Is there a simple way to do this? Or will I have to reimplement the paintEvent?


  • Moderators

    You are going to need some better math to do this.

    I ran your code and played around with height a bit using a QPushButton so I could see the edges.

    What it looks like is when you are calling move() it is putting it exactly where it should. The top left of the widget is drawn at the width, height you specify in your function.

    Unfortunately that value is off depending on where you are in the slider position. For easy math lets assume widget height is 100. If you are at slider value of 100 (max) your height variable would be 0. This is great and works fine.

    However, if you are at value 0 (min) your height variable is 100, this won't work. This means the label widget will be drawn at height 100 which is the maximum size of the window. So you will not be able to see any of the widget.

    This is also why it doesn't stay right next to the grabber. The grabber size is also not in your calculation. So at 50 value of the slider (dead middle) the label would draw right in the middle of the screen for it's top left. Which is off center from where you expect it to be next to the grabber.

    So that is what is going on... But after many attempts at fixing the math I couldn't get it right. I could get it right when it was 50%, or I could get it right when it was 100%, or right at 0%, but couldn't get it beyond those points in my calculations.

    The main reason this is happening is we don't know the position of the grabber and that is what you are trying to align with. For instance, at 50% if you have:
    @
    label->move(slider->width(), height-(label->height()/2)+1);
    @

    this would center the label exactly on the grabber at 50% value. However it moves up and down wrong just like before. This is because the value of the slider is not the same as the grabber position. Also even if you had grabber position you would still need some math to calculate things when it was at the bottom of the space or the top as centering wouldn't work then.

    Hope that sends you in the right direction. This isn't a Qt thing, Qt is acting like it should, it's a math thing and I couldn't find a good solution in a quick amount of time for you.



  • Try
    @
    int height= QStyle::sliderPositionFromValue(0, 100, value, slider->height() - label->height(), true);
    @



  • I figured it out. And yes I also noticed it was just a math problem.

    The height should be
    @
    int height = label->height()slider->height()/slider->maximum() + (slider->maximum() -label->height()-value)(slider->height()-label->height())/slider->maximum();
    @

    Works perfectly now.



  • [quote author="andreyc" date="1407039781"]Try
    @
    int height= QStyle::sliderPositionFromValue(0, 100, value, slider->height() - label->height(), true);
    @
    [/quote]

    That also works. If I had known earlier I wouldn't have needed to pick up paper and pen to figure out the formula. Haha thanks


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.