1

I'm developing a timeline editor containing tracks represented by QLabels in a QScrollArea.

First there's a track by default, and we can add and remove tracks dynamically.

I'm having issue with the fact that when there are a few tracks left (3) and I remove one of them, the painting is broken, please see the gif below:

enter image description here

I've tried :

  • qApp->processEvents()
  • update()
  • show()
  • style()->unpolish(); style()->polish();

and I applied those methods to all graphical elements implied in this context.

Here is my code description :

  • EditCueTimelineWidget class is the global widget shown is the image.

  • ui->TimelineEditScrollArea is the QScrollArea.

  • ui->scrollAreaWidgetContents is the scrollArea's content widget.

  • _trackLabelList is a QVector of TrackLabel.

  • _subTrackLabelList (for each TrackLabel) is a QVector of SubTrackLabel.

  • TrackLabel and SubTrackLabel have a _label member which is a VerticalLabel (which shows the name vertically) and a _strip member which is a QLabel with orange or yellow color (showing which track or subtrack is currently selected).

Here's the code

void EditCueTimelineWidget::refreshWidget()
{
    qApp->processEvents();
    ui->label->refreshTimemarks();
    for(auto l :qAsConst(_trackLabelList))
    {
        l->recenterWidgets();
        l->update();
        l->show();
    }

    style()->unpolish(ui->scrollAreaWidgetContents);
    style()->polish(ui->scrollAreaWidgetContents);
    style()->unpolish(ui->TimelineEditScrollArea);
    style()->polish(ui->TimelineEditScrollArea);
    style()->unpolish(this);
    style()->polish(this);

    ui->scrollAreaWidgetContents->update();
    ui->TimelineEditScrollArea->update();
    update();
    ui->scrollAreaWidgetContents->show();
    ui->TimelineEditScrollArea->show();
    show();

    ui->nbTracksLabel->setText(QString::number(_trackLabelList.size())+tr(" Tracks"));
    qApp->processEvents();
}
void TrackLabel::recenterWidgets()
{
    _label->setFixedSize(50,height());
    _label->move(40,0);

    _strip->setFixedSize(15, height());
    _strip->move(1,1);

    int nbSub = _subTrackLabelList.size();
    for(int k = 0; k <nbSub ; k++)
    {
        SubTrackLabel* l = _subTrackLabelList.at(k);
        int h = height()/nbSub;
        int posY = k * h;
        if(k != (nbSub -1))
            l->setFixedSize(width() - 100, h);
        else
            l->setFixedSize(width() - 100, height() - posY);
        l->move(100,posY);

        l->recenterWidgets();
        l->update();
        l->show();
    }

    style()->unpolish(_label);
    style()->polish(_label);
    style()->unpolish(_strip);
    style()->polish(_strip);
    style()->unpolish(this);
    style()->polish(this);

    _label->update();
    _strip->update();
    _label->show();
    _strip->show();
}
void SubTrackLabel::recenterWidgets()
{
    _label->setFixedSize(35,height());
    _label->move(20,0);

    _strip->setFixedSize(12, height());
    _strip->move(1,1);

    style()->unpolish(_label);
    style()->polish(_label);
    style()->unpolish(_strip);
    style()->polish(_strip);
    style()->unpolish(this);
    style()->polish(this);

    _label->update();
    _strip->update();
    _label->show();
    _strip->show();
}

Note that I have a resizing eventFilter on EditCueTimelineWidget, and when I resize the application manually, I get the result expected: the two last tracks take all the space and are correctly shown :

bool EditCueTimelineWidget::eventFilter(QObject *, QEvent *event)
{
    if (event->type() == QEvent::Resize)
    {
        refreshWidget();
        return true;
    }
    return false;
}

Also note that in TrackLabel constructor, I have this :

    setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
    setMinimumHeight(300);

What method should I call, or should I change call order of the methods I'm already using, in order to get the result I need?

1 Answers1

0

This was the problem :

when I added a TrackLabel, I called : ui->scrollAreaWidgetContents->layout()->addWidget(l); But I didn't removedd it from the layout when take the TrackLabel from the vector and deletelater() I did it now and it works fine :

ui->scrollAreaWidgetContents->layout()->removeWidget(activeTrack);

I wipe all those "refresh painting" method from my code, except for all show() which seems to be necessary, And I kept qApp->prrocessEvents() but outside of refrefhWidget (it was a bad idea, since I call this method in a resize event, and a lot of qApp->prrocessEvents() each time I resize for 1 pixel make it... crash ! I put qApp->prrocessEvents() only when I have to do an ensureWidgetVisible (have to do it to force recomputing the 'maximum' of the scroll bar or something like that)