I'm trying to create a dynamic QSlider that accepts a QVector of integer values and maps them underneath the QSlider relative to what position they represent.
Here's a screenshot of what I have now: My Slider http://dev.kyleswebspace.com/images/QInteractiveSlider.jpg
As you can see, the ticks don't line up with their values. This is one of the issues.
The main issue I'm struggling with though, is that no matter what I change my PADDING value to (see qinteractiveslider.h), the QSlider in my widget remains the same size in relation to the grid of values.
- Why isn't my QGridLayout's arguments providing the correct amount of padding?
- How can I enforce these margins on the QSlider?
- Is there a better way of positioning these labels? I'm open to suggestions.
Here is the code:
qinteractiveslider.h
#ifndef QINTERACTIVESLIDER_H
#define QINTERACTIVESLIDER_H
#include <QtGui/QGridLayout>
#include <QtGui/QLabel>
#include <QtGui/QSlider>
#include <QtGui/QWidget>
class QInteractiveSlider : public QWidget
{
Q_OBJECT
public:
QInteractiveSlider(QVector<int>* values, int min, int max, QWidget *parent = 0, Qt::WFlags flags = 0);
~QInteractiveSlider();
private:
static const int GRID_WIDTH = 10000;
static const int PADDING = GRID_WIDTH / 3;
QGridLayout* m_layout;
QSlider* m_slider;
QVector<int>* m_values;
};
qinteractiveslider.cpp
#include "qinteractiveslider.h"
QInteractiveSlider::QInteractiveSlider(QVector<int>* values, int min, int max, QWidget *parent, Qt::WFlags flags)
: QWidget(parent, flags)
{
m_layout = new QGridLayout();
m_layout->setSpacing(0);
m_slider = new QSlider(Qt::Horizontal);
m_slider->setTickInterval(25);
m_slider->setTickPosition(QSlider::TicksBelow);
m_layout->addWidget(m_slider, 0, PADDING, 1, GRID_WIDTH - PADDING, Qt::AlignBottom);
//populate bottom row with labels
QVector<int>::Iterator iterator = values->begin();
while(iterator != values->end()) {
//place the label at the relative position under the slider
int columnIndex = ((double)*iterator / (double)max) * (double)GRID_WIDTH;
QString labelString = QString::number(*iterator);
QLabel* label = new QLabel(labelString);
m_layout->addWidget(label, 1, columnIndex, 1, 1, Qt::AlignTop);
iterator++;
}
this->setLayout(m_layout);
}
QInteractiveSlider::~QInteractiveSlider()
{
}
main.cpp
#include "qinteractiveslid开发者_StackOverflow中文版er.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QVector<int>* testVector = new QVector<int>();
testVector->append(0);
testVector->append(50);
testVector->append(25);
testVector->append(100);
QInteractiveSlider* w = new QInteractiveSlider(testVector, 0, 100);
w->show();
return a.exec();
}
I'm not sure that a grid layout is the best way to go about this.
Firstly, I would let the slider take care of itself - in a layout. And then the big job would be to place the labels where they should go.
Instead of using a layout for this, I would just parent the labels to the parent QWidget and then call
QWidget::move(int x, int y)
However, this will only work the first time, but since you are very nicely isolated in a QWidget (custom control) you can re-adjust the label positions when the parent resizes as follows:
void QInteractiveSlider::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
// Loop through the labels and adjust their location.
label->move(...);
}
That should do the trick.
If you run across any problems with this, let me know, and we'll see what we can do.
I cannot directly answer the 1st and 2nd questions. Displaying numbers separately is a bad idea. Since now you have to know where to manually display the numbers. This is not very portable and breaks encapsulation. It also might not scale properly to changing QSlider sizes. Since QSlider doesn't give an option of displaying numbers under ticks , you should either extend QSlider and rewrite the paint() function or use QWT. http://qwt.sourceforge.net/class_qwt_slider.html
You could also perhaps use a combination of QHBoxLayouts instead that way you could space things properly without too much hassle with the margins.
Here is a screenshot of what the following code produces:
You could make it a bit prettier by putting a maximum width on the labels. That way you could avoid having to set the left align right align on them.
#ifndef DESIGNERLS7532_H
#define DESIGNERLS7532_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QHBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QSlider>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Form
{
public:
QVBoxLayout *verticalLayout;
QWidget *widget;
QHBoxLayout *horizontalLayout;
QSlider *horizontalSlider;
QWidget *widget_2;
QHBoxLayout *horizontalLayout_2;
QLabel *label;
QLabel *label_4;
QLabel *label_2;
QLabel *label_5;
QLabel *label_3;
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(268, 55);
verticalLayout = new QVBoxLayout(Form);
verticalLayout->setSpacing(0);
verticalLayout->setContentsMargins(0, 0, 0, 0);
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
widget = new QWidget(Form);
widget->setObjectName(QString::fromUtf8("widget"));
horizontalLayout = new QHBoxLayout(widget);
horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
horizontalLayout->setContentsMargins(-1, -1, -1, 0);
horizontalSlider = new QSlider(widget);
horizontalSlider->setObjectName(QString::fromUtf8("horizontalSlider"));
horizontalSlider->setOrientation(Qt::Horizontal);
horizontalSlider->setTickPosition(QSlider::TicksBelow);
horizontalLayout->addWidget(horizontalSlider);
verticalLayout->addWidget(widget);
widget_2 = new QWidget(Form);
widget_2->setObjectName(QString::fromUtf8("widget_2"));
horizontalLayout_2 = new QHBoxLayout(widget_2);
horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
horizontalLayout_2->setContentsMargins(-1, 0, -1, -1);
label = new QLabel(widget_2);
label->setObjectName(QString::fromUtf8("label"));
horizontalLayout_2->addWidget(label);
label_4 = new QLabel(widget_2);
label_4->setObjectName(QString::fromUtf8("label_4"));
label_4->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter);
horizontalLayout_2->addWidget(label_4);
label_2 = new QLabel(widget_2);
label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setAlignment(Qt::AlignCenter);
horizontalLayout_2->addWidget(label_2);
label_5 = new QLabel(widget_2);
label_5->setObjectName(QString::fromUtf8("label_5"));
label_5->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
horizontalLayout_2->addWidget(label_5);
label_3 = new QLabel(widget_2);
label_3->setObjectName(QString::fromUtf8("label_3"));
label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
horizontalLayout_2->addWidget(label_3);
horizontalLayout_2->setStretch(0, 1);
horizontalLayout_2->setStretch(1, 1);
horizontalLayout_2->setStretch(2, 1);
horizontalLayout_2->setStretch(3, 1);
horizontalLayout_2->setStretch(4, 1);
verticalLayout->addWidget(widget_2);
retranslateUi(Form);
QMetaObject::connectSlotsByName(Form);
} // setupUi
void retranslateUi(QWidget *Form)
{
Form->setWindowTitle(QApplication::translate("Form", "Form", 0, QApplication::UnicodeUTF8));
label->setText(QApplication::translate("Form", "0", 0, QApplication::UnicodeUTF8));
label_4->setText(QApplication::translate("Form", "25", 0, QApplication::UnicodeUTF8));
label_2->setText(QApplication::translate("Form", "50", 0, QApplication::UnicodeUTF8));
label_5->setText(QString());
label_3->setText(QApplication::translate("Form", "100", 0, QApplication::UnicodeUTF8));
} // retranslateUi
};
namespace Ui {
class Form: public Ui_Form {};
} // namespace Ui
QT_END_NAMESPACE
#endif // DESIGNERLS7532_H
精彩评论