How to make a 2d Array in QT? - c++

Hi my question is simple, I just asked in the QT Forums but nobody answer to me.
I just wanted to make a 2D array of a QLabel, can somebody help me, All I read about it, they use a dynamic vector, something like this:
<QVector <Data_Type>>
I can't use that (My project don't have to use that yet, crap specifications I know), so I have to use a 2D like in C++ or C.
EDIT: I have the 2D Array but dont know how to show it, All I have is this, and don't give me errors:
QWidget *mainWidget = new QWidget;
QLabel **maze;
maze= new QLabel*[x];
for (int i = 0; i < x; i++) {
maze[i]= new QLabel[y];
}
for(int i=0;i<x;i++){
for(int j=0;j<y;j++){
maze[i][j].setPixmap(test);
maze[i][j].move(i*60,j*60);
}
}
mainWidget->show();
setCentralWidget(mainWidget);
Now I just want to show the images, once I run the project, no images appear, is the Widget thing right? How to show in the Main Window? I need a 2D Widget too?
Thanks for your time.

Assuming that the x and y are number of rows and columns, correspondingly, you can simply do this trick:
[..]
QGridLayout *grid = new QGridLayout;
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
QLabel *label = new QLabel(this);
label->setPixmap("Path_Of_The_Image");
grid.addWidget(label, i, j);
}
}
[..]

Related

How to iterate over and sort QGridLayout items

I have a QGridLayout with 225 children QTextEdit. I need to populate a QString board[15][15] array with their text values based on the position of each QTextEdit. If I was doing this the long way, I would do it like this:
boardArray[0][0] = ui->box0x0->toPlainText();
boardArray[0][1] = ui->box0x1->toPlainText();
boardArray[0][2] = ui->box0x2->toPlainText();
...
That seems like a pretty bad solution. So I decided to iterate over the QTextEdit children of the grid so I could manipulate each one;
QList<QTextEdit*> textEdits = ui->gridLayout->findChildren<QTextEdit *>();
for (QTextEdit* box : textEdits) {
// We don't know where this box is though
board[ ??? ][ ??? ] = box->toPlainText();
}
Unfortunately, there isn't a QTextEdit.row property or anything, so I do not know the order they are in or how I could populate my board array without it being random.
Do y'all have any ideas about how I can organize the QTextEdit widgets into my board array? I wasn't sure how I could do this with that iteration technique.
Iterating over the grid layout should work, something along the following lines (I haven't tested this):
for (int i{0}; i < ui->gridLayout->rowCount(); ++i)
{
for (int j{0}; j < ui->gridLayout->columnCount(); ++j)
{
auto* textEdit{static_cast<QTextEdit*>(ui->gridLayout->itemAtPosition(i, j)->widget()};
board[i][j] = textEdit->toPlainText();
}
}

QTableWidget Checkbox get state and location

How to get state of all checkbox and get row and column of checked?
Onclick PushButton function.
QTableWidget *t = ui->tableWidget;
t->setRowCount(2);
t->setColumnCount(2);
QStringList tableHeader;
tableHeader<<"item01"<<"item02";
t->setHorizontalHeaderLabels(tableHeader);
for (int i = 0; i < t->rowCount(); i++) {
for (int j = 0; j < t->columnCount(); j++) {
QWidget *pWidget = new QWidget();
QHBoxLayout *pLayout = new QHBoxLayout(pWidget);
QCheckBox *pCheckBox = new QCheckBox();
pLayout->setAlignment(Qt::AlignCenter);
pLayout->setContentsMargins(0,0,0,0);
pLayout->addWidget(pCheckBox);
pWidget->setLayout(pLayout);
t->setCellWidget(i, j, pWidget);
}
}
And when I clicked the button, I need get all selected elements with rows, columns of each.
void Widget::on_pushButton_clicked()
{
// Code here
// For example: Selected ["item01", 2]
}
I simply iterate over all cell widgets:
for (int i = 0; i < t->rowCount(); i++) {
for (int j = 0; j < t->columnCount(); j++) {
QWidget *pWidget = t->cellWidget(i, j);
QCheckBox *checkbox = pWidget->findChild<QCheckBox *>();
if (checkbox && checkbox->isChecked())
qDebug() << t->horizontalHeaderItem(j)->text() << i;
}
}
It's been awhile since I've programmed with Qt, but I believe there is not really good way of doing this. I've done all of these solutions with success.
1) Iterate through all the cell widgets like svlasov's answer says. This has some scalability issues.
2) Create hash maps where the pointer to the button is the key and the indices you want are the values. You can get which button was clicked with QObject::sender().
3) Store the indices you want as properties on the button when you create the buttons (see setProperty() in QObject's documentation). For example,
button->setProperty("x index", x);
In your slot, use QObject::sender() to get the pointer to the button and then call
button->property("x");
I've generally found the third option to be the cleanest and best performing.
Note that these answers also work for QTreeWidgets and QListWidgets.

QDialog not auto-reducing to fit it contents

When using a QDialog with dynamic contents, the size of the window may get bigger to better fit the contents.
However, in my case, I'd also like it to auto-reduce it size if the contents become smaller (In my case, a form that may differ regarding the choices made).
How can I reach this behaviour?
Thanks
It can be reproduced by adding two buttons:
void MainWindow::on_pushButton_2_clicked()
{
for (int i=0; i<12; i++) {
QPushButton *button = new QPushButton("Blha");
buttons.push_back(button);
ui->zone->addWidget(button);
}
adjustSize();
}
void MainWindow::on_pushButton_clicked()
{
for (int i=0; i<10; i++)
if (buttons.size()) {
QPushButton *button = buttons.back();
buttons.pop_back();
ui->zone->removeWidget(button);
delete button;
}
adjustSize();
}
If you create the 12 buttons like above and then destroy 10 of them, the size of the window will be really big
Actually, I eventually solved this out by wrapping my contents in a widget (like the centralWidget of a MainWindow) and calling adjustSize() on my widget

QT 2-dimensional array graphical grid

I am making a 2-dimensional grid (2-d Cellular Automaton). So I made full code for console. But now I need to implement that with GUI. I am using linux, so I read out that QT Creator will be the best choice.
Can somebody give me a small tip. How is better to start. Which Views/widjets you recommend to use for that? Any help would be useful.
In c++ code I made a 2-dimensional char array of size 15/15 elements which have elements of type '1' or '0'.
I will be very grateful for any help! Thank you in advance.
One of ways: create a QImage and fill it with your data using setPixel. Convert it to QPixmap and use QLabel to display it.
Below is the two simple examples of how to show arrays on GUI. There are possible other variations too, of course, depending on your needs.
Widget with a grid layout
QWidget *mainWidget = new QWidget;
QGridLayout *layout = new QGridLayout;
for (int r = 0; r < 15; r++) {
for (int c = 0; c < 15; c++) {
QLabel *label = new QLabel("1", mainWidget); // Text could be 1 or 0.
layout->addWidget(label, r, c);
}
}
mainWidget->setLayout(layout);
mainWidget->show();
Using table view
QTableWidget *table = new QTableWidget(15, 15);
for (int r = 0; r < 15; r++) {
for (int c = 0; c < 15; c++) {
QTableWidgetItem *item = new QTableWidgetItem("1"); // Text could be 1 or 0.
table->setItem(r, c, item);
}
}
table->show();

How to pass coordinates of button in matrix to slot on click?

I'm beginning in C++ and Qt. I have a matrix of QPushButtons and I want to handle the click event for them. Problem is I'm not being able to tell the slot the coordinates os the button in the array so that I can play with them. I've succeed in passing a integer to my slot, but not both coordinates. I'm not sure if I'm making myself clear enough... That's my problematic code:
for (int i = 0; i < mapSize_x; i++) {
for (int j = 0; j < mapSize_y; j++) {
buttonsArray[i][j] = new QPushButton();
ui->mainLayout->addWidget(buttonsArray[i][j], i, j);
connect(buttonsArray[i][j], SIGNAL(clicked()),
signalMapper, SLOT(map()));
signalMapper->setMapping(buttonsArray[i][j], i, j); // here
}
}
connect(signalMapper, SIGNAL(mapped(int, int)),
this, SLOT(buttonClick(int, int)));
setMapping only accepts two parameters, and I want to pass three. Is there a workaround? I've googled a lot and still can't find an answer. I've also tried to pass the QPushButton object instead of the coordinates, but unsuccessfully as well. Thanks in advance.
Consider using a QHash to store your pushbuttons, keyed by the buttons themselves and pointing to a pair containing their row and column. You should then be able to set your mapping based on the widget pointer and then look up the associated row and column when the signal mapper emits its signal. For example, declare a class data member as follows:
QHash<QPushButton*, QPair<int, int> > buttonHash;
Then your code above could become
for (int i = 0; i < mapSize_x; i++) {
for (int j = 0; j < mapSize_y; j++) {
QPair<int, int> gridPair(i, j);
QPushButton* button = new QPushButton();
buttonHash.insert(button, gridPair);
ui->mainLayout->addWidget(button, i, j);
connect(button, SIGNAL(clicked()),
signalMapper, SLOT(map()));
signalMapper->setMapping(button, qobject_cast<QWidget*>(button));
}
}
connect(signalMapper, SIGNAL(mapped(QWidget*)),
this, SLOT(buttonClick(QWidget*)));
Finally, your buttonClick slot would become the following:
void SomeClass::buttonClick(QWidget* widget) {
QPair<int, int> pair = buttonHash.value(qobject_cast<QPushButton*>(widget));
int myRow = pair.first;
int myColumn = pair.second;
...
}
There are also at least 2 other ways of tackling this problem:
You could try to combine the row and column into a string and use QSignalMapper::setMapping(QObject*, const QString&). This would then require some logic to pull the row and column out of the string in the buttonClick slot.
You could try to combine the row and column into a single integer by using bit shifting and a bitwise OR. You could then rely on QSignalMapper::setMapping(QObject*, int). This would require some logic to pull the row and column out of the integer in the buttonClick slot.
I won't go into detail about these other solutions because they're somewhat ugly. The solution I provided above remains the most intuitive.
The QSignalMapper class can be very useful in certain circumstances, but it may be overkill for your current use-case.
Instead, consider using a QButtonGroup, which was designed for exactly what you're trying to do, and provides a much cleaner and simpler API.