2

mineSweeping ゲームでQPushButtonを使用しています。

イージーモードからハードモードに変更後、QPushButton の数は9x9から 30x16 に変更されるはずです。

そこで、MainWindowのコンストラクターでGridLayoutに最大数 (ハードモード) のQPushButtonを追加します。

btnArr = new QPushButton[HARD_WIDTH * HARD_HEIGHT]; // member element
int index = 0;
for (int i = 0; i < HARD_HEIGHT; ++i) {
    for (int j = 0; j < HARD_WIDTH; ++j) {
        ui->mainGrid->addWidget(&btnArr[index], i, j, 1, 1,
                                Qt::AlignCenter);
        ++index;
    }
}

次に、ユーザーがモードを変更した場合 (例: イージー モードからハード モード)、resetBtn(HARD_WIDTH, HARD_HEIGHT);が呼び出されます。

void MainWindow::resetBtn(const int width, const int height)
{
    int index = 0;
    for (int i = 0; i < HARD_HEIGHT; ++i) {
        for (int j = 0; j < HARD_WIDTH; ++j) {
            if (j < width && i < height) {
                btnArr[index].setVisible(true);
            } else {
                btnArr[index].setVisible(false);
            }
            ++index;
        }
    }
}

setVisible問題は、呼び出されるたびにウィジェットが再描画されるように見えることです。したがって、ハードモードの場合、30x16 回呼び出され、次のような奇妙な効果が発生します。 ここに画像の説明を入力

では、このループ中にウィジェットを再描画しないように設定するにはどうすればよいですか?

前もって感謝します。

4

5 に答える 5

2

あなたは間違った問題を解決しようとしていると思います。このようにウィジェットを更新するべきではありません。どうしても必要な場合は、変更前にレイアウトの親ウィジェットを非表示にし、後で再度表示するとうまくいくはずです。

より良いアプローチは、QStackedWidgetを使用し、最初にすべてのボードを準備することです。別のボードに切り替えるには、アクティブなウィジェットを切り替えるだけです。

于 2012-06-02T07:09:42.650 に答える
1

の総数QPushButtonは本当に大きいです:30x16 = 480 !!! QPushButton私は人々にプログラミングロジックを変更させるために使用しませんが、この場合、sを使用することはより良いアプローチではないと思います。レイアウトは、オブジェクトが追加されたときにオブジェクトを移動しようとして非常に時間がかかる必要があります。おそらく、レイアウトを再描画するための更新時間の内部制限に達している可能性があります。

私がやったのは、カスタムpaintEventメソッドを使用したカスタムウィジェットです。そこで、幅と高さを希望する列と行の数に分割し、ゲームのプレイ中にセルをピックスマップでペイントすることができます。

mousePressEventマウスの相互作用については、グリッド内のマウスの位置を計算し、対応するメソッドを呼び出すか、イベントの位置を示す信号を出力するカスタムロジックでをオーバーライドするのが最善でした。コーディングはそれほど難しくありません。この方法を使用して、event->buttons()どのマウスボタンが押されたかを確認し、必要に応じてさまざまな信号を発することもできます。

私はあなたのプログラム全体を変える方が良いと答えるのに使用しませんが、この場合、あなたは「困難な道」を進んでいると思います。これはあなたが探している種類の答えではないことを私は知っていますが、この可能性を考慮してください。

于 2012-06-06T05:20:27.637 に答える
1

これらの「大規模な」変更を行う前に親ウィジェットを呼び出しsetUpdatesEnabled(false)て、すべてが完了したら再度有効にすることができます。

于 2012-05-22T05:48:59.620 に答える
1

たぶん私は間違っているかもしれませんが、私が知る限り、Qt は setVisible() が呼び出された直後にウィジェットをレンダリングしません。render() を手動で呼び出した場合を除き、レンダリングは「render」イベントの結果として発生します。

公式の Qt ドキュメント ( http://qt-project.org/doc/qt-4.8/qwidget.html#paintEvent ) から:

Qt はまた、複数のペイント イベントを 1 つにマージすることで、ペイントを高速化しようとします。update() が数回呼び出されるか、ウィンドウ システムが複数のペイント イベントを送信すると、Qt はこれらのイベントをより大きな領域を持つ 1 つのイベントにマージします (QRegion::united() を参照)。repaint() 関数はこの最適化を許可しないため、可能な限り update() を使用することをお勧めします。

私の直感では、これはペイントの問題ではなく、レイアウト (「ハード モード」ですべてのボタンを表示するのに十分なスペースがない) であることがわかります。また、ボタンをレイアウトに追加するときに Qt::AlignCenter を使用しないでください。レイアウト内のすべてのボタンを中央に配置しようとします。レイアウトの親ウィジェットを中央に配置し (ない場合は作成して中央に配置)、サイズ ポリシーを正しく設定する必要があります (QWidget setSizePolicy)。

しかし、@Mat が示唆したように、これが本当に描画の問題である場合は setUpdatesEnabled(false/true) を使用できます (setUpdatesEnabled で問題が解決する場合は、@Mat の解決策を受け入れてください)。

于 2012-05-23T10:12:44.483 に答える
0

表示/非表示の代わりに有効/無効にしてみてください:

void MainWindow::resetBtn(const int width, const int height)
{
    int index = 0;
    for (int i = 0; i < HARD_HEIGHT; i++)
        for (int j = 0; j < HARD_WIDTH; j++)
            btnArr[index++].setEnabled(j < width && i < height);
}
于 2012-06-02T08:22:19.907 に答える