Qt:使用二维数组值更新pixmap网格布局 我正在使用Visual Studio 2010和QT 4.7(两个Windows)中的C++组合进行游戏。这个游戏是战舰的克隆,是基于控制台输入的。我已经创建了我想要的gui外观,在Qt designer的Qt端,我的gui由一个10x10的网格布局组成,使用标签来保存游戏单元的像素图:

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

我对每个标签进行了精心命名,以表示其在2d阵列中的位置(即舰队地图=>
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数组更新这些像素贴图

  • 循环结构-我能理解
  • 条件语句-我可以理解
  • 处理标签的qt特定语法-新手,所以不知道atm
  • 下面是一些伪代码,我正试图用map.h做这类事情:

    #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);