#qt #qt4 #qslider
#qt #qt4 #qslider
Вопрос:
Я пытаюсь создать динамический QSlider, который принимает QVector целочисленных значений и отображает их под QSlider относительно того, какую позицию они представляют.
Вот скриншот того, что у меня есть сейчас: Мой слайдер http://dev.kyleswebspace.com/images/QInteractiveSlider.jpg
Как вы можете видеть, отметки не совпадают с их значениями. Это одна из проблем.
Основная проблема, с которой я борюсь, заключается в том, что независимо от того, на что я меняю значение заполнения (см. qinteractiveslider.h), QSlider в моем виджете остается того же размера по отношению к сетке значений.
- Почему аргументы моего QGridLayout не предоставляют правильное количество отступов?
- Как я могу принудительно использовать эти поля в QSlider?
- Есть ли лучший способ позиционирования этих меток? Я открыт для предложений.
Вот код:
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 "qinteractiveslider.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();
}
Комментарии:
1. В итоге я согласился с предложением Лиз, и оно отлично сработало. Спасибо, Лиз!
Ответ №1:
Я не уверен, что макет сетки — лучший способ добиться этого.
Во-первых, я бы позволил слайдеру позаботиться о себе — в макете. И тогда большой задачей было бы разместить метки там, где они должны быть.
Вместо того, чтобы использовать макет для этого, я бы просто привязал метки к родительскому QWidget, а затем вызвал
QWidget::move(int x, int y)
Однако это сработает только в первый раз, но поскольку вы очень хорошо изолированы в QWidget (пользовательском элементе управления), вы можете повторно настроить позиции меток при изменении размера родительского элемента следующим образом:
void QInteractiveSlider::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
// Loop through the labels and adjust their location.
label->move(...);
}
Это должно сработать.
Если вы столкнетесь с какими-либо проблемами с этим, дайте мне знать, и мы посмотрим, что мы можем сделать.
Комментарии:
1. В итоге я выбрал именно этот метод, и он работал фантастически. Большое спасибо.
Ответ №2:
Я не могу напрямую ответить на 1-й и 2-й вопросы. Отображать числа по отдельности — плохая идея. Поскольку теперь вы должны знать, где вручную отображать числа. Это не очень переносимо и нарушает инкапсуляцию. Это также может неправильно масштабироваться при изменении размеров QSlider. Поскольку QSlider не предоставляет возможности отображения чисел под тиками, вам следует либо расширить QSlider и переписать функцию paint(), либо использовать QWT. http://qwt.sourceforge.net/class_qwt_slider.html
Комментарии:
1. Я также должен иметь возможность сделать эти отображаемые числа интерактивными, чтобы нажатие на число регулировало ползунок. Как я могу этого добиться, если я пойду по пути переопределения paint ()?
Ответ №3:
Возможно, вы также могли бы вместо этого использовать комбинацию QHBoxLayouts, чтобы вы могли правильно размещать объекты без особых проблем с полями.
Вот скриншот того, что выдает следующий код:
Вы могли бы сделать это немного красивее, указав максимальную ширину надписей. Таким образом, вы могли бы избежать необходимости устанавливать для них выравнивание по левому краю.
#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
Комментарии:
1. Спасибо за усилия, но мне нужно иметь возможность принимать неопределенное количество неопределенных целых чисел для неопределенного диапазона (вся эта информация будет передана в конструктор).
2. Понял. Планируете ли вы просто увеличить размер слайдера, чтобы компенсировать добавленные целые числа, или отфильтровать их, когда их наберется слишком много? В примере показана статическая версия, однако вы могли бы динамически добавлять qlabels для целых чисел, которые вы показывали в horizontalLayout_2.