如何更新 Qt 中的场景?
How can I update a scene in Qt?
我正在尝试学习 C++,为此,我想实现一个棋盘游戏(生命游戏),其中我们有多个单元格。如果细胞是活的,我们就把它涂成白色,如果细胞是死的,我们就把它涂成黑色。
我现在想做的只是:
- 让一个细胞存活
- 在屏幕上显示
- 稍等半秒
- 让另一个细胞存活下来
- 在屏幕上显示。
但是,在我看来,当场景显示时,两个细胞都已经存活了。这是我当前代码的主要部分:
#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);
}
}
}
输出是:
我正在尝试学习 C++,为此,我想实现一个棋盘游戏(生命游戏),其中我们有多个单元格。如果细胞是活的,我们就把它涂成白色,如果细胞是死的,我们就把它涂成黑色。 我现在想做的只是:
- 让一个细胞存活
- 在屏幕上显示
- 稍等半秒
- 让另一个细胞存活下来
- 在屏幕上显示。
但是,在我看来,当场景显示时,两个细胞都已经存活了。这是我当前代码的主要部分:
#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);
}
}
}
输出是: