简体   繁体   中英

Qt - Why can't I trigger mousePressEvent for my custom button in MainWindow

This is my first time to ask on Stack Overflow. If any suggestion about asking question, please let me know. I am very new to Qt, and have some problems while using event. Hope someone can provide any thoughts.

Background:

I have my custom pushButton, which is rxPushButton in rx.h and rx.cpp . I use on_rxPushButton_clicked to change the image and it works pretty well. In MainWindow , I need to use some rx so I include the class rx and I want to detect if I press left button of the mouse, I need to know which rx has been pressed and record its id in int rxId in MainWindow .

Problem:

I tried two ways to achieve my goal, including mousePressEvent and eventFilter . I found that I can't detect the mouse pressed signal on any rx , but I can detect it outside rx in other places in Mainwindow . I wonder if the events will conflict, but when I comment on_rxPushButton_clicked in rx.cpp , MainWindow still doesn't work for the problem. So I presume that maybe the space in the screen occupied by rx will not be in control of MainWindow (I can get Debug message "test1" but not "test2" in my code, check below). How should I do to solve this problem if I need both things (change image in rx and modify one variable in MainWindow )? Or maybe it's just something wrong with my code and how to modify?

I hope to separate them if possible because I still need to include many objects in MainWindow in the future.

Here are some of my related codes:

rx.cpp

void rx::on_rxPushButton_clicked(void)
{
    startLoading();
}

void rx::startLoading(void)
{
    state = 1;
    connect(timer, SIGNAL(timeout()), this, SLOT(loading1()));
    timer->start(LOADING_INTERVAL);
}

void rx::loading1(void)
{
    if(state == 1)
    {
        state = 2;
        ui->rxPushButton->setStyleSheet("border-image: url(:/images/Rx/Rxloading1.png);");
        disconnect(timer, SIGNAL(timeout()), this, SLOT(loading1()));
    }
}

mainwindow.cpp

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

    for(int i = 0 ; i < rxSize ; i++)
    {
        rxList << new rx(this);
        int j = i/rxHorizontalCount;
        rxList[i]->setGeometry(500+(i-j*8)*110,10+j*90,100,90);
    }
    //rxList[0]->installEventFilter(this);
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton)
    {
        qDebug() << "test1";
        if(rxList[0]->rect().contains(event->x(), event->y()))
            qDebug() << "test2";
    }
}

Event propagating prevent you to do it. When mouse is over Button, event sends to button, not to the MainWindow, thats why you never see test2 in debug output.

Since I don't know what do you need it's hard to say what you should do. You can process event in Button and send some signals or whatever, or set event filter and check if target object is your button, and so on.

Any way, read Qt event system docs for better understanding.

Change image in rx

Use QSignalMapper class that bundles signals from QWidgets (class rx) and re-emits them with widget (class rx) parameters corresponding to the object that sent the signal. We connect each button's clicked() signal to the signal mapper's map() slot, and create a mapping in the signal mapper from each button to the button itself. Finally we connect the signal mapper's mapped() signal to the custom widget's(rx object) clicked() signal. When the user clicks a button, the custom widget(rx object) will emit a single clicked() signal whose argument is the button (rx object) the user clicked. Handle the button clicked event in MainWindow::slotButtonsClicked(QWidget *p) function.

Modify n variable in MainWindow:

You can update variable of MainWindow in mousePressEvent function

class MainWindow : public QWidget
   {
    public :
        MainWindow (QWidget *parent);

        QSignalMapper * mapper;

    slots:
        void slotButtonsClicked(QWidget *);

    // ...  
}

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

    for(int i = 0 ; i < rxSize ; i++)
    {
        rxList << new rx(this);
        int j = i/rxHorizontalCount;
        rxList[i]->setGeometry(500+(i-j*8)*110,10+j*90,100,90);
        QObject::connect(rxList[i], SIGNAL(clicked()),mapper,SLOT(map()));

        //Adds a mapping so that when map() is signalled from the sender, the signal mapped(widget ) is emitted.
        mapper->setMapping(rxList[i], rxList[i]);
    }

    QObject::connect(mapper,SIGNAL(mapped(QWidget *)),this,SLOT(slotButtonsClicked(QWidget *)));   
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton)
    {
        qDebug() << "Clicked outside the button";

        //Now you can modify n variable in MainWindow
    }

    MainWindow::mousePressEvent(event);
}

void MainWindow::slotButtonsClicked(QWidget *p)
{
    rx *button = dynamic_cast<rx *>(p);
    button->on_rxPushButton_clicked();

    qDebug() << button <<" clicked on button";

    //Now you can change image in rx 
}

Hope this works :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM