c++ - QScrollArea 中的自定义小部件仅在滚动时严重重绘

标签 c++ qt qt5 qwidget qscrollarea

我试图在 QT 中获取自定义滚动小部件,但在滚动时出现重绘错误。 Alt-tab 或其他重绘事件正确重绘。

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

repeatingwidget.cpp(节选):

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::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 中不会发生的重绘错误。

我已经尝试了 setGeometrysetWidgetResizable 和不同的大小策略,但我仍然遇到这些重绘错误。

During first draw:

滚动后:

After scrolling

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

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

最佳答案

QPaintEvent 是一种可以让你进行智能绘画的方法,即在需要的地方绘画,从而节省资源,例如它给了我们必须绘制的矩形的信息event->rect(),有了这个我们可以计算出必须绘制的项目,因为其他项目将被隐藏,因此没有必要绘制它们:

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);
    }
}

enter image description here

enter image description here

关于c++ - QScrollArea 中的自定义小部件仅在滚动时严重重绘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52460376/

相关文章:

c++ - 程序在 Visual Studio 2012 中运行,但不在 ideone.com 中运行

python - 属性错误: 'Ui_Form' object has no attribute 'printHam_btn'

QTableView - 限制所选项目的数量?

mysql - QT5 找到 MySQL 但在 Debian 上无法加载它

c++ - MXE Qt5 应用程序在 Docker 容器中构建失败

c++ - 图像缩小使用什么算法?

c++ - Linux C++ 文件权限被拒绝

c++ - 全等、相似和直角三角形

c++ - 这安全吗? (qt QQueue.dequeue() c++ 内联指针取消引用)

c++ - 将 Qt 属性与命名空间中定义的自定义类型一起使用