0

私のアプリケーションQGridLayoutでは、の大部分をカバーするがありWindowます。その中に、一連のQLineEditQLabelオブジェクトを追加しました。現在、QLineEditオブジェクトの数が500を超える場合&&QLabelオブジェクトが500を超える場合、GUIは非常に遅く、値が大きい場合は正しく動作しません。また、これらのウィジェットのほとんどはウィンドウに表示されません。表示するにはスクロールする必要があります。(ループしてループの後に呼び出すことによって)非常に多くwidgetsを追加しているので、ペイントには多くの時間がかかります。だから私は、自分が追加されたとしても、誰もがペイントされているわけではないという解決策のアイデアを持っています。すべてが描かれている内にありたいです&grid layoutrepaintwidgetsGrid Layoutrectanglewidgetsウィンドウがスクロールされるたびに、長方形の座標が更新されます。しかし、私はこれを行う方法がわかりません。だから私はそれが可能か知りたかったのですか?そして、可能であれば、それを実装する方法を理解できるように、小さなサンプルコードを追加してください。ありがとうございました。

更新:状況を描写するための画像を追加します。

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

コードを破棄したくないとのことですが。最も簡単なものから始めて、これらの1つを試してみます。

  • を使用していますか、QScrollAreaそれともスクロールバーを使用してシミュレートしていますか?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();
    
  • それが機能しない場合は、表示されている長方形を参照するイベントフィルターを作成します。イベントフィルタリングは、1つ以上のウィジェットを対象としたイベントをインターセプトし、処理する前にそれらを破棄するかどうかを決定できる便利な手法です。

    あなたの場合、を傍受するとき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);
     }
    
  • 最後の手段として、、、、およびを使用QGraphicsSceneしてUIをリレーアウトします。シーングラフは、不要なUIの再描画を破棄するのに適している場合があります。QGraphicsWidgetQGraphicsGridLayoutQGraphicsView

于 2013-03-12T14:57:52.603 に答える
1

初めに。問題を正しい方法で解決していますか?おそらく、QTableWidgetでもっと幸せになるでしょうか?そのセルは編集可能であり、QTableWidgetは編集中のセルのQLineEditの作成と維持を処理します。

于 2013-03-08T13:55:06.793 に答える