0

在我的应用程序中,我有一个QGridLayout涵盖大部分Window. 在其中,我添加了一系列QLineEdit&QLabel对象。目前,当QLineEdit对象数 > 500 &&QLabel对象 > 500 时,GUI速度非常慢,并且对于更大的值无法正常运行。而且大多数这些小部件在窗口中不可见,它们需要滚动才能查看。由于我widgetsgrid layout(通过循环和循环后调用repaint)中添加了这么多,所以绘画需要很多时间。所以我有一个解决方案的想法,即使我widgets被添加到Grid Layout不是每个人都被画了。我想要一个rectangle里面所有widgets的东西都被画出来了每当滚动窗口时,矩形的坐标就会更新。但我不知道该怎么做。所以我想知道是否有可能做到这一点?如果可能,请添加一个小示例代码,以便我了解如何实现它。谢谢你。

更新:添加图像来描述情况。

Black Rectangle = QGridLayout say myGid.

Red Rectangle = Bounding Rectangle which is approximately same size as Main Window of my Application.

Green Rectangle = Widgets in myGrid.

Green Rectangle filled with yellow = Widgets shown in Main Window (仅应考虑调用这些小部件repaint,其余未填充的矩形是存在于myGrid但不考虑调用的小部件repaint。因此,当我在我的主应用程序中滚动时,坐标red rectangle会更新并且widgets bounded by it are considered for repaint. 我希望我让问题变得简单易懂。 在此处输入图像描述

4

2 回答 2

3

我了解您不想丢弃您的代码。我会尝试其中一种,从最简单的开始:

  • 您是使用 aQScrollArea还是使用滚动条模拟它?QScrollArea可能已经将绘制事件丢弃到视口之外的子小部件。在屏幕外组装网格。否则,每次添加新的小部件时,Qt 都会重新计算并重新绘制布局。(这是一个完整的例子。)

    QWidget* widget = new QWidget(); // This is an invisible widget.
    
    for (int i = 0; i < 100; i++) {
        for (int j = 0; j < 100; j++) {
            QLineEdit* lineEdit = new QLineEdit();
            lineEdit->setText(QString("I am the line edit at (%1, %2)").arg(i).arg(j));
            layout->addWidget(lineEdit, i, j);
            if (j % 10 == 0) {
                // Do not block the UI thread while the UI is being assembled.
                qApp->processEvents();
            }
        }
    }
    
    // The layout will be calculated only once, here:
    
    scrollArea->setWidget(widget);
    widget->show();
    
  • 如果这不起作用,请创建一个引用可见矩形的事件过滤器。事件过滤是一种有用的技术,您可以在其中拦截针对一个或多个小部件的事件,并决定在处理之前是否应该丢弃它们。

    在您的情况下,当您拦截 a 时QPaintEvent,请检查目标小部件是否与可见矩形相交。如果是,则将事件传递给目标小部件。如果不是,则丢弃该事件。

    我不知道如何滚动 UI 的细节,所以我将计算可见矩形留给你。事件过滤器代码将是这样的。

     bool MyClass::eventFilter(QObject *obj, QEvent *event)
     {
        if (event->type() == QEvent::Paint) {
            if (QWidget* widget = qobject_cast<QWidget*>(object)) {
                QRect visibleRectangle = somehowGetVisibleRectangle();
                if (visibleRectangle.intersects(widget->geometry())) {
                    return false;
                } else {
                    // Returning true means "drop this event."
                    return true; 
                }
            }
        }
    
        // Assuming MyClass extends QWidget. Adjust as necessary.
        return QWidget::eventFilter(obj, event);
     }
    
  • 作为最后的手段,使用QGraphicsSceneQGraphicsWidgetQGraphicsGridLayout和重新布局您的 UI QGraphicsView。场景图可能更擅长丢弃不必要的 UI 重绘。

于 2013-03-12T14:57:52.603 回答
1

First of all. Are you sure you are solving your problem in the right way? Perhaps you will be happier with QTableWidget? Its cells can be editable and then QTableWidget will take care of creating and maintaining QLineEdit for the cell that is being edited.

于 2013-03-08T13:55:06.793 回答