QScrollArea中的自定义小部件只能在滚动条上重绘 [英] Custom Widget in QScrollArea Badly Redrawing Only on Scroll

查看:386
本文介绍了QScrollArea中的自定义小部件只能在滚动条上重绘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在QT中获取自定义滚动小部件,并且在滚动时遇到重绘错误. Alt-tab或其他重绘事件会正确重绘.

I'm trying to get a custom scrolling widget in QT, and I'm getting redraw errors on scroll. Alt-tab or other redrawing events redraw correctly.

我以 http:上的示例为基础://doc.qt.io/qt-5/qtwidgets-widgets-charactermap-example.html

repeatingwidget.cpp(摘录):

repeatingwidget.cpp (excerpt):

QSize RepeatingWidget::sizeHint() const {
    return QSize(500, itemHeight * displayItems.size() + 1);
}

void RepeatingWidget::paintEvent(QPaintEvent *event) {
    QPainter painter(this);
    painter.fillRect(event->rect(), QBrush(Qt::white));
    painter.setFont(displayFont);

    QRect itemRect = event->rect();

    int top = itemRect.top();

    QFontMetrics fontMetrics(*displayFont);
    for (auto item : displayItems) {
        painter.setPen(QPen(Qt::gray));
        painter.drawRect(itemRect.left(), top, itemRect.right(), itemHeight);
        painter.setPen(QPen(Qt::black));
        painter.drawText(8, 4 + top + fontMetrics.ascent(), item.name);

        top += itemHeight;
    }
}

mainwindow.cpp(摘录):

mainwindow.cpp (excerpt):

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    QMenu *filemenu = menuBar()->addMenu(tr("File"));
    filemenu->addAction(tr("Quit"), this, &QWidget::close);

    auto *centralWidget = new QWidget;

    scrollArea = new QScrollArea;

    repeatingArea = new RepeatingWidget();
    scrollArea->setWidget(repeatingArea);

    auto *centralLayout = new QVBoxLayout;
    centralLayout->addWidget(scrollArea, 1);

    centralWidget->setLayout(centralLayout);

    setCentralWidget(centralWidget);
    setWindowTitle(tr("Widget Test"));
}

这似乎与示例匹配,但是我遇到了charmap中没有发生的重绘错误.

This seems to match the example, but I'm getting redraw errors that don't happen in charmap.

我尝试了setGeometrysetWidgetResizable和其他尺寸策略,但仍然遇到这些重绘错误.

I've tried setGeometry, setWidgetResizable, and different size policies, but I'm still getting these redraw errors.

滚动后:

我不知道我在做什么错,因为它在重要方面与charmap中的示例代码基本相同.

I don't know what I'm doing wrong because it's largely identical in important ways to the example code from the charmap.

这是完整代码: https://gist.github.com/jonasbuckner/2acc1a960e457946ce4756199de3fb57

推荐答案

QPaintEvent是一种方法,可以使您进行智能绘画,即在需要的地方进行绘画,从而节省资源,例如,它为我们提供了必须通过event->rect()绘制的矩形的信息,借助此信息,我们可以计算出必须绘制的项目,因为其他项目将被隐藏,因此不必绘制它们:

QPaintEvent is a method that allows you to make an intelligent painting, that is, to paint where necessary, thus saving resources, for example it gives us the information of the rectangle that must be painted through event->rect(), with this we can calculate the items that have to be painted since others will be hidden and therefore it is not necessary to paint them:

void RepeatingWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.fillRect(event->rect(), QBrush(Qt::white));
    painter.setFont(displayFont);
    QFontMetrics fontMetrics(displayFont);
    int i = std::max(event->rect().top()/itemHeight, 0);
    int j = std::min(event->rect().bottom()/itemHeight+1, displayItems.size());
    QRect itemRect(0, i*itemHeight, width(), itemHeight);
    for(; i < j; i++){
        painter.setPen(QPen(Qt::gray));
        painter.drawRect(itemRect);
        painter.setPen(QPen(Qt::black));
        painter.drawText(8, 4 + itemRect.top() + fontMetrics.ascent(), displayItems[i].name);
        itemRect.translate(0, itemHeight);
    }
}

这篇关于QScrollArea中的自定义小部件只能在滚动条上重绘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆