Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt QGridLayout - removing item spacing

Tags:

c++

qt

I am trying to write an implementation of battleship in Qt and I am using two QGridLayouts for containing QToolButtons that are used to represent players' grids. The top-level layout (QMainWindows one) is a QHBoxLayout. What I want to accomplish is to remove the spacing between these buttons. This is how it's looking at the moment:

Grid

It definitely isn't pretty. I am adding items into these layouts like this:

QIcon icon;
icon.addFile(QStringLiteral(":/images/Resources/field_blue.png"), QSize(), QIcon::Normal, QIcon::Off);
for (int i = 0; i < dimensions; ++i)
{
    for (int j = 0; j < dimensions; ++j)
    {
        QToolButton* buttonLeft = new QToolButton(this);
        buttonLeft->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
        buttonLeft->setText(QString::number(i) + "-" + QString::number(j));
        buttonLeft->setFixedSize(FIELD_ICON_SIZE + 10, FIELD_ICON_SIZE + 10); // FIELD_ICON_SIZE -> 20
        buttonLeft->setIcon(icon);
        buttonLeft->setIconSize(QSize(FIELD_ICON_SIZE, FIELD_ICON_SIZE));
        buttonLeft->setAutoRaise(true);
        QToolButton* buttonRight = new QToolButton(this);
        buttonRight->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
        buttonRight->setText(QString::number(i) + "-" + QString::number(j));
        buttonRight->setFixedSize(FIELD_ICON_SIZE + 10, FIELD_ICON_SIZE + 10);
        buttonRight->setIcon(icon);
        buttonRight->setIconSize(QSize(FIELD_ICON_SIZE, FIELD_ICON_SIZE));
        buttonRight->setAutoRaise(true);
        _ui.gridLayoutLeft->addWidget(buttonLeft, i, j);
        _ui.gridLayoutRight->addWidget(buttonRight, i, j);
    }
}

I could try using spacers but they leave blank spots which is also not desirable.

like image 594
Venom Avatar asked Aug 29 '14 00:08

Venom


1 Answers

As almost always in programming there are several ways of achieving what you want, so I'll give you my solution which is just another one. If you want to use "buttons" as tiles for your game, you will need to strong-style them, not only make them look the way you want for a specific theme in a specific platform, which is what you're doing now. The default style for QToolButtons is not the same on Mac, Windows, Linux nor the behavior of the auto-rising effect. That's why I recommend to take full control of the button style. I'll include a very basic example you can use to get some ideas and put them in your application.

First I decided to use QPushButtons instead of QToolButtons. The code for populating the left side grid would be like follows:

// ...
for (int i = 0; i < dimensions; ++i)
{
    for (int j = 0; j < dimensions; ++j)
    {
        QPushButton* buttonLeft = new QPushButton(this);
        buttonLeft->setFixedSize(20, 20);
        QToolButton* buttonRight = new QToolButton(this);
        ui->gridLayoutLeft->addWidget(buttonLeft, i + 1, j + 1);

        // ...

    }
}

Notice that I've changed the indexes when adding the buttons to the grid. This is because I will reserve the first row and the first column for the spacers I'll use later to shrink the buttons.

Now, lets set the layout spacing to zero:

ui->gridLayoutLeft->setSpacing(0);

and add the spacers:

enter image description here

    // Vertical spacers
    ui->gridLayoutLeft->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding), 0, 0, 1, dimensions + 2);
    ui->gridLayoutLeft->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding), dimensions + 1, 0, 1, dimensions + 2);

    // Horizontal spacers
    ui->gridLayoutLeft->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 1, 0, dimensions, 1);
    ui->gridLayoutLeft->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 1, dimensions + 1, dimensions, 1);

The buttons are now as joint as they can.

enter image description here

Finally the buttons need to be styled. To do that I prefer to use style sheets. (A lot of information about style sheets can be found in the Qt documentation: The Style Sheet Syntax, Qt Style Sheets Reference, Qt Style Sheets Examples)

QString styleSheet =
    "QPushButton {"
    "  background-color: blue;"
    "  border: none;"
    "}"
    "QPushButton:hover {"
      "background-color: lightblue;"
    "}"
    "QPushButton:pressed {"
      "background-color: red;"
    "}";
setStyleSheet(styleSheet);

The result of this simple style sheet is:

enter image description hereenter image description here

You can play with it until you get a nice behavior, you can even simulate the auto-raising effect but the most important fact is that with this approach your game board should look exactly the same on all Qt supported platforms.

like image 94
mhcuervo Avatar answered Oct 12 '22 19:10

mhcuervo