Qt: update pixmap grid layout with 2d array values?

Let no one call you lazy. :) Per your update, you now know how to use QLabel::setPixmap(). What you think you need is getting a QLabel pointer from a name, which would be is a combination of two things: QWidget::findChild to get a QWidget* from a QString qobject_cast to get a QLabel* from a QWidget If you go down this path, what you'd wind up with is something like: QWidget* cellWidget = ui->findChild(TR_position); QLabel* cellLabel = qobject_cast(cellWidget); cellLabel->setPixmap(QPixmap(":/images/missspace.

Png")); But BEWARE! There are many things wrong with this approach.It's brittle: What if there doesn't happen to be any widget with that name (mysterious crash)? Or even worse, what if there are multiple widgets with that name and this code marches along blissfully ignorant of that odd condition that is likely a bug?

It's poor OOP: While there are some decent cases to use dynamic casting (or "downcasting"), it usually indicates a flaw in a design. You know that all QLabels are QWidgets, but not all QWidgets are QLabels...so that qobject_cast call might return NULL. It's just one more point of failure.

Sometimes you can't avoid this, but really there is no reason your program needs to be structured in such a way.It's terribly slow: Searching for a widget by its name is essentially a naive recursive search. If you've set aside a separate widget frame for your each grid and only search that, Qt will have to do 100 string compares to find the last element (so 50 in the average case). Imagine clearing the grid with a loop...now you're talking about 100*50 string compares!

All these things are avoidable. Just as it's possible to use loops to set the images on the controls by name, it's possible to use loops to create the widgets in the first place. You basically would leave the area for the game board blank in the design tool, and then dynamically create the controls with code...attach them to the layout with code...and save pointers to them in 2D array.(You wouldn't access them by label name at that point, you'd index them just as you are indexing your board.) You could create your own class derived from QLabel (such as a GameCell class) which contained the information for your board cell and methods related to it.

Then you wouldn't need an array of label widgets in parallel to an array representing your board. You'd simply have one array of objects that took care of both aspects of the implementation. UPDATE: Since you asked in the comments for specifics, here's a GameCell class: class GameCell : public QLabel { Q_OBJECT public: enum State { Undiscovered, Miss }; GameCell (QWidget *parent = 0) : QLabel (parent), currentState (Undiscovered) { syncBitmap(); } State getState() const { return currentState; } void setState(State newState) { if (currentState!

= newState) { currentState = newState; syncBitmap(); } } private: void syncBitmap() { // you'd use setPixmap instead of setText switch (currentState) { case Undiscovered: setText("U"); break; case case Miss: setText("M"); break; } } State currentState; }; This does double duty by behaving like a QWidget as well as maintaining a piece of internal state. Then a GameMap widget can use a QGridLayout of these GameCells: 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 addWidget(cell, row, column); } } } private: GameCell* cellsColumnsRows; QGridLayout* layout; }; If you wanted to, you could just leave spaces in your layout in the designer you wanted to fill in with the GameMap widget. Or you can push on and do the whole thing programmatically.

For the sake of simplicity I'll just put two boards next to each other with a vertical separator on the surface of a dialog: 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; }; I'm not going to write a whole game here or make it look fancy. That's just the gist, showing how to get 200 labels up in a programmatic fashion: With my code, getting a GameCell from an (x,y) coordinate doesn't require an average of 50 string compares. Due to the formalized and predictable nature of 2D arrays, indexing into cellsxy only requires a single multiply operation and a single addition operation.

There's no downcasting, and you can simply write: cellsxy. SetState(GameCell::Miss); ADDENDUM: Creating a QWidget for each grid cell isn't necessarily the way to go in the first place. Some might consider that "heavyweight".

If your game were being played out on a large virtual space of tiles then it could be much too slow. You might find it useful to look into QGraphicsGridLayout, which could be a more appropriate approach in the long run: http://doc.qt.nokia.com/stable/graphicsview-basicgraphicslayouts.html Using QWidgets won't be much of an issue with a 10x10 grid, however, so if you want to just stick with that then you can. If you're going to do it that way, then at least you shouldn't be placing them all by hand!

If you have code that isn't doing what you expect, you should put a short version of it in your question. But first try to get a simple program that's just one QLabel, like in the link. If that doesn't work, then the question can focus on figuring out why without having to worry about grids or boards!) – HostileFork Dec 1 at 1:54 @ HostileFork, yeap hand named 200 labels actually since two game boards, I like the idea about haveing the grid being built at runtime, but unsure how to go about this since I am a newbie with Qt.

From what I understand if you use Qt designer you shoot yourself in the foot on these sort of things. How would code up the last paragraph that you mention in your post? I haven't found an example matching that yet?

– Wuts.the. Martyr Dec 1 at 2:00 added an image of what the current grid looks like, how different would it be to do this manually through code? I really like your idea since that was what I was actually going for.

I was trying to use the label names to swap pixmaps out but your method seems even better honestly. Thank you so much, I really hope you can show me how to do this, if you need access to the code I can make that happen as well, since I host my own server. – Wuts.the.

Martyr Dec 1 at 2:11 @user1067830 I've reorganized your question a bit and put the cropped image inline with the text. Does the code you've provided compile?(I'd be surprised if it did.) Is this a project for school or something you are doing for fun? – HostileFork Dec 1 at 3:00 @HostileFork..Thank you, The post looks much cleaner!

I like it. On the map. H, no its more or less pseudo at this point, obvious the label name + using ij will not work, but I just wanted show the idea I was working with.

I would like to create the array you mention using the widgets and test it with the two test buttons to swap between the two, simulating a "getboardupdate". The last method you suggested, does this create a fresh array each loop? Thanks for the help.

– Wuts.the. Martyr Dec 1 at 3:19.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions