Mapping binary buttons in the order they are placed on a Widget
-
@jensig What does handleButton(int) do?
Why do you create a new QTextEdit every time instead of reusing the existing one?
The spacing inside the text edit is wrong probably because you don't use a font with fix spacing.
Thisbool Widget::isChecked(QPushButton *btn) { if (btn->isChecked()) return true; return false; }
can be simplified to
bool Widget::isChecked(QPushButton *btn) { return btn->isChecked(); }
-
connect(&mapper, SIGNAL(mapped(int)), this, SIGNAL(handleButton(int)));
So, you want to emit a signal when mapped(int) signal is emitted - is that correct?
"I don't understand what you mean when you say to reuse the existing QTextEdit?" - do you want to create a text edit for each button row?
-
@jsulm
In regards to mapping, all I want is to have all the values of each button (indexed 0 to 59) in a QVector<QString> or anything else so I would be able to retrieve them when a user presses on "calculate".
When a user presses any of the buttons, it is able to modify the text on the QPushButton to "0" or "1", so I want their values in order or indexed in a QVector<QString> or anything else when we press on "calculate"."So, you want to emit a signal when mapped(int) signal is emitted - is that correct?"
I am very confused about the utilization of signals so I really can't tell if to be able to retrieve the values I need to emit a signal.
"do you want to create a text edit for each button row?"
No, only one QTextEdit at the end to show all values on the buttons like so:
1011
1100
1000
1111Thank you
-
@jensig said in Mapping binary buttons in the order they are placed on a Widget:
No, only one QTextEdit at the end to show all values on the buttons like so:
Then do not create a new text edit each time a button is pressed.
Change this line
connect(&mapper, SIGNAL(mapped(int)), this, SIGNAL(handleButton(int)));
to
connect(&mapper, SIGNAL(mapped(int)), this, SLOT(mapped(int)));
And implement mapped slot where you get the index of the button as parameter:
void Widget::mapped(int index) { ... }
-
Hi @jensig
are you sure, you want to do this without lambdas?
Would make this so, so much easier:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QVector> class QTextEdit; class QPushButton; class QGridLayout; class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = nullptr); private: QVector<QVector<QPushButton*>> btns; QGridLayout *layout_; QTextEdit *textEdit; }; #endif // WIDGET_H
#include "widget.h" #include <QGridLayout> #include <QTextEdit> #include <QPushButton> static const unsigned SIZE_LONG = 15; static const unsigned SIZE_BITS = 4; Widget::Widget(QWidget *parent) : QWidget(parent) { layout_ = new QGridLayout; textEdit = new QTextEdit(); textEdit->resize(100,100); textEdit->show(); for (int i = 0; i < SIZE_LONG; ++i) { QVector<QPushButton*> btnRow; for (int j = 0; j < SIZE_BITS; ++j) { QPushButton *btn = new QPushButton("0"); btn->setCheckable(true); layout_->addWidget(btn,i,j,Qt::AlignHCenter); connect(btn, &QPushButton::toggled, this, [=](bool checked){ btn->setText(checked ? "1" : "0"); textEdit->clear(); for(int x(0); x < btns.size(); x++){ QString line; for(int y(0); y < btns.at(x).size(); y++){ line.append(btns.at(x).at(y)->text()); } textEdit->append(line); } }); btnRow.append(btn); } btns.append(btnRow); } setLayout(layout_); }
-
@J.Hilk
Hi , thanks for the simplification.
I changed your code a little but I can't figure out how to put a QTextEdit when a "Calculate" button is pressed like in the picture above.Is there any particular reason why you've written QTextEdit, QPushButton, QGridLayout in a forward declaration instead of includes?
#include "widget.h" #include <QGridLayout> #include <QTextEdit> #include <QPushButton> static const unsigned SIZE_LONG = 15; static const unsigned SIZE_BITS = 4; Widget::Widget(QWidget *parent) : QWidget(parent) { layout_ = new QGridLayout; textEdit_ = new QTextEdit(); textEdit_->resize(100, 100); //textEdit_->show(); QPushButton *btnCalculate = new QPushButton("Calculate"); btnCalculate->setCheckable(true); for (unsigned i = 0; i < SIZE_LONG; ++i) { QVector<QPushButton*> btnRow; for (unsigned j = 0; j < SIZE_BITS; ++j) { QPushButton *btn = new QPushButton("0"); btn->setCheckable(true); layout_->addWidget(btn, i, j, Qt::AlignHCenter); if (i == SIZE_LONG - 1 && j == SIZE_BITS - 1) { layout_->addWidget(btnCalculate, i + 1, j, Qt::AlignRight); } connect(btn, &QPushButton::toggled, this, [=](bool checked){ btn->setText(checked ? "1" : "0"); textEdit_->clear(); for(int x = 0; x < btns_.size(); x++){ QString line; for(int y = 0; y < btns_[x].size(); y++){ line.append(btns_[x][y]->text()); } textEdit_->append(line); } }); connect(btnCalculate, &QPushButton::toggled, this, [=](bool calculate){ if (calculate == false) layout_->addWidget(textEdit_, 0, SIZE_BITS + 1, Qt::AlignHCenter); }); btnRow.append(btn); } btns_.append(btnRow); } setLayout(layout_); }
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QVector> class QTextEdit; class QPushButton; class QGridLayout; class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = nullptr); private: QVector<QVector<QPushButton*>> btns_; QGridLayout *layout_; QTextEdit *textEdit_; }; #endif // WIDGET_H
Thank you
-
@J.Hilk
I couldn't prevent QTextEdit from changing the spacing between rows when it is called with the QPushButton "Calculate" (see image in my first post). Spacing between rows 1, 2 & 3 change when QTextEdit is placed there. I tried to follow @jsulm 's advice but I think he refers to spacing inside QTextEdit and not the spacing between the rows of buttons.
I've also tried to follow the documentation without much result Qt5 Layouts.I tried this, but it crashes instantly:
The rest of my code is identical to my previous post, where I changed your code.connect(btnCalculate, &QPushButton::toggled, this, [=](bool calculate){ if (calculate) { vLayout_->addWidget(textEdit_); // from QVBoxLayout *vLayout_; groupBox_->setLayout(vLayout_); // from QGroupBox *groupBox_; layout_->addWidget(groupBox_, 0, SIZE_BITS + 1, Qt::AlignRight); // from QGridLayout *layout_; //layout_->setSpacing(0); } });
The program has unexpectedly finished. The process was ended forcefully.
Thank you
-
Ok @jensig ,
as a general rule of thumb, don‘t dynamically create widgets in slots such as "button clicks", that‘s bad design and will end up slowing down your application pretty fast and you may loose oversight of what widget was created and still needs to be deleted. Etc.That said, you can create the QTextEdit during the Button setup and refere it later on.
But, QPushButtons have by default a fixed height and placing the QTextEdit into the gridlayout will result in „streched „ rows like you have it in the op.
Two solutions I can think of:
- Nesting layouts
Place your gridlayout and the QTextEdit as Widgets in a QHorizontalLayout. That should solve your issue
- stretching the QTextEdit over all rows of the Gridlayout
For that I‘ll adjust my example code:
Right after the QPushbutton create loop:... layout_->addWidget(TextEdit,0,SIZE_BITS,SIZE_LONG,1);
addWidget has an overload that allows colmns and rows that it shall span:
void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = ...)
Edit: fixed obious spelling mistakes, creating posts at 1 am on an iPad is apparently not the best idea.