如何控制QGridLayout中应该在GUI中绘制的Widgets?

时间:2013-03-08 13:25:28

标签: c++ qt

在我的应用程序中,我有一个QGridLayout,涵盖Window的大部分内容。在其中我添加了一系列QLineEdit& QLabel个对象。目前,QLineEdit个对象的数量为> 500&& QLabel个对象> 500 GUI显着缓慢&更大的价值观无法正常运作。此外,大多数这些小部件在窗口中都不可见,需要滚动才能查看。 由于我在widgets中添加了这么多grid 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. 我希望我能让这个问题变得简单易懂。 enter image description here

2 个答案:

答案 0 :(得分:3)

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

  • 您使用的是QScrollArea还是使用滚动条进行模拟? QScrollArea可能已经将绘制事件丢弃到视口外的子窗口小部件。在屏幕外组装网格。否则,每次添加新窗口小部件时,Qt都会重新计算并重新绘制布局。 (Here is a complete example。)

    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();
    
  • 如果这不起作用,请创建一个引用可见矩形的event filter。事件过滤是一种有用的技术,您可以拦截针对一个或多个小部件的事件,并决定在处理之前是否应该将它们丢弃。

    在您的情况下,当您截取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);
     }
    
  • 作为最后的手段,请使用QGraphicsSceneQGraphicsWidgetQGraphicsGridLayoutQGraphicsView重新停用您的用户界面。场景图可能更好地丢弃不必要的UI重绘。

答案 1 :(得分:1)

首先。您确定以正确的方式解决问题吗?也许你会对QTableWidget更开心?它的单元格可以编辑,然后QTableWidget将负责为正在编辑的单元格创建和维护QLineEdit。