QT 2-dimensional array graphical grid - c++

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();

Related

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.

Qt programming QComboBox

I am using Qt and C++ to add some features to a freeware called: EASYPAINT.
I had to add a more intuitive method in which the users can see the actual width directly from the tool instead of changing numbers. ( just like in the new windows paint , where you can actually see the line thickness and not pixels.)
I am using a QComboBox. My question is (look at the code first), instead of having 20 (penSizeList->addItem), I know we can have addItems.... But what about the icon. for each Item, will I have to search for 20 different line thickness.png and add them? Or is there another method I can use?
And also, how can I get rid of the string in addItem, and only keep an image or icon in the QComboBox.
QComboBox *penSizeList = new QComboBox();
penSizeList->setIconSize(QSize(100,100));
penSizeList->setStatusTip("Pen Size");
QIcon ONEpxIcon(":/media/actions-icons/clear-gray.png");
QIcon THREEpxIcon(":/media/instruments-icons/canvas-lines1.png");
penSizeList->addItem(ONEpxIcon,"1px");
penSizeList->addItem(THREEpxIcon,"2px");
penSizeList->addItem(THREEpxIcon,"3px");
penSizeList->addItem(THREEpxIcon,"4px");
penSizeList->addItem(THREEpxIcon,"5px");
penSizeList->addItem(THREEpxIcon,"6px");
penSizeList->addItem(THREEpxIcon,"7px");
penSizeList->addItem(THREEpxIcon,"8px");
penSizeList->addItem(THREEpxIcon,"9px");
penSizeList->addItem(THREEpxIcon,"10px");
penSizeList->addItem(THREEpxIcon,"11px");
penSizeList->addItem(THREEpxIcon,"12px");
penSizeList->addItem(THREEpxIcon,"13px");
penSizeList->addItem(THREEpxIcon,"14px");
penSizeList->addItem(THREEpxIcon,"15px");
penSizeList->addItem(THREEpxIcon,"16px");
penSizeList->addItem(THREEpxIcon,"17px");
penSizeList->addItem(THREEpxIcon,"18px");
penSizeList->addItem(THREEpxIcon,"19px");
penSizeList->addItem(THREEpxIcon,"20px");
connect(penSizeList,SIGNAL(activated(int)), this, SLOT(penValueChanged(int)));
Try to do this in loop.
penSizeList->addItem(ONEpxIcon,"1px");
for(int i = 2; i < 21 ; i++)
{
penSizeList->addItem(THREEpxIcon,QString("%1px").arg(i));
}
Or if you have different icons for each line:
for(int i = 1; i < 21 ; i++)
{
penSizeList->addItem(QIcon(QString("iconLine%1.png").arg(i)),QString("%1px").arg(i));
}
If you want only icons, set empty string:
penSizeList->addItem(icon,"");
If you want full image then you should set this image as background. For example:
QPixmap pxmap("G:/2/qt.jpg");
QStandardItemModel *md = new QStandardItemModel;
QStandardItem *iii = new QStandardItem;
iii->setBackground(QBrush(Qt::red));
iii->setText("ss");
QStandardItem *iiii = new QStandardItem;
iiii->setBackground(QBrush(pxmap));
iiii->setText("ss");
md->setItem(1,0,iii);
md->setItem(0,0,iiii);
ui->comboBox->setModel(md);

How to make a 2d Array in QT?

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);
}
}
[..]

Spacing between widgets in QHBoxLayout

I'm trying to create a GUI with QtCreator. For this GUI, I need to display several images with different sizes next to each other. These images should be touching each other.
I use a QWidget with a QHBoxLayout, where I add the labels (with different sizes) containing the images.
According to related questions, I should use setSpacing and setContentsMargin to remove these spaces, but that won't work; I tried several times.
Here's the code:
QWidget *widget = new QWidget(ui->tagcloud);
QHBoxLayout * l = new QHBoxLayout(widget);
ui->tagcloud->setWidget(widget);
for(int i=0;i<list.size();++i)
{
QLabel *lab = new QLabel;
QPixmap pic((list[i].imgPath).c_str()); //This fetches the image
int sizeChange = 50 + (2*list[i].percent); //Calculates the size of the image
lab->setFixedSize(QSize(sizeChange, sizeChange));
lab->setPixmap(pic);
lab->setScaledContents(true);
l->addWidget(lab);
l->setSpacing(0);
}
However, when I run this, the spacing remains the same (i.e. definitely not zero).
If I add more labels to the layout, the spacing seems to get smaller.
Can anyone explain or help me? Thanks!
Setting spacing to 0 and adding stretch before and after works for me :
l->addStretch();
for(int i = 0; i < list.size(); ++i)
{
QLabel *lab = new QLabel;
QPixmap pic((list[i].imgPath).c_str()); //This fetches the image
int sizeChange = 50 + (2*list[i].percent); //Calculates the size of the image
lab->setFixedSize(QSize(sizeChange, sizeChange));
lab->setPixmap(pic);
lab->setScaledContents(true);
l->addWidget(lab);
}
l->addStretch();
l->setSpacing(0);
Also this works I think
l->setSizeConstraint(QLayout::SetMaximumSize);

Add widgets to QFileDialog

I need to add a widget (QTableWidget) into QFileDialog's layout. I know that it is QGridLayout with sizes (3,4). The table must be in 3-rd row and span all columns.
QTableWidget* tableWidget = new QTableWidget(this);
QGridLayout *layout = static_cast<QGridLayout*>(QFileDialog::layout());
layout->addWidget(tableWidget, 2, 0, 1, 4);
With this code the original 3-rd row which contains lineEdit and save/open pushButton disappears. How can I add widgets between already existing widgets of QGridLayout so that original widgets remain in the layout.
I strongly recommend you not to rely on QFileDialog's implementation. The layout can be different on different platforms or different versions of Qt. It may be more correct to place your table under the dialog or to the right of it. This can be done easily without altering the layout of the QFileDialog itself. Just create a QVBoxLayout and put QFileDialog and QTableWidget inside it.
However, the question has been asked, and the solution exists. QGridLayout has no functionality such as QBoxLayout::insertItem. So we need to implement this behavior manually. The plan is:
Obtain the list of layout items placed in 3rd and 4th rows.
Calculate new positions of items.
Take elements out of item and add them back at new positions.
Working code:
QFileDialog* f = new QFileDialog();
f->setOption(QFileDialog::DontUseNativeDialog, true); //we need qt layout
QGridLayout *layout = static_cast<QGridLayout*>(f->layout());
QList< QPair<QLayoutItem*, QList<int> > > moved_items;
f->show();
for(int i = 0; i < layout->count(); i++) {
int row, column, rowSpan, columnSpan;
layout->getItemPosition(i, &row, &column, &rowSpan, &columnSpan);
if (row >= 2) {
QList<int> list;
list << (row + 1) << column << rowSpan << columnSpan;
moved_items << qMakePair(layout->takeAt(i), list);
i--; // takeAt has shifted the rest items
}
}
for(int i = 0; i < moved_items.count(); i++) {
layout->addItem(moved_items[i].first,
moved_items[i].second[0],
moved_items[i].second[1],
moved_items[i].second[2],
moved_items[i].second[3]);
}
QTableWidget* tableWidget = new QTableWidget();
layout->addWidget(tableWidget, 2, 0, 1, 4);