How to connect a QSlider to QDoubleSpinBox

15.9k views Asked by At

I want to connect a QSlider to a QDoubleSpinBox but while the code compiles fine and runs for simple QSpinBox, it doesn't work for QDoubleSpinBox

QSlider *horizontalSlider1 = new QSlider();
QDoubleSpinBox *spinBox1 = new QDoubleSpinBox();

connect(spinBox1, SIGNAL(valueChanged(double)),horizontalSlider1,SLOT(setValue(double)) );
connect(horizontalSlider1,SIGNAL(valueChanged(double)),spinBox1,SLOT(setValue(double)) );
6

There are 6 answers

1
Dave Kilian On BEST ANSWER

QSlider and QDoubleSpinBox take different types of arguments in valueChanged/setValue (QSlider uses ints and QDoubleSpinBox uses doubles, of course). Changing the argument type for the slider's signal and slot might help:

connect(spinBox1, SIGNAL(valueChanged(double)),horizontalSlider1,SLOT(setValue(int)) );
connect(horizontalSlider1,SIGNAL(valueChanged(int)),spinBox1,SLOT(setValue(double)) );

I'm not sure if Qt can automatically handle this type conversion for you; if not, you'll have to define your own slots to call setValue() on the correct object

0
spraff On

You'll have to add your own slot which converts the argument type and emits a signal or updates the slider directly.

0
Dusty Campbell On

As Dave Kilian answered, the signals and slots for QSlider don't use double. Also, Qt 4 does not automatically convert the types; it will not allow you to connect them. So, you will have to write your own conversion slot which updates the value of the other item.

0
Abhijeet Bhilare On

Hope this could help you.

#include <QApplication>
#include <QtGui>
#include <QVBoxLayout>
#include <QSlider>
#include <QLabel>

class DoubleSlider : public QSlider {
    Q_OBJECT

public:
    DoubleSlider(QWidget *parent = 0) : QSlider(parent) {
        connect(this, SIGNAL(valueChanged(int)),
            this, SLOT(notifyValueChanged(int)));
    }

signals:
    void doubleValueChanged(double value);

public slots:
    void notifyValueChanged(int value) {
        double doubleValue = value / 10.0;
        emit doubleValueChanged(doubleValue);
    }
};

class Test : public QWidget {
    Q_OBJECT
public:
    Test(QWidget *parent = 0) : QWidget(parent),
        m_slider(new DoubleSlider()),
        m_label(new QLabel())
    {
        m_slider->setOrientation(Qt::Horizontal);
        m_slider->setRange(0, 100);
        QVBoxLayout *layout = new QVBoxLayout(this);
        layout->addWidget(m_slider);
        layout->addWidget(m_label);
        connect(m_slider, SIGNAL(doubleValueChanged(double)),
            this, SLOT(updateLabelValue(double)));
        updateLabelValue(m_slider->value());
    }

public slots:
    void updateLabelValue(double value) {
        m_label->setText(QString::number(value, 'f', 2));
    }

private:
    QSlider *m_slider;
    QLabel *m_label;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Test *wid = new Test();
    wid->show();

    return a.exec();
}

#include "main.moc"
0
Ben Smith On

One catch to syncing a QSlider or QDial to a QDoubleSpinBox is that when the QDoubleSpinBox updates the QDial or QSlider, the QDial or QSlider valueChanged signal will be triggered causing them to update the QDoubleSpinBox in return. This causes an issue where you cannot enter decimal values into the QDoubleSpinBox, because when you enter a decimal ".", the QDial/Slider update overwrites the decimal, blocking you from entering the rest of the decimal value.

To fix this, have each input widget check if their value already matches the value in the widget they are writing to, and if they do, then do not update the value. Here is an example of a function that allows a QDial and QDoubleSpinBox to update each other:

    def syncDialAndSpinbox(self, widget_in, widget_out):
        if isinstance(widget_in, QtWidgets.QDial):
            value =  float(widget_in.value())*100.0/float(widget_in.maximum())
            out_value = widget_out.value()
        else:
            value = round(widget_in.value()*widget_out.maximum()/100)
            out_value = widget_out.value()

        if value != out_value:
            widget_out.setValue(value)

In this example, the QDoubleSpinBox is a percentage (0.0-100.0) and the QDial has 100,000 steps to support a float output of percentages to three decimal places (0.000% to 100.000%).

0
kjyv On

There is some example code on how to create your own slots and emit signals in this very similar question:

use a created vector as range for QDoubleSpinBox and QSlider