Search code examples
c++qtqt5qpushbuttonqlineedit

QPushButton color change in QLineEdit eventFilter


I would like to make a push button visible when I insert a number in one of the lineedit. The button and linedit are on the same row. I know the position or name of the lineedit but i dont know how to link back to the push button to make it visible or to be able to change color.

If you look in the eventFilter thats where I'm stuck and I need some help. Thank you

#include "mainwindow.h"
#include "ui_mainwindow.h" 
#include <QLineEdit>
#include <QPushButton>
#include <QGridLayout>
#include <QLabel>
#include <QRegion>
#include <QLayoutItem>
#include <QList>
#include<QObject>
#include <QEvent>
#include <QKeyEvent>
#include <QModelIndexList>
#include <QKeySequence>
#include <QSignalMapper>
#include<QIntValidator>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);


        ui->scrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
        ui->scrollArea->setWidgetResizable( true );

        QWidget *widget = new QWidget(this);
        ui->scrollArea->setWidget( widget );

        QGridLayout *gridLayout = new QGridLayout();
        widget->setLayout( gridLayout );


    QPushButton *button[20];

    for (int i = 0; i < 20; i++)
    {
        QLabel *label = new QLabel( QString( "%1" ).arg( i ) );
        gridLayout->addWidget(label,i,1,1,1 );
        gridLayout->setColumnMinimumWidth(1, 100);
        gridLayout->setColumnMinimumWidth(2, 10);

        if (i==5)
        {
            QLineEdit *lineEdit = new QLineEdit;
            gridLayout->addWidget(lineEdit,i,5,1,1);

        } else
        {
        QLineEdit *lineEdit = new QLineEdit(this);
        gridLayout->addWidget(lineEdit,i,3,1,1);
        lineEdit->setValidator(new QIntValidator(0,100,this));
        lineEdit->setObjectName(QString::number(i));
        lineEdit->installEventFilter(this);


        gridLayout->setColumnMinimumWidth(4, 25);
        gridLayout->setColumnMinimumWidth(5, 50);
        gridLayout->setColumnMinimumWidth(6, 25);

        QLineEdit *lineEdit_B = new QLineEdit;
        gridLayout->addWidget(lineEdit_B,i,7,1,1);
        lineEdit_B->setValidator(new QIntValidator(0,100,this));

        gridLayout->setColumnMinimumWidth(8, 10);
        }


        gridLayout->setColumnMinimumWidth(9, 10);
        button[i] = new QPushButton();
        gridLayout->addWidget(button[i],i,10,1,1);
        gridLayout->setColumnStretch(10,20);

        button[i]->setFixedHeight(20);
        button[i]->setFixedWidth(20);
        button[i]->setStyleSheet("background-color:red;");
        button[i]->setText(QString::number(i));

        QRegion* region = new QRegion(*(new QRect(button[i]->x(),button[i]->y(),15,15)),QRegion::Ellipse);
        button[i]->setMask(*region);
        button[i]->setVisible(false);

        gridLayout->setColumnMinimumWidth(10, 50);
        gridLayout->setColumnMinimumWidth(11, 10);

    }

  }


MainWindow::~MainWindow()
{
delete ui;
}


bool MainWindow::eventFilter(QObject * obj, QEvent *event)// *event)
{
    if (event->type() == QEvent::KeyPress)
    {
      ui->lineEdit->setText(QString("%1").arg(obj->objectName()));
      QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
          qDebug() << "key " << keyEvent->key() << "from" << obj;

  // HERE'S WHERE I NEED HELP
      QPushButton* button = ui->scrollArea->findChild<QPushButton*>();  

  // I think here I would use a for loop to match the listedit 
  // with a number with the corresponding push button.
  // When i find the push button I set it to yellow.

   }
   return QObject::eventFilter(obj, event);

   }




   void MainWindow::on_pushButton_clicked()
   {

   }

Solution

  • It is not necessary to use eventFilter, you complicate the task since it is difficult to discriminate which element it is. One possible option is to use the textChanged signal to display the button.

    Also you had many tasks that are executed many times in the loop unnecessarily, those tasks that do not depend on the index must be out.

    Also if you are going to store buttons do not use arrays, use containers like QList.

    Also, you should not create pointers indiscriminately, since it is your responsibility to eliminate them, for example, QRegion is passed by value to setMask(), so it is not necessary to create a pointer.

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QGridLayout>
    #include <QLabel>
    #include <QLineEdit>
    #include <QPushButton>
    #include <QScrollArea>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        ui->scrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
        ui->scrollArea->setWidgetResizable( true );
    
        QWidget *widget = new QWidget(this);
        ui->scrollArea->setWidget( widget );
    
        QGridLayout *gridLayout = new QGridLayout(widget);
    
        for(int i=0; i<20; i++){
            QLabel *label = new QLabel(QString::number(i));
            gridLayout->addWidget(label, i, 1);
    
            QPushButton *button = new QPushButton(QString::number(i));
            gridLayout->addWidget(button,i,10,1,1);
            button->setFixedSize(20, 20);
            button->setStyleSheet("background-color:red;");
    
            QRegion region(QRect(button->pos(),QSize(15,15)),QRegion::Ellipse);
            button->setMask(region);
            button->hide();
    
            if(i==5){
                QLineEdit *lineEdit = new QLineEdit;
                gridLayout->addWidget(lineEdit,i,5);
    
                connect(lineEdit, &QLineEdit::textChanged, [button](const QString &text){
                    button->setVisible(!text.isEmpty());
                });
            }
            else{
                QLineEdit *lineEdit_A = new QLineEdit;
                gridLayout->addWidget(lineEdit_A,i,3);
                lineEdit_A->setValidator(new QIntValidator(0,100,this));
    
                QLineEdit *lineEdit_B = new QLineEdit;
                gridLayout->addWidget(lineEdit_B,i, 7);
                lineEdit_B->setValidator(new QIntValidator(0,100,this));
    
                connect(lineEdit_A, &QLineEdit::textChanged, [button](const QString &text){
                    button->setVisible(!text.isEmpty());
                });
                connect(lineEdit_B, &QLineEdit::textChanged, [button](const QString &text){
                    button->setVisible(!text.isEmpty());
                });
            }
        }
    
        gridLayout->setColumnMinimumWidth(1, 100);
        gridLayout->setColumnMinimumWidth(2, 10);
        gridLayout->setColumnMinimumWidth(4, 25);
        gridLayout->setColumnMinimumWidth(5, 50);
        gridLayout->setColumnMinimumWidth(6, 25);
        gridLayout->setColumnMinimumWidth(8, 10);
        gridLayout->setColumnMinimumWidth(9, 10);
        gridLayout->setColumnStretch(10,20);
        gridLayout->setColumnMinimumWidth(10, 50);
        gridLayout->setColumnMinimumWidth(11, 10);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    The complete example can be found in the following link.