如何更新 Qt 中的场景?

How can I update a scene in Qt?

我正在尝试学习 C++,为此,我想实现一个棋盘游戏(生命游戏),其中我们有多个单元格。如果细胞是活的,我们就把它涂成白色,如果细胞是死的,我们就把它涂成黑色。 我现在想做的只是:

  1. 让一个细胞存活
  2. 在屏幕上显示
  3. 稍等半秒
  4. 让另一个细胞存活下来
  5. 在屏幕上显示。

但是,在我看来,当场景显示时,两个细胞都已经存活了。这是我当前代码的主要部分:

#include "mainwindow.h"
#include <vector>
#include <iostream>

#include <QApplication>
#include <QPushButton>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QGraphicsView>
#include <QTimer>

using namespace std;

// global variables:
const int WIDTH = 600;
const int HEIGHT = 400;
const int SIZE = 10;
const int NCOL = HEIGHT/SIZE;

const QColor aliveCol = QColor(200,200,200);
const QColor deadCol = QColor(50,50,50);

class Cell {
    public:
    int x;
    int y;
    bool alive;
    vector<Cell> neigh;

    Cell(int a = 0, int b = 0) {
        x = a;
        y = b;
        alive = false;
        neigh = {};
    }

    void draw(QGraphicsScene * scene){
        QGraphicsRectItem * cell1 = new QGraphicsRectItem(this->x*SIZE,this->y*SIZE,SIZE,SIZE);
        if (this->alive) {
            cell1->setBrush(QBrush(aliveCol));
        }
        else {
            cell1->setBrush(QBrush(deadCol));
        }
        scene->addItem(cell1);
    }

};

void updateScene (Cell mat [NCOL][NCOL], QGraphicsScene * scene) {
    for (int i = 0; i<NCOL; i++) {
        for (int j = 0; j<NCOL; j++) {
            mat[i][j].draw(scene);
        }
    }
}

int main(int argc, char *argv[])
{   
    QApplication prog(argc, argv);
    //MainWindow w;
    //w.show();
    /**
    QPushButton *button = new QPushButton("Quit now!!");
    QObject::connect(button, SIGNAL(clicked()), &prog, SLOT(quit()));
    button->show();**/
    QGraphicsScene * scene = new QGraphicsScene(0,0,WIDTH,HEIGHT);

    //background:
    scene->setBackgroundBrush(Qt::gray);

    //build the board
    for (int i = 0; i <= NCOL; i++){
          scene->addLine(SIZE*i,0,SIZE*i,HEIGHT);
          scene->addLine(0,SIZE*i,HEIGHT,SIZE*i);
    }

    //building the cells matrix:
    Cell mat [NCOL][NCOL]={};
    for (int i = 0; i<NCOL; i++) {
        for (int j = 0; j<NCOL; j++) {
            mat[i][j] = Cell(i,j);
        }
    }

    //(...) <- Non important stuff    

    //step 1
    mat[9][7].alive = true;

    updateScene(mat,scene);

    //step 2
    QGraphicsView * view = new QGraphicsView(scene);
    view->setFixedSize(610,410);
    view->show();

    //step 3 (I know this is not how it is done, but I'm having troubles with QTimer)
    for (int i = 0; i < 2000; i++) {
        continue;
    }

    // step 4
    mat[20][30].alive = true;
    updateScene(mat,scene);

    // step 5
    scene->advance();
    scene->update();

    return prog.exec();
}

我稍微修改了你的代码,我使用 Mainwindow class 而不是直接使用 main 函数并使用了 QTimer class 和 QRandomGenerator

结果是这样的:

在mainwindow.h中:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <vector>
#include <iostream>

#include <QApplication>
#include <QPushButton>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QGraphicsView>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui
{
class MainWindow;
}
QT_END_NAMESPACE

using namespace std;

// global variables:
const int     WIDTH    = 600;
const int     HEIGHT   = 400;
const int     SIZE     = 10;
const int     NCOL     = HEIGHT / SIZE;
const QColor  aliveCol = QColor(200, 200, 200);
const QColor  deadCol  = QColor(50, 50, 50);


class Cell
{
public:
    int           x;
    int           y;
    bool          alive;
    vector<Cell>  neigh;

    Cell(int a = 0, int b = 0)
    {
        x     = a;
        y     = b;
        alive = false;
        neigh = { };
    }

    void  draw(QGraphicsScene *scene)
    {
        QGraphicsRectItem *cell1 = new QGraphicsRectItem(this->x * SIZE, this->y * SIZE, SIZE, SIZE);

        if (this->alive)
        {
            cell1->setBrush(QBrush(aliveCol));
        }
        else
        {
            cell1->setBrush(QBrush(deadCol));
        }

        scene->addItem(cell1);
    }
};

class MainWindow: public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);

    ~MainWindow();

    void  updateScene(Cell mat[NCOL][NCOL], QGraphicsScene *scene);

private:
    Ui::MainWindow *ui;
    Cell            mat[NCOL][NCOL] = { };
};

#endif // MAINWINDOW_H

在mainwindow.cpp中:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtCore/QRandomGenerator>

MainWindow::MainWindow(QWidget *parent):
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QGraphicsScene *scene = new QGraphicsScene(0, 0, WIDTH, HEIGHT);

    // background:
    scene->setBackgroundBrush(Qt::gray);

    // build the board
    for (int i = 0; i <= NCOL; i++)
    {
        scene->addLine(SIZE * i, 0, SIZE * i, HEIGHT);
        scene->addLine(0, SIZE * i, HEIGHT, SIZE * i);
    }

    // building the cells matrix:

    for (int i = 0; i < NCOL; i++)
    {
        for (int j = 0; j < NCOL; j++)
        {
            mat[i][j] = Cell(i, j);
        }
    }


    // step 1
    mat[9][7].alive = true;

    updateScene(mat, scene);

    // step 2
    QGraphicsView *view = new QGraphicsView(scene);
    view->setFixedSize(610, 410);
    view->show();

    // step 3 (I know this is not how it is done, but I'm having troubles with QTimer)
    QTimer *_timer = new QTimer;

    connect(_timer, &QTimer::timeout, scene, [this, scene]()
    {
        mat[QRandomGenerator::global()->bounded(40)][QRandomGenerator::global()->bounded(40)].alive = true;
        updateScene(mat, scene);
    });

    _timer->start(500);


   
}

MainWindow::~MainWindow()
{
    delete ui;
}

void  MainWindow::updateScene(Cell mat[NCOL][NCOL], QGraphicsScene *scene)
{
    for (int i = 0; i < NCOL; i++)
    {
        for (int j = 0; j < NCOL; j++)
        {
            mat[i][j].draw(scene);
        }
    }
}

输出是: