Updating QGridLayouts - c++

Hi guys I'm coding game for my studies and I've big problems with that (My leg was injured and I couldn't go to lessons).
My job is to do simple Battleships game in c++, qt.
I'm in point where logic code is done, but gui is a big mess.
Here's code for gui .cpp file:
#include <QtWidgets>
#include "dialog.h"
Dialog::Dialog()
{
createGraczBox();
createKomputerBox();
createOdpowiedz();
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(graczBox , 0 , 0 );
mainLayout->addWidget(komputerBox , 0 , 1 );
mainLayout->addWidget(Odpowiedz , 0 , 2 );
setLayout(mainLayout);
setFixedSize(800,400);
setWindowTitle(tr("Battleships!"));
}
void Dialog::createGraczBox()
{
graczBox = new QGroupBox(tr("Gracz"));
QGridLayout *layout = new QGridLayout;
for (int j = 0; j < NumGridRows; ++j) {
labels[j] = new QLabel(tr("%0").arg(j+1));
layout->addWidget(labels[j], 0 , j + 1 , Qt::AlignLeft);
}
for (int i = 0; i < NumGridRows; ++i) {
labels[i] = new QLabel(tr("%0").arg(i + 1));
layout->addWidget(labels[i], i + 1, 0);
}
for(int g = 1;g<10;++g)
{
layout->setColumnStretch(g,1);
}
graczBox->setLayout(layout);
}
void Dialog::createKomputerBox()
{
komputerBox = new QGroupBox(tr("Komputer"));
QGridLayout *layout = new QGridLayout;
for (int j = 0; j < NumGridRows; ++j) {
labels[j] = new QLabel(tr("%0").arg(j+1));
layout->addWidget(labels[j], 0 , j + 1 );
}
for (int i = 0; i < NumGridRows; ++i) {
labels[i] = new QLabel(tr("%0").arg(i + 1));
layout->addWidget(labels[i], i + 1, 0);
}
for(int g = 1;g<10;++g)
{
layout->setColumnStretch(g,1);
}
komputerBox->setLayout(layout);
}
void Dialog::createOdpowiedz()
{
Odpowiedz = new QGroupBox(tr("Komendy"));
QFormLayout *layout = new QFormLayout;
xLabel = new QLabel;
QPushButton *zmienna_x_przycisk = new QPushButton(tr("X"));
connect(zmienna_x_przycisk, SIGNAL(clicked()), this, SLOT(setx()));
yLabel = new QLabel;
QPushButton *zmienna_y_przycisk = new QPushButton(tr("Y"));
connect(zmienna_y_przycisk, SIGNAL(clicked()), this, SLOT(sety()));
xLabel->setText(tr("Aktualne X: %1").arg(zmienna_x));
yLabel->setText(tr("Aktualne Y: %1").arg(zmienna_y));
layout->addRow(xLabel);
layout->addRow(zmienna_x_przycisk);
layout->addRow(yLabel);
layout->addRow(zmienna_y_przycisk);
Odpowiedz->setLayout(layout);
}
void Dialog::setx()
{
bool ok_x;
x = QInputDialog::getInt(this, tr("Podaj X:"),
tr(""), 1, 1, 10, 1, &ok_x);
if (ok_x)
x=zmienna_x;
}
void Dialog::sety()
{
bool ok_y;
y = QInputDialog::getInt(this, tr("Podaj Y:"),
tr(""), 1, 1, 10, 1, &ok_y);
if (ok_y)
y=zmienna_y;
}
They way it should work:
I'm choosing x and y by clicking on it.
Choosing numbers in new window.
They should appear in "Aktualne X:/Y:".
When I've x and y, click ok button (he's not there by now).
Computer checking numbers marking it in space Komputer / Gracz.
Reset x and y to 0.
Show text "You missed. Computer missed."
Go on till one'll win.
But I don't know how to make my layout updating itself by other actions. I can't make dowhile work here.

You need to use signals and slots here. Create "OK" button and connect it to a function, that will be used to handle your x and y variables.

Related

Qt5 QPushButton's can't be clicked (?!)

I have an inherited widget game_widget in which I declared 9 QPushButton's that are stored in an array via a method init_ui and a layout widget on which the buttons are supposed to be placed. There is also init_ui function that is called in the constructor. Here are the main elements of the class:
class game_widget : public QWidget
{
Q_OBJECT
public:
// The layout widget for the buttons
QWidget* gridLayoutWidget = new QWidget(this);
QPushButton** fields; // Fields list
QPushButton* field1 = new QPushButton(gridLayoutWidget);
...
QPushButton* field9 = new QPushButton(gridLayoutWidget);
...
private:
void init_ui();
};
Here is init_ui:
void game_widget::init_ui()
{
fields = new QPushButton* [9]; // Fields list
fields[0] = field1;
...
fields[8] = field9;
...
// Preparing layout for the buttons
gridLayoutWidget->setGeometry(QRect(10, 10, 531, 531));
QGridLayout* grid_layout = new QGridLayout(gridLayoutWidget);
// Adding each field to the layout
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
fields[i * 3 + j]->setMaximumSize(QSize(170, 170));
fields[i * 3 + j]->setMinimumSize(QSize(170, 170));
grid_layout->addWidget(fields[i * 3 + j], i, j);
}
}
Now the thing is that those buttons are not even clickable - not to mention that hovering over them doesn't do anything with them as well, there is no animation. Nothing else about them was changed, so their behavior should be normal, but it isn't. If You have the slightest idea what might be going on, please help.
You are creating 9 extra QPushButtons in void game_widget::init_ui(), try the following:
void game_widget::init_ui()
{
QVector <QPushButton*> fields; // Fields list
fields[0] << field1;
...
fields[8] << field9;
...
// Preparing layout for the buttons
gridLayoutWidget->setGeometry(QRect(10, 10, 531, 531));
QGridLayout* grid_layout = new QGridLayout(gridLayoutWidget);
// Adding each field to the layout
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
fields[i * 3 + j]->setMaximumSize(QSize(170, 170));
fields[i * 3 + j]->setMinimumSize(QSize(170, 170));
grid_layout->addWidget(fields[i * 3 + j], i, j);
}
}

QGroupBox's child restricts shrink the form

I have a multiple screen video player, and I just want to keep 16:9 ratio. There is a qgroupbox as a container of a qwidget which plays video in it. I also use qgroupbox to show selected frame by painting border to green. I can't do this on qwidget because rendered video overlaps that. When I have done with resize, I emit a signal with mouseup event to be able to informed about the resize operation completed. Then I calculate new bounds for qwidget to keep 16:9 ratio and apply this values for qwidget. Here is the image to show you how my app looks like:
And here is the code that I use to resize qwidgets:
void playBack::OnWindowResized()
{
float ratio = 16.0f / 9.0f;
float w = playBackplayer_contList.at(0)->size().width(); //qgroupbox's width
float h = playBackplayer_contList.at(0)->size().height();//qgroupbox's height
float currentRatio = w / h;
float newW = 0;
float newH = 0;
if (currentRatio > ratio)
{
newH = h;
newW = h*ratio;
}
else if (currentRatio < ratio)
{
newW = w;
newH = w / ratio;
}
qDebug() << "NEW WIDGET SIZE: " << (int)newW << " x " << (int)newH;
for (int i = 0; i < playBackplayer_widgtList.count(); i++)
{
playBackplayer_widgtList.at(i)->setMinimumSize(newW, newH);
//playBackplayer_widgtList.at(i)->resize(newW, newH);
}
}
This code works perfectly when I enlarge form, but When I want to shrink, It doesn't allow me to do that. Because I set a minimum value for qwidgets. If I don't use setMinimumSize, use resize(w,h) instead, than orientation problems occur. And here is a example for this issue:
This code below shows ctor and this is where I set the layout:
playBack::playBack()
{
playback_player_1_widget = new QWidget;
playback_player_2_widget = new QWidget;
playback_player_3_widget = new QWidget;
playback_player_4_widget = new QWidget;
playback_player_1_widget_cont = new QGroupBox;
playback_player_2_widget_cont = new QGroupBox;
playback_player_3_widget_cont = new QGroupBox;
playback_player_4_widget_cont = new QGroupBox;
playBackplayer_widgtList.append(playback_player_1_widget);
playBackplayer_widgtList.append(playback_player_2_widget);
playBackplayer_widgtList.append(playback_player_3_widget);
playBackplayer_widgtList.append(playback_player_4_widget);
playBackplayer_contList.append(playback_player_1_widget_cont);
playBackplayer_contList.append(playback_player_2_widget_cont);
playBackplayer_contList.append(playback_player_3_widget_cont);
playBackplayer_contList.append(playback_player_4_widget_cont);
int rowcnt = 0;
int colcnt = 0;
for (int i = 0; i < 4; i++)
{
playBackplayer_contList.at(i)->setStyleSheet(QString("border:1px solid #000;background-color:#000;"));
playBackplayer_widgtList.at(i)->setStyleSheet(QString("background-color:#f00;"));
QGridLayout* layout = new QGridLayout;
layout->setRowStretch(0, 1);
layout->setColumnStretch(0, 1);
layout->setRowStretch(2, 1);
layout->setColumnStretch(2, 1);
playBackplayer_widgtList.at(i)->setMinimumWidth(100);
playBackplayer_widgtList.at(i)->setMinimumHeight(100);
playBackplayer_widgtList.at(i)->setMaximumWidth(10000);
playBackplayer_widgtList.at(i)->setMaximumHeight(10000);
layout->addWidget(playBackplayer_widgtList.at(i),1,1);
layout->setMargin(0);
layout->setSpacing(0);
playBackplayer_contList.at(i)->setLayout(layout);
mainLayout->addWidget(playBackplayer_contList.at(i), colcnt, rowcnt);
rowcnt++;
if (rowcnt % 2 == 0)
{
rowcnt = 0;
colcnt++;
}
playBackplayer_widgtList.at(i)->setAcceptDrops(true);
}
}
I have tried various things, I have tried to set size 0 for qwidget before resize, (in mousedownevent) that didn't work, I have tried deleting layout for qgroupbox, after resize happens, create new layout and set it for groupbox, that didn't work, I have tried layout()->adjustSize(), update(), repaint(), all that stuff didn't work. What am I missing? I need helps from you. Any help would be appreciated. Thank you in advance.
Do away with the grid layout inside the container group boxes. Instead, align and resize the video widget with setGeometry
Here is a simple subclass of QGroupBox I made that keeps your desired ratio and always stays in the center:
class RatioGroupBox : public QGroupBox{
Q_OBJECT
public:
RatioGroupBox(QWidget *parent = nullptr) : QGroupBox (parent){
setFlat(true);
setStyleSheet("border:1px solid #000;background-color:#000;");
setMinimumSize(100, 100);
setMaximumSize(10000, 10000);
ratio = 16.0f/9.0f;
ratioWidget = new QWidget(this);
ratioWidget->setStyleSheet("background: #f00;");
ratioWidget->setAcceptDrops(true);
}
protected:
void resizeEvent(QResizeEvent *){//or you can use your own resize slot
float w = width();
float h = height();
float currentRatio = w/h;
float newW(0);
float newH(0);
if (currentRatio > ratio){
newH = h;
newW = h*ratio;
}
else if (currentRatio < ratio){
newW = w;
newH = w / ratio;
}
ratioWidget->setGeometry((w-newW)/2, (h-newH)/2, newW, newH);
}
private:
QWidget *ratioWidget;
float ratio;
};
Your entire ctor will become something like:
playBack::playBack()
{
for(int r=0; r<2; r++){
for(int c=0; c<2; c++){
RatioGroupBox* playback_player_cont = new RatioGroupBox;
mainLayout->addWidget(playback_player_cont, c, r);
playBackplayer_contList.append(playback_player_cont);
}
}
}
You can of course access your video widgets by exposing ratioWidget any way you like. Either by making it public or creating a getter function.

QChart log axis data not shown

I have a 2Y Axis plo with a QValueAxison the y1 and QLogValueAxis on y2.
The linear plot is shown, the log plot is not shown. The data for both is the same.
I wonder how to set up the ticks and limits for the log axis?
This is the code:
chart = new QChart();
chart->legend()->hide();
chart->setTitle("Histogramm");
axisX = new QValueAxis;
axisX->setLabelFormat("%g");
chart->addAxis(axisX, Qt::AlignBottom);
series = new QLineSeries;
chart->addSeries(series);
axisY = new QValueAxis;
axisY->setTitleText("linear scale");
axisY->setLinePenColor(series->pen().color());
chart->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisX);
series->attachAxis(axisY);
serieslog = new QLineSeries;
chart->addSeries(serieslog);
axisY3 = new QLogValueAxis();
axisY3->setTitleText("logarithmic scale");
axisY3->setBase(10.0);
axisY3->setLinePenColor(serieslog->pen().color());
chart->addAxis(axisY3, Qt::AlignRight);
serieslog->attachAxis(axisX);
serieslog->attachAxis(axisY3);
chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
// Create a layout and add Chart
QGridLayout *layout = new QGridLayout(this);
layout->addWidget(chartView);
void WidgetHistogramm::setData(const std::vector<int> data)
{
if (data.size() <= 0)
{
LOG_DEBUG() << "Histogram Data empty";
return;
}
auto max = *max_element(std::begin(data), std::end(data));
QVector<QPointF> points(data.size());
for(std::vector<int>::size_type i = 0; i != data.size(); ++i) {
points[i] = QPointF(i, data[i]*100/max);
}
series->replace(points);
serieslog->replace(points);
chart->axisX(series)->setRange(0, data.size());
chart->axisY(series)->setRange(0, 100);
chart->axisX(serieslog)->setRange(0, data.size());
chart->axisY(serieslog)->setRange(-1000, 1);
}
The range does not refer to the scaled values, but to the actual values, for example in your case it should be from epsilon to 100. On the other hand the values that are shown in the logarithmic scale must be positive, in your case I see that there is zeros so a possible solution is to add an epsilon:
void WidgetHistogramm::setData(const std::vector<int> data)
{
if (data.size() <= 0){
LOG_DEBUG() << "Histogram Data empty";
return;
}
auto max = *max_element(std::begin(data), std::end(data));
QVector<QPointF> points(data.size());
for(std::vector<int>::size_type i = 0; i != data.size(); ++i) {
points[i] = QPointF(i, data[i]*100.0/max + std::numeric_limits<qreal>::epsilon());
}
series->replace(points);
serieslog->replace(points);
chart->axisX(series)->setRange(0, points.size());
chart->axisY(series)->setRange(0, 100);
chart->axisX(serieslog)->setRange(0, points.size());
chart->axisY(serieslog)->setRange( std::numeric_limits<qreal>::epsilon(), 100);
}

QT QTableWidget::item() returns nullptr even when widget assigned to it

This is driving me nuts. Here's the relevant code:
//Inside UI class
QTableWidget *table_view;
Later,
QLabel* lb_param_id = new QLabel(this);
lb_param_id->setText(QString::number(param_id));
QLabel* lb_param_name = new QLabel(this);
lb_param_name->setText(QString(param_name));
QLineEdit* te_value = new QLineEdit(this);
te_value->setText(QString(value));
QPushButton* pb_command = new QPushButton();
pb_command->setText("Change");
...
if(ui->table_view->rowCount() <= param_id)
ui->table_view->setRowCount(param_id + 1);
ui->table_view->setCellWidget(param_id, 0, lb_param_id);
ui->table_view->setCellWidget(param_id, 1, lb_param_name);
ui->table_view->setCellWidget(param_id, 2, te_value);
ui->table_view->setCellWidget(param_id, 3, pb_command);
for(int i =0; i < ui->table_view->rowCount(); ++i)
{
for(int j = 0; j < ui->table_view->columnCount(); ++j)
{
QTableWidgetItem* item = ui->table_view->item(i, j);
//Here, item is nullptr. Why?
item->setForeground(QColor::fromRgb(255,255,255));
}
}
I set widgets, then try to change foreground of all widgets inside QTableWidget. However, what is returned from ui->table_view->item() is nullptr. What is going on here? btw, The column count is set at initialization.
Add following few lines of code.
if(ui->table_view->rowCount() <= param_id)
ui->table_view->setRowCount(param_id + 1);
ui->table_view->setColumnCount(4);
ui->table_view->setItem(param_id, 0, new QTableWidgetItem());
ui->table_view->setItem(param_id, 1, new QTableWidgetItem());
ui->table_view->setItem(param_id, 2, new QTableWidgetItem());
ui->table_view->setItem(param_id, 3, new QTableWidgetItem());
ui->table_view->setCellWidget(param_id, 0, lb_param_id);
...
Basically, you need to insert the data into the cell first before you can set widget. In your case, you don't have meaning fully data.
Inspecting the qt source, this is the how setCellWidget() imaplemented:
void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
{
QModelIndex index = model()->index(row, column, QModelIndex());
QAbstractItemView::setIndexWidget(index, widget);
}
Without setting the cell first, the model index is invalid index. I agree qt should insert the data if returned index is invalid. For now, you have to work with qt code.

Correctly implementing a custom QWidget in Qt

I'm completely new to Qt/GUI programming and I'm trying to create the UI for a simple Tic Tac Toe game. I created two custom QWidget classes. My main window class (GameWindow) extends the base QWidget, and my other class XOSpace extends QFrame. XOSpace serves two purposes: dividing up the board into spaces (each one will have a HLine or VLine shape), and being a starting point for drawing X's and O's in the correct spot on the board (as soon as I can figure out how to use Qt painters and paint events). My problem is that when I add the XOSpaces to GameWindow they don't display. But when I added QFrame objects from the base class as a test, they displayed fine. How do I extend QFrame (or any widget class), and still make sure it will function the same as the base classes in Qt? Are there any functions I need to reimplement? Anything else?
class XOSpace : public QFrame {
Q_OBJECT
private:
XO xo ; //enum representing whether this space holds an X, O, or blank
public:
explicit XOSpace(QWidget *parent = 0) ;
explicit XOSpace(QWidget *parent, int size, QFrame::Shape) ;
~XOSpace();
void setXO(XO) ;
};
XOSpace::XOSpace(QWidget *parent) : QFrame(parent) {
this->xo = XO::blank ;
this->setGeometry(QRect());
this->setFrameShape(QFrame::HLine) ;
this->setFrameShadow(QFrame::Sunken) ;
this->setMinimumWidth(96) ;
this->setLineWidth(1) ;
this->show();
}
XOSpace::XOSpace(QWidget* parent, int size, QFrame::Shape shape) : QFrame(parent) {
this->xo = XO::blank ;
this->setGeometry(QRect());
this->setFrameShape(shape);
this->setFrameShadow(QFrame::Sunken);
this->setMinimumWidth(size) ;
this->setLineWidth(1) ;
this->show() ;
}
QSize XOSpace::sizeHint() const {
return this->size();
}
void XOSpace::setXO(XO xo) {
this->xo = xo ;
}
XOSpace::~XOSpace() {
;
}
namespace Ui {
class GameWindow;
}
class GameWindow : public QWidget {
Q_OBJECT
private:
Ui::GameWindow *ui ;
//these don't display:
vector<XOSpace*>* hSpaces ;
//these do:
QFrame* vLineOne ;
/* declare 7 more
like this */
public:
explicit GameWindow(QWidget *parent = 0);
~GameWindow();
friend class XOSpace ;
};
GameWindow::GameWindow(QWidget *parent) : QWidget(parent),
ui(new Ui::GameWindow) {
ui->setupUi(this);
this->setWindowTitle("Hello world!");
QGridLayout *mainLayout = new QGridLayout() ;
mainLayout->setColumnMinimumWidth(0, 25);
mainLayout->setColumnMinimumWidth(6, 25);
this->setLayout(mainLayout) ;
QPushButton* button = new QPushButton("Play") ;
button->setFixedWidth(100);
mainLayout->addWidget(button, 2, 3) ;
QGridLayout* secondaryLayout = new QGridLayout() ;
mainLayout->addLayout(secondaryLayout, 1, 1, 1, 5);
QGroupBox* gBox = new QGroupBox() ;
secondaryLayout->addWidget(gBox, 0, 0);
QGridLayout* boardLayout = new QGridLayout() ;
gBox->setLayout(boardLayout);
hSpaces = new vector<XOSpace*>() ;
vLineOne = new QFrame() ;
vLineOne->setGeometry(QRect());
vLineOne->setFrameShape(QFrame::VLine);
vLineOne->setFrameShadow(QFrame::Sunken);
vLineOne->setMinimumHeight(96) ;
/*repeat for vLines 2-4
*/
vLineFive = new QFrame() ;
vLineFive->setGeometry(QRect());
vLineFive->setFrameShape(QFrame::VLine);
vLineFive->setFrameShadow(QFrame::Sunken);
vLineFive->setMinimumHeight(48);
/*repeat for vLines 6-8
*/
for(vector<XOSpace*>::size_type i = 0 ; i < 6 ; i++) {
hSpaces->push_back(new XOSpace(this, 96,
QFrame::HLine));
}
//horizontal spaces: (don’t display properly)
boardLayout->addWidget(hSpaces->at(0), 0, 0,
Qt::AlignBottom);
boardLayout->addWidget(hSpaces->at(1), 0, 2,
Qt::AlignBottom);
boardLayout->addWidget(hSpaces->at(2), 0, 4,
Qt::AlignBottom);
boardLayout->addWidget(hSpaces->at(3), 3, 0, Qt::AlignTop);
boardLayout->addWidget(hSpaces->at(4), 3, 2, Qt::AlignTop);
boardLayout->addWidget(hSpaces->at(5), 3, 4, Qt::AlignTop);
//vertical spaces: (display OK)
boardLayout->addWidget(vLineOne, 0, 1) ;
boardLayout->addWidget(vLineFive, 1, 1) ;
boardLayout->addWidget(vLineTwo, 0, 3) ;
boardLayout->addWidget(vLineSix, 1, 3) ;
boardLayout->addWidget(vLineThree, 2, 1) ;
boardLayout->addWidget(vLineSeven, 3, 1) ;
boardLayout->addWidget(vLineFour, 2, 3) ;
boardLayout->addWidget(vLineEight, 3, 3) ;
mainLayout->setRowStretch(0, 1);
//set rows and columns stretch
mainLayout->setVerticalSpacing(0) ;
//set spacing etc.
}
GameWindow::~GameWindow() {
delete ui;
if (hSpaces != nullptr) {
for(vector<XOSpace*>::size_type i = 0 ; i < hSpaces->size() ; i++) {
if (hSpaces->at(i) != nullptr) {
delete hSpaces->at(i) ;
}
}
delete hSpaces ;
}
}
The XOSpaces are supposed to be drawn as horizontal line segments that will make up the two horizontal lines on a tic tac toe board. Here's what my application looks like now:
Here is a lot of little pieces of advice. The first GUI or two that you make in Qt will probably be pretty hard to do. Using layouts, like you have started doing will help quite a bit.
So here are the first couple recommendations I would give:
Don't call show in your xospace constructors. Adding them to a layout, makes it the parent's job to show it. So in your main when you call gameWindow->show(); it handles all the showing of nested elements.
QLabel is a subclass of QFrame. Change the elements in question to be of type QLabel and then add in setText("X") to their constructor or somewhere to make sure you can see your elements.
If you aren't using a the UI form, I would leave it out.
Based on your game layout, this is what your variables look like:
// vL1 vL2
// hs0 vL6 hs1 vL5 hs2
// vL3 vL4
// hs3 vL7 hs4 vL8 hs5
// ??? ???
Instead of relying on the size of these vertical and horizontal lines for your stretching and size constraints, why not use the elements that will sit on the board, like in spots marked with an X below:
// X vL1 X vL2 X
// hs0 vL6 hs1 vL5 hs2
// X vL3 X vL4 X
// hs3 vL7 hs4 vL8 hs5
// X ??? X ??? X
This would allow you to take two and span them across the grid.
boardLayout->addWidget(vLines.at(0), 0, 1, 5, 1) ;
boardLayout->addWidget(vLines.at(1), 0, 3, 5, 1) ;
mainLayout->setRowStretch(1, 1);
Then like I hint above, you could use a QList or a QVector to remove so much copy and paste code.
vLines.append(new QFrame);
vLines.append(new QFrame);
foreach(QFrame * f, vLines)
{
//f->setGeometry(QRect());
f->setFrameShape(QFrame::VLine);
f->setFrameShadow(QFrame::Sunken);
f->setMinimumHeight(96);
}
Also setGeometry() is useful if you aren't using layouts. And setting the geometry to QRect(), is probably equivalent to the default constructor it has.
And when you start putting object trees together, you don't have to worry as much about how they clean up:
http://qt-project.org/doc/qt-4.8/objecttrees.html
EDIT:
Here is how I would layout the board:
QGridLayout * board = new QGridLayout();
for(int r = 0; r < 5; r++)
{
for(int c = 0; c < 5; c++)
{
if(r % 2 == 1)
{
if(c % 2 == 1)
{
// is an intersection
// leave it blank?
// or add a box?
}
else
{
// is a horizontal line
QFrame * f = new QFrame();
f->setFrameShape(QFrame::HLine);
f->setFrameShadow(QFrame::Sunken);
f->setMinimumWidth(96);
board->addWidget(f,r, c);
}
}
else
{
if(c % 2 == 1)
{
// is a vertical line
QFrame * f = new QFrame();
f->setFrameShape(QFrame::VLine);
f->setFrameShadow(QFrame::Sunken);
f->setMinimumHeight(96);
board->addWidget(f, r, c);
}
else
{
// is an XO location
board->addWidget(new QLabel(), r, c, Qt::AlignCenter);
}
}
}
}
setLayout(board);
Then if you just let QGridLayout manage your item's location and access, you do something like this:
void GameWindow::setXO(QString val, int r, int c)
{
// upper left xo location is 0,0
// lower right xo location is 2,2
// we map to skip the frame locations
if(r > 2 || r < 0 || c < 0 || c > 2)
{
qDebug() << "Error in setXO" << r << c;
return;
}
QLabel * xo = qobject_cast<QLabel*>(board->itemAtPosition(r*2, c*2)->widget());
if(xo != 0)
{
xo->setText(val);
}
}
Hope that helps.