In a for loop, I can construct a string.
foreach (...) {
QString str = "pushButton" + QString::number(count);
// this gives pushButton1
// Now I want to get the button widget that has this string as it's variable name
// and modify it in some way, e.g. change it's button caption
str->setText("New Title");
count ++;
}
Is this possible? if so, then how
edited: here's how i created the buttons
for (int i=0; i<total; i++) {
QPushButton *btn = new QPushButton();
btn->setObjectName("pushButton" + QString::number(i));
ui->horizontalLayout->addWidget(btn);
}
You can get the button through the parent and objectName, in your case the parent is this, so you should use the following:
QWidget* p = ui->horizontalLayout->parentWidget();
for(int count=0; count<total; count++){
const QString str = "pushButton" + QString::number(count);
QPushButton* btn = p->findChild<QPushButton *>(str);
btn->setText("someText");
}
Related
I have a little problem displaying my layouts. I have an application that contains a GridLayout, HBoxLayout, and VBoxLayout.
The HBoxLayout contains: a button and line edit
The GridLayout contains: progbars (1-99)
The HBoxLayout and the GridLayout are put in a VBoxLayout
My problem is when I click, The grid layout appears on the HBoxLayout. It's like the HBoxLayout wasn't a part of the VBoxLayout. So, even when I destroy the layout and create it again, I still have the same problem.
An image is displayed below to better understand my problem.
code: window.cpp
Window::Window(QWidget *parent) :
QWidget(parent){
label = NULL;
progressbar = NULL;
workerThread = NULL;
m_counter = NULL;
layout = new QHBoxLayout(NULL);
lineEdit = new QLineEdit(NULL);
m_button = new QPushButton("click", NULL);
time= new QTimer(this);
lineEdit-> setInputMask("00");;
//lineEdit->setGeometry(400,10,160,30);
lineEdit->setPlaceholderText("N between 1 & 99");
// Create and position the button
// m_button->setGeometry(100, 10, 150, 30);
QIcon icon("/home/ca/Downloads/chauvin.png");
m_button->setIcon(icon);
m_button->setIconSize(QSize(100, 30));
m_button->setToolTip("this is a beautifull button ");
//layout = new QFormLayout;
layout->addWidget(m_button);
layout->addWidget(lineEdit);
setLayout( layout );
// showTime();
time->start(1000);
setWindowTitle(tr("Digital Clock"));
// NEW : Do the connection
connect(m_button, &QPushButton::pressed, this , &Window::slotButtonPressed);}
void Window::slotButtonPressed(){
layoutgrid = new QGridLayout(NULL);
m_button->setEnabled(true);
QString contenu = lineEdit->text();
int i_contenunumber= contenu.toInt(0,10);
m_counter= new int[i_contenunumber];
memset( m_counter, 0, i_contenunumber );
label = new QLabel*[ i_contenunumber ];
progressbar = new QProgressBar*[ i_contenunumber ];
workerThread= new mythread*[ i_contenunumber ];
int x= 0;
int y= -1;
int i=0;
m_button->setText("Checked");
for(i=0;i< i_contenunumber ;i++)
{
if (i%5==0)
{
x=0;
y++;
}
int i_Randomvalue = rand() % 500 + 100;
// label[i] = new QLabel(NULL);
// //label[i]->setGeometry(100*x*1.7, 80+(50*y), 160, 30);
// label[i]->setText("Tread" + QString::number(i_Randomvalue));
// label[i]->setVisible(true);
progressbar[i] = new QProgressBar(NULL);
progressbar[i]->setRange(0, 100);
progressbar[i]->setOrientation(Qt::Horizontal);
//progressbar[i]->setGeometry(100*x*1.7,60+(50*y),150,30);
progressbar[i]->setValue(0);
progressbar[i]->setVisible(true);
layoutgrid->addWidget(progressbar[i],y,x);
setLayout(layoutgrid);
workerThread[i] = new mythread(i_Randomvalue, i);
connect(workerThread[i], &mythread::signalemit, this, &Window::barprogress);enter code here
connect(workerThread[i], &mythread::signalFinThread, this, &Window::findethread);
workerThread[i] ->start();
x++;
m_counter[i]=0;
}
// Window::setFixedSize(1000,120+(50*y-1));
removeLayout();
layoutvbox = new QVBoxLayout(NULL);
layoutvbox->addLayout(layout);
layoutvbox->addLayout(layoutgrid);
setLayout(layoutvbox);
adjustSize();
}
void Window::removeLayout ( void )
{
QLayout* po_l_layout = QWidget::layout ();
if (po_l_layout != 0)
{
QLayoutItem *item;
while ((item = po_l_layout->takeAt(0)) != 0)
po_l_layout->removeItem (item);
delete po_l_layout;
}
}
delete layout will not work here because it will not delete all the containing widgets
Instead just create a new widget that contains the layout
m_widget = new QWidget();
QGridLayout *outerLayout = new QGridLayout(m_widget);
m_layout->addWidget(m_widget);
this->setLayout(m_layout);
to remove and rebuild just delete the widget
delete m_widget
deleting a widget deletes all sub layouts and widgets contained by the widget
Once the layout of your widget is set, you can not change it unless you remove the old layout. My suggestion is to delete the old layout
//remove all of layouts widgets here
delete layout
Then create the QVBoxLayout and call setLayout(layoutvbox)
If you wish to switch back and forth, just recreate/delete when needed.
I want to display users avatars to treewidget items as icons. I get avatars path and other users info from the database and store it in QVector with the structure.
MyDB *employeesAccountsDB = new MyDB();
connect(employeesAccountsDB, &MyDB::accountInfo, [this](QVector<AccountData> dataVector) {
for (int i = 0; i < dataVector.size(); i++) {
QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
item->setSizeHint(0, QSize(40, 40));
item->setText(0, dataVector[i].avatarPath);
item->setText(1, dataVector[i].username);
item->setText(2, dataVector[i].email);
item->setText(3, dataVector[i].group);
emit avatarPath(dataVector[i].avatarPath);
}
dataVector.clear();
});
Info is a GUI class.
NetManager *avatarNetManager = new NetManager();
connect(this, &Info::avatarPath, avatarNetManager, &NetManager::getAvatar);
connect(avatarNetManager, &NetManager::image, [this](QPixmap avatar, int index) {
QIcon avatarIcon;
if (!avatar.isNull()) {
avatarIcon = avatar.scaled(80, 80);
} else {
avatarIcon = QPixmap(":/Icon/default_avatar.png").scaled(80, 80);
}
qDebug() << index;
treeWidget->topLevelItem(index)->setIcon(0, avatarIcon);
});
int index = 0; // initialized as global variable in the `NetManager` constructor
void NetManager::getAvatar(QString path, int index)
{
networkManager = new QNetworkAccessManager(this);
networkManager->get(QNetworkRequest(QUrl(path)));
connect(networkManager, &QNetworkAccessManager::finished, [this](QNetworkReply *avatarNetReply) {
QPixmap avatarPixmap;
avatarPixmap.loadFromData(avatarNetReply->readAll());
emit image(avatarPixmap, index);
index++;
avatarNetReply->close();
avatarNetReply->deleteLater();
networkManager->deleteLater();
emit finished();
});
}
For example, first icon is Ok, third icon should be on the second item and second icon should be on third item.
I need something to maintain the order of the icons.
All works well but the avatars don't relate to the users. Any ideas how to collect and retrieve them to the appropriate user? Thanks.
Updated:
INDEX: 2
QPixmap(QSize(1280, 720),depth=32,devicePixelRatio=1,cacheKey=0xee000002d0)
INDEX: 0
QPixmap(QSize(380, 400),depth=32,devicePixelRatio=1,cacheKey=0xf000000190)
INDEX: 1
QPixmap(QSize(277, 400),depth=32,devicePixelRatio=1,cacheKey=0xf200000190)
INDEX: 0
QPixmap(QSize(380, 400),depth=32,devicePixelRatio=1,cacheKey=0xed00000190)
INDEX: 2
QPixmap(QSize(1280, 720),depth=32,devicePixelRatio=1,cacheKey=0xf0000002d0)
INDEX: 1
QPixmap(QSize(277, 400),depth=32,devicePixelRatio=1,cacheKey=0xf200000190)
Indices change every time application launches.
Code:
MyDB *employeesAccountsDB = new MyDB();
connect(employeesAccountsDB, &MyDB::accountInfo, [this](QVector<AccountData> dataVector) {
for (int i = 0; i < dataVector.size(); i++) {
QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
item->setSizeHint(0, QSize(40, 40));
item->setText(0, dataVector[i].avatarPath);
item->setText(1, dataVector[i].username);
item->setText(2, dataVector[i].email);
item->setText(3, dataVector[i].group);
emit avatarPath(dataVector[i].avatarPath, i);
}
dataVector.clear();
});
void NetManager::getAvatar(QString path, int index)
{
networkManager = new QNetworkAccessManager(this);
networkManager->get(QNetworkRequest(QUrl(path)));
connect(networkManager, &QNetworkAccessManager::finished, [this, index](QNetworkReply *avatarNetReply) {
QPixmap avatarPixmap;
avatarPixmap.loadFromData(avatarNetReply->readAll());
emit image(avatarPixmap, index);
avatarNetReply->close();
avatarNetReply->deleteLater();
networkManager->deleteLater();
emit finished();
});
}
NetManager *avatarNetManager = new NetManager();
connect(this, &Info::avatarPath, avatarNetManager, &NetManager::getAvatar);
connect(avatarNetManager, &NetManager::image, [this](QPixmap avatar, int index) {
QIcon avatarIcon;
if (!avatar.isNull()) {
avatarIcon = avatar.scaled(80, 80);
} else {
avatarIcon = QPixmap(":/Icon/default_avatar.png").scaled(80, 80);
}
qDebug() << index;
treeWidget->topLevelItem(index)->setIcon(0, avatarIcon);
});
I have fixed it by QString variable to hold the avatar path and QStringList to hold other user info and when image is retrieved from the path I do the following:
MyDB *employeesAccountsDB = new MyDB();
connect(employeesAccountsDB, &MyDB::accountInfo, [this](QPixmap avatar, QStringList accountInfo) {
QIcon avatarIcon;
if (!avatar.isNull()) {
avatarIcon = avatar.scaled(80, 80);
} else {
avatarIcon = QPixmap(":/Icon/default_avatar.png").scaled(80, 80);
}
QTreeWidgetItem *item = new QTreeWidgetItem(treewidget);
item->setIcon(0, avatarIcon);
item->setSizeHint(0, QSize(40, 40));
for (int i = 0; i < accountInfo.size(); i++) {
item->setText(i, accountInfo.at(i));
}
});
All works well.
I would like to get a number of a QTableWidget row after selecting some topic in comboBox how it is possible to get the row, thanks.
void MainWindow::metto_stringa(int i)
{
QWidget *w = qobject_cast<QWidget *>(sender()->parent());
if(w)
{
int row = ui->tableWidget->indexAt(w->pos()).row();
ui->lineEdit->setText(QString::number( row ));
}
// ui->lineEdit->setText(QString::number( i ));
}
else if(i == 3)
{
// ui->tableWidget->setCellWidget(ui->tableWidget->rowCount(), i, "");
QString s = "Normal";
QComboBox *combo = new QComboBox;
combo->addItem("Below normal");
combo->addItem("Normal");
combo->addItem("Above normal");
combo->addItem("High");
combo->addItem("Real time");
connect(combo,SIGNAL(currentIndexChanged(int)),this,
SLOT(metto_stringa(int)));
ui->tableWidget->setCellWidget(ui->tableWidget->rowCount()-1, i,combo);
/* ui->tableWidget->setCellWidget(i,4,combo);
QTableWidgetItem*item = new QTableWidgetItem(s);
item->setFlags(item->flags() ^ Qt::ItemIsEditable);
ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, i,
item);*/
continue;
}
In this case you should not use the parent of the QComboBox, you must use the same sender()
void MainWindow::metto_stringa(int index)
{
QWidget *w = qobject_cast<QWidget *>(sender());
if(w)
{
int row = ui->tableWidget->indexAt(w->pos()).row();
ui->lineEdit->setText(QString::number(row));
}
}
In the question I answered before I commented that you must access the widget that you use in the setCellWidget() function, in the previous case the widget had the following form:
QWidget <--- QPushButton
parent() sender()
ie you owe to that widget so we take advantage of sender() and parent() in the previous case. In the current case QComboBox is added directly.
i'm working to creat an interface that dynamically generates QgroupeBox with layouts, i get the number of groupebox needed and it perfectly work. now i want to use a button to destroy these groupBoxes for a repeat section of the same action (get the number of groupeBox needed and creat them)
this is the code i used for this:
void interface::on_pushButton_12_clicked(){
int i,k;
ui->pushButton_13->setEnabled(true);
QGroupBox *first = new QGroupBox(this);
QVBoxLayout *test = new QVBoxLayout;
k = recupEdit();
ui->pushButton_12->hide();
ui->lineEdit->hide();
ui->label->hide();
for(i = 1; i<=k;i++)
{
first = creatgroupebox();
test->addWidget(first);
test->addStretch(1);
ui->tab->setLayout(test);
}
}
int interface::recupEdit(){
int k;
QString recup = ui->lineEdit->text();
k = recup.toInt(0,10);
return k;
}
QGroupBox *interface::creatgroupebox()
{
QGroupBox *group = new QGroupBox(this);
QLineEdit *Id = new QLineEdit("Id");
QLineEdit *Data1 = new QLineEdit("Data 1");
QLineEdit *Data2 = new QLineEdit("Data 2");
QLineEdit *Data3 = new QLineEdit("Data 3");
QLineEdit *Data4 = new QLineEdit("Data 4");
QLineEdit *Data5 = new QLineEdit("Data 5");
QLineEdit *Data6 = new QLineEdit("Data 6");
QLineEdit *Data7 = new QLineEdit("Data 7");
QLineEdit *Data8 = new QLineEdit("Data 8");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(Id);
layout->addWidget(Data1);
layout->addWidget(Data2);
layout->addWidget(Data3);
layout->addWidget(Data4);
layout->addWidget(Data5);
layout->addWidget(Data6);
layout->addWidget(Data7);
layout->addWidget(Data8);
group->setLayout(layout);
return group;
}
void interface::on_pushButton_13_clicked()
{
ui->pushButton_12->show();
ui->lineEdit->show();
ui->label->show();
}
You can get all child objects by using QObject::children()
auto gb = new QGroupBox();
gb->setLayout(new QHBoxLayout());
gb->layout()->addWidget(new QLineEdit());
foreach (QObject *o, gb->layout()->children()) {
auto le = qobject_cast<QLineEdit*>(o);
if (!le)
continue;
//do what you need with your linedit
}
Is it what you want?
I am trying to count how many buttons have been checked
void pracownik2::on_pushButton_4_clicked()
{
this->setWindowTitle("EKRAN");
QWidget *centralWidget = new QWidget;
int licznik=1;
QString licz;
QString kolumny = ui->lineEdit->text();
QString wiersze = ui->lineEdit_2->text();
QPushButton *button[wiersze.toInt()][kolumny.toInt()];
QGridLayout *controlsLayout = new QGridLayout;
for(int i=0;i<wiersze.toInt();i++)
{
for(int j=0;j<kolumny.toInt();j++)
{
licz = QString::number(licznik);
licznik++;
button[i][j] = new QPushButton(licz);
button[i][j]->setCheckable(1);
controlsLayout->addWidget(button[i][j], i, j);
}
}
QPushButton *okej = new QPushButton("Zatwierdź");
QPushButton *anul = new QPushButton("Anuluj");
controlsLayout->addWidget(okej, wiersze.toInt(), 0);
controlsLayout->addWidget(anul, wiersze.toInt(), 1);
controlsLayout->setHorizontalSpacing(0);
controlsLayout->setVerticalSpacing(0);
centralWidget->setLayout(controlsLayout);
setCentralWidget(centralWidget);
for(int i=0;i<wiersze.toInt();i++)
{
for(int j=0;j<kolumny.toInt();j++)
{
connect(button[i][j],SIGNAL(toggled(bool)),this,SLOT(tescik()));
}
}
connect(anul,SIGNAL(clicked()),this,SLOT(close()));
connect(okej,SIGNAL(clicked()),this,SLOT(okay2()));
}
void pracownik2::tescik()
{
miejsca++;
}
void pracownik2::okay2()
{
QString m=QString::number(miejsca);
QMessageBox::information(this,"elo","wybranych miejsc: " + m);
}
If i check buttons number 1,2,3 and press okay button it shows that 3 buttons have been checked BUT if I check button number 1 and uncheck it and press okay it shows that 2 buttons have been checked. How to make my variable increment only if I check button, not also when I uncheck it?
I'm sorry for the code edit, just couldn't make it look better
The signal toggled has a boolean parameter, add it to your slot, and adjust count according to it. Change connect:
connect(button[i][j],SIGNAL(toggled(bool)),this,SLOT(tescik(bool)));
And change slot:
void pracownik2::tescik(bool t) {
if (t) miejsca++;
else miejsca--;
}