简体   繁体   中英

Qt Custom widget with overlapping subwidgets

I'm trying to make a custom widget in Qt5 which is sort of like a QProgressBar but with 3 sliders and user movable: (slightly broken JS implementation: codepen , gist )

I'm having issues working out quite how to do this. My attempts have failed to either render all the parts of the widget correctly (making it very difficult to select and move different parts of it) or not working correctly with a VBoxLayout (doesn't expand to fit the horizontal space)

My latest attempt (you should be able to get the general idea from the constructor, nothing else was implemented)

UTrackSlider::UTrackSlider(QWidget *parent) : QWidget(parent)
{
    this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);

    // CIRCLE_HEIGHT = 10
    // BACKGROUND_HEIGHT = 30

    /// @todo css should be in global stylesheet
    background = new QLabel(this);
    background->setMinimumHeight(this->BACKGROUND_HEIGHT);
    background->setStyleSheet("QLabel{ border: 1px solid gray; background-color:white; border-radius:2px}");
    background->setAttribute(Qt::WA_DeleteOnClose);

    cue = new QLabel(this);
    cue->setFixedSize(QSize(this->CIRCLE_HEIGHT, this->CIRCLE_HEIGHT));
    cue->setStyleSheet("QLabel:hover{ border: 2px solid #d9534f; border-radius:5px}");
    cue->setAttribute(Qt::WA_DeleteOnClose);

    duration = new QLabel(this);
    duration->setFixedSize(3, this->BACKGROUND_HEIGHT);
    duration->setStyleSheet("QLabel{border: 3px solid #2376bb} QLabel:hover{border: 5px solid #2376bb}");
    duration->setAttribute(Qt::WA_DeleteOnClose);

    intro = new QLabel(this);
    intro->setFixedSize(QSize(this->CIRCLE_HEIGHT, this->CIRCLE_HEIGHT));
    intro->setStyleSheet("QLabel:hover{ border: 2px solid #5bc85c; border-radius:5px}");
    intro->setAttribute(Qt::WA_DeleteOnClose);

    QGridLayout *mainLayout = new QGridLayout(this);
    mainLayout->addWidget(cue, 5, 0);
    mainLayout->addWidget(background, 0, this->CIRCLE_HEIGHT);
    mainLayout->addWidget(duration, 2, this->CIRCLE_HEIGHT);
    mainLayout->addWidget(intro, 5, this->CIRCLE_HEIGHT + this->BACKGROUND_HEIGHT);
    this->setLayout(mainLayout);
}

Basically, any pointers about how I should structure this composite widget such that it works in all these conditions?

EDIT: After discussing the issue with some people on #qt , i've come to the conclusion that I must override paintEvent. But this also means overriding some other functions to do the onClick and dragging effects, and I've got no idea where to start

You're right, you have to re-implement

1.void paintEvent(QPaintEvent *) 
2.void mouseMoveEvent(QMouseEvent *)
3.void mousePressEvent(QMouseEvent *)
4.void mouseReleaseEvent(QMouseEvent *)

of QWidget.

In order to handle the mouse event correctly, you may use QCoreApplication::sendEvent(QObject *, QEvent *) to pass the event to the target widget.

Here's an example: https://github.com/Serge45/MultiSlider

In this example, I create three widgets(ColorSlider) in a container widget, and then use a linked list to propagate the mouse event correctly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM