Make a game board
-
Hi,
I've been trying to make a 10x10 board for a game I'm writing. I thought about using
QGraphicsRectItem
within aQGraphicsGridLayout
. Each rectangle would be a cell for the board.I can't have manage to display anything and I don't understand how this grid layout should be used. It seems it should be used with a scene but I don't get how to display the scene, I thought about putting it as a widget's attribute but still no luck.
Is there a place with examples of such layouts within an application? The experience has been pretty jarring so far.
Thanks
-
Hi,
You don't show a scene. You use a QGraphicsView to show the content of the scene.
-
So I have to have a view, sets its layout to a grid and add all the items to the view itself, is that right?
-
@NullFunction
No, you just have to set theQGraphicsView
to view your scene, you place things on the scene and the view shows them. No layouts or grids here, justsetPos()
on theQGraphicsItem
s where yo want them, to be. -
@JonB I'm getting lost here. I'd like to build a simple window that shows a board of 10x10 rectangles of the same size.
Each rectangle will be a cell that will either have a piece on it or be free.
I don't understand the structure of how to show the board.
Should the top-level object be an application, a widget or a dialog? Should it have a QGraphicsView as attribute and if so, how do I place my rectangles inside the view?
I'm new to Qt and it's difficult to find examples that have a consistent structure.
-
@NullFunction said in Make a game board:
I'd like to build a simple window that shows a board of 10x10 rectangles of the same size.
If you are struggling, you could just use
QTableWidget
as a base instead of the QGraphics framework and set the number of rows and columnsI don't understand the structure of how to show the board.
QGraphicsView
is the projector,QGraphicsScene
is the movie. neither work alone. If you want to use that framework you have to first build the movie (theQGraphicsScene
) with your objects and then tell the projector (theQGraphicsView
) what part you want it to displayShould the top-level object be an application, a widget or a dialog?
You need an instance of
QApplication
but that's not a top level item, that just takes care of the event loop, if you want a dialog useQDialog
if you want a window with potentially menus, toolbars, statusbars and docked widgets then useQMainWindow
if you want just a generic one, useQWidget
Should it have a QGraphicsView as attribute
QGraphicsView
is a class, not an attribute, that ultimately inherits fromQWidget
(this is pure C++, nothing to do with Qt)I'm new to Qt and it's difficult to find examples that have a consistent structure.
Qt examples are of good quality tbh
-
QGraphicsView is a class, not an attribute, that ultimately inherits from QWidget (this is pure C++, nothing to do with Qt)
That's not what I mean, I was asking if the top-level object (for example a
QGraphicsWidget
) should have theQGraphicsView
as a member.This is what I mean when I'm asking about the structure, right now this works but it doesn't feel right.
#include "widget.h" Widget::Widget(QGraphicsWidget *parent) : QGraphicsWidget(parent) { QGraphicsScene *scene = new QGraphicsScene; this->graphicsView.setScene(scene); QGraphicsGridLayout *layout = new QGraphicsGridLayout; this->setLayout(layout); for (size_t i = 0; i < 10; i++) { for (size_t j = 0; j < 10; j++) { QGraphicsRectItem *rec = new QGraphicsRectItem(0, 0, 80, 80); rec->setBrush(Qt::darkGreen); rec->setPos(i * 85, j * 85); scene->addItem(rec); } } graphicsView.resize(850, 850); } void Widget::show() { graphicsView.show(); }
-
@NullFunction said in Make a game board:
That's not what I mean, I was asking if the top-level object (for example a
QGraphicsWidget
) should have theQGraphicsView
as a member.This is a "wrong" question, and similarly for your code. A
QGraphicsWidget
The
QGraphicsWidget
class is the base class for all widget items in a QGraphicsScene.QGraphicsWidget
is an extended base item that provides extra functionality overQGraphicsItem
.So they are widget-items which you place on a
QGraphisScene
. You are thinking they are a "top-level object", "should have theQGraphicsView
as a member", and your code creates anew QGraphicsScene
, and putsQGraphicsRectItem
on it. This is not what they are about at all.Start by forgetting about
QGraphicsWidget
, I've never used one and I don't see why you would here.Let's try again:
-
You want a single
QGraphicsScene
. No more, no less. That is the "canvas" for graphics. It is not aQWidget
. Indeed, it has no visual appearance. -
You will add
QGraphicsItem
-derived objects (e.g.QGraphicsRectItem
s) onto theQGraphicsScene
. These are things which have a shape, size & position. There are no "layouts" or "grids", you use their size & position to determine where they appear, such as lined up in rows or columns. -
You will want a
QGraphicsView
. That is the visual object, which shows yourQGraphicsScene
and theQGraphicsItem
s on it. In your case you will want one and only one (other can have multiple views attached to one scene, e.g. to view separate areas of a large scene or to zoom in on some area of the scene, but you don't need that.) This is aQWidget
. You can place in somewhere, e.g. on a layout on aQMainWindow
, or (like anyQWidget
) you can have it standalone as its own entire window, as yu please. This is what "I was asking if the top-level object" should be referring to --- either theQGraphicsView
itself, or some other widget with a layout you choose to put it onto.
The very simplest one could need is shown in the minimal example at https://doc.qt.io/qt-5/qgraphicsscene.html#details:
QGraphicsScene scene; scene.addText("Hello, world!"); QGraphicsView view(&scene); view.show();
-
-
Thanks for the answer, I'm starting to get it.
So, in short, the view is the widget and I add content to the scene, which I tell the view to display?
So in the case of my example, I could get rid of the widget altogether and just have the view and the scene.
This was the first step of my project, once I have the board, I also have to place pieces on it, interactively. The end result would be something like this
|-----------------------------------------------------------------| | File Start Restart Turn of player: RED| |-----------------------------------------------------------------| | | | | | | | | | | Board | | | | | | | | | | | | | | | | | | | | | | | | | | |-----------------------------------------------------------------|
With the board in the middle, as a grid of rectangles (the board cells), side panels to stock the pieces and add them onto the board interactively, once the side panels are empty, the game can start.
A top bar with menu like items and relevant information about the game.Should each item here (top menu bar, side panels, boards) be
QGraphicsView
objects with their own layout, plugged into an encompassingQApplication
?Thanks for the help
-
@NullFunction said in Make a game board:
Should each item here (top menu bar, side panels, boards) be QGraphicsView objects with their own layout, plugged into an encompassing QApplication ?
Yes to all you said except for this! Your
Board
area is aQGrapchicsView
, with aQGraphicsScene
attached to it. Everything else is not, they are widgets/layouts/whatever, e.g. see what aQMainWindow
is composed of. I repeat once again: you want oneQGraphicsScene
with oneQGraphicsView
, and anything which produces more than that is not right for your case. The graphics stuff is only in yourBoard
area, nowhere else. -
Thanks that makes sense!
I'm a bit worried about the pieces, they'll have to be drag-n-drop'ed from the side panel to the board, that'll call from a redisplay of the side panel (to show the piece isn't there anymore) and a redisplay of the board (to show there's now a new piece on there).
Do you have a comment on what kind of object I should use for the piece? I was thinking about inheriting from a
QGraphicsItem
but I also need to draw each piece in a different color and with a different shape (just like chess with kings, queens, rooks, etc). butQGraphicsPixMapItem
seems appropriate as well.Thanks
-
@NullFunction
QGraphicsItem
is an abstract class,QGraphicsPixMapItem
is derived from it. Yes, you will create instances of the latter with the pixmap of the pieces as required. Those will be added to the scene, theGraphicsView
will then show them automatically.For the "side panel with pieces", you would either have to create (probably) a separate scene + view for them, or I would probably use some kind of
QListView
orQLabel
s (i.e. widgets) with the pieces' pixmaps on them. You then have to implement the drag & drop between those and theGraphicsView
for the board. You will not add the actual widget you drag, you will create aQGraphicsPixmapItem
from its pixmap to place on theQGraphicsScene
. -
@NullFunction
You should read through Graphics View Framework.
Also I believe the example code at Drag and drop from QListWidget onto QGraphicsItem might be of help for what you want. -
I did read the View page as well as a guide on the Model/View for Qt but the problem, at least to me, is that it often implies some knowledge on the structure or logic of Qt. I had never used it before and as you saw above, I'm not sure how to structure the code.
Thanks for the reference