Qt:使用二维数组值更新pixmap网格布局 我正在使用Visual Studio 2010和QT 4.7(两个Windows)中的C++组合进行游戏。这个游戏是战舰的克隆,是基于控制台输入的。我已经创建了我想要的gui外观,在Qt designer的Qt端,我的gui由一个10x10的网格布局组成,使用标签来保存游戏单元的像素图:
我对每个标签进行了精心命名,以表示其在2d阵列中的位置(即舰队地图=>Qt:使用二维数组值更新pixmap网格布局 我正在使用Visual Studio 2010和QT 4.7(两个Windows)中的C++组合进行游戏。这个游戏是战舰的克隆,是基于控制台输入的。我已经创建了我想要的gui外观,在Qt designer的Qt端,我的gui由一个10x10的网格布局组成,使用标签来保存游戏单元的像素图:,qt,qpixmap,grid-layout,Qt,Qpixmap,Grid Layout,我对每个标签进行了精心命名,以表示其在2d阵列中的位置(即舰队地图=>F_00=>F[0,0]=>F[I],[j])。我可以使用properties editor手动选择要显示的pixmap,但我想要动态的 我使用一个updatemapboard类在玩家开火后重新绘制游戏板,该类通过一个char数组进行存储。我想使用一个通用的getupdatearray类型函数来更新我的每一个pixmaps。当我们遍历数组时,它将更新当前与单个标签关联的pixmap,以匹配数组中的同类标签。(假设hit为F[5
F_00
=>F[0,0]
=>F[I],[j]
)。我可以使用properties editor手动选择要显示的pixmap,但我想要动态的
我使用一个updatemapboard类在玩家开火后重新绘制游戏板,该类通过一个char数组进行存储。我想使用一个通用的getupdatearray类型函数来更新我的每一个pixmaps。当我们遍历数组时,它将更新当前与单个标签关联的pixmap,以匹配数组中的同类标签。(假设hit为F[5][6]=“X”
,然后当循环到达数组中的该位置时,它会将F_56处的像素贴图网格更新为等于hit.png,替换为空的.png
我知道如何进行循环以实现这一点,但不确定如何使每个标签的pixmap更接近于运行时特性而不是现在的编译时(静态)特性。我读过QPaint和另一个处理图像的Qt类,但仍然很难做到这一点
问你们中的任何人,我如何基于2d数组更新这些像素贴图
#include <QtCore>
#include <QtGui>
// WARNING: PSEUDOCODE, DOES NOT COMPILE
// AT A LOSS ON HOW TO SELECT THE CORRECT LABEL
// MAYBE A CHILD CLASS FOR THAT?
class map {
public:
char updateboard(char mapname, char b[][10]){
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
char C = b[i][j];
if (C == 'M'){//miss
Qlabel mapname_[i][j](<img src='images/missspace.png'/>);
mapname_[i][j].show();
}
else if(C == 'X'){//hit
Qlabel mapname_[i][j](<img src='images/hitspace.png'/>);
mapname_[i][j].show();
}
else if(C == ' '){//undiscovered space
Qlabel mapname_[i][j](<img src='image/emptyspace.png'/>);
mapname_[i][j].show();
}
}
}
}
};
提前谢谢
更新:
我已经到了可以用按钮交换pixmaps的地步,但我想创建一些更具动态性的东西。我想使用一个Qstring,在其中放置我要更改的标签的名称,方法是使用以下方法附加x y值:
TR_position.append(QString::number(xvalue));
当我尝试使用以下命令调用它时:
ui->TR_position->setPixmap(QPixmap(":/images/missspace.png"));
…它显然不起作用。有没有办法键入case it,或者使用字符串的内容作为Qlabel名称?您手动输入并命名了200个标签小部件?不要让任何人说您懒惰。:) 根据您的更新,您现在可以使用。您认为需要的是从名称中获取QLabel指针,这将是两件事的组合:
- 从
QString
- 从
QWidget
QWidget* cellWidget = ui->findChild(TR_position);
QLabel* cellLabel = qobject_cast<QLabel*>(cellWidget);
cellLabel->setPixmap(QPixmap(":/images/missspace.png"));
通过像QWidget一样的行为以及维护一段内部状态,这有双重职责。然后GameMap小部件可以使用这些GameCell的QGridLayout:
class GameMap : public QWidget {
Q_OBJECT
public:
static const int Rows = 10;
static const int Columns = 10;
GameMap (QWidget* parent = 0) :
QWidget (parent)
{
layout = new QGridLayout (this);
for (int column = 0; column < Columns; column++) {
for (int row = 0; row < Rows; row++) {
GameCell* cell = new GameCell (this);
cells[column][row] = cell;
layout->addWidget(cell, row, column);
}
}
}
private:
GameCell* cells[Columns][Rows];
QGridLayout* layout;
};
我不会在这里写一个完整的游戏,也不会让它看起来很花哨。这只是要点,展示了如何以编程方式设置200个标签:
在我的代码中,从(x,y)坐标获取GameCell不需要平均50个字符串比较。由于二维数组的形式化和可预测性,索引到单元格[x][y]
只需要一次乘法操作和一次加法操作。没有悲观情绪,你可以简单地写:
cells[x][y].setState(GameCell::Miss);
附录:首先,为每个网格单元创建一个QWidget并不一定是正确的做法。有些人可能会认为是“重量级人物”。如果你的游戏是在一个巨大的虚拟瓷砖空间中进行的,那么它可能会太慢。您可能会发现这一点很有用,从长远来看,哪一种方法更合适:
然而,使用QWidgets对于10x10网格来说并不是什么大问题,所以如果你想坚持使用它,那么你可以。如果你打算这样做,那么至少你不应该把它们全部用手放好 如果你的代码没有达到你期望的效果,你应该在你的问题中加入一个简短的版本。但是首先尝试得到一个简单的程序,它只是一个QLabel,就像链接中一样。如果这不起作用,那么问题可以集中在找出原因,而不必担心网格或板!)@HostileFork,yeap hand命名了200个标签实际上因为有两个游戏板,我喜欢在运行时构建网格的想法,但不确定如何进行,因为我是Qt的新手。据我所知,如果你使用Qt designer,你会在这类事情上打自己的脚。你在帖子中提到的最后一段是如何编码的?我还没有找到与之匹配的示例?添加了一个当前网格的图像,通过代码手动执行此操作会有多大不同?我真的很喜欢你的想法,因为那才是我真正想要的。我试图使用标签名称来交换pixmaps,但老实说,您的方法似乎更好。非常感谢您,如果您需要访问代码,我也可以这样做,因为我拥有自己的服务器。@user1067830我已经重新组织了您的问题,并将裁剪后的图像与文本内联。您提供的代码是否可以编译?(如果是的话,我会很惊讶。)这是学校的项目还是你为了好玩而做的事情?@HostileFork..谢谢,这篇文章看起来干净多了!!我喜欢。在map.h上,在这一点上,它或多或少是伪的,显然使用[i][j]的标签名+将不起作用,但我只是想展示我的想法。我想使用小部件创建您提到的数组,并使用两个测试按钮测试它,以在这两个按钮之间切换,模拟“getboardupdate”。您建议的最后一种方法是,这是否会在每个循环中创建一个新的数组?谢谢你的帮助。
class GameMap : public QWidget {
Q_OBJECT
public:
static const int Rows = 10;
static const int Columns = 10;
GameMap (QWidget* parent = 0) :
QWidget (parent)
{
layout = new QGridLayout (this);
for (int column = 0; column < Columns; column++) {
for (int row = 0; row < Rows; row++) {
GameCell* cell = new GameCell (this);
cells[column][row] = cell;
layout->addWidget(cell, row, column);
}
}
}
private:
GameCell* cells[Columns][Rows];
QGridLayout* layout;
};
class Game : public QDialog
{
Q_OBJECT
public:
Game (QWidget *parent = 0)
: QDialog(parent)
{
targetMap = new GameMap (this);
fleetMap = new GameMap (this);
verticalSeparator = new QFrame (this);
verticalSeparator->setFrameShape(QFrame::VLine);
verticalSeparator->setFrameShadow(QFrame::Sunken);
layout = new QHBoxLayout (this);
layout->addWidget(targetMap);
layout->addWidget(verticalSeparator);
layout->addWidget(fleetMap);
setLayout(layout);
setWindowTitle(tr("Battleship"));
}
private:
GameMap* targetMap;
QFrame* verticalSeparator;
GameMap* fleetMap;
QHBoxLayout* layout;
};
cells[x][y].setState(GameCell::Miss);