multiple signals for one slot

10,269

Solution 1

First of all, "It doesn't work" does not mean anything, and it is hard to help you if you do not say what errors you get. Then, there are few problems.

All QObject's derived classes are not copiable, it means you can not do

QWidget a;
QWidget b;
b = a; // Wrong

You should use pointers (or perhaps references).

QWidget a;
QWidget * b = new QWidget(...);
QWidget * c;
c = & a; // Ok
c = b; // Ok

Then your connect calls are wrong:

connect(&up, SIGNAL(clicked()), &up, SLOT(scrollUp()));

The third argument is the object who has the slot. up is a QPushButton, it does not have a scrollUp() slot, it is your MainWindow who does:

connect(&up, SIGNAL(clicked()), this, SLOT(scrollUp()));

(since connect is called in MainWindow's constructor this points to the current MainWindow object).

Also in C++ the single = sign means assignment, for equality comparison use =='. Andsender` is a function.

Your approach should work if implemented in the right way:

class MainWindow: public QWidget
{
    QScrollArea * scroll1;
    QScrollArea * scroll2;
    QWidget * view1;
    QWidget * view2;
    QPushButton * up1;
    QPushButton * up2;
    QPushButton * down1;
    QPushButton * down2;

public:
    MainWindow()
    {
        // Here initialize member variables.
        ...

        connect(up1, SIGNAL(clicked()), this, SLOT(scrollUp()));
        connect(up2, SIGNAL(clicked()), this, SLOT(scrollUp()));
        connect(down1, SIGNAL(clicked()), this, SLOT(scrollDown()));
        connect(down2, SIGNAL(clicked()), this, SLOT(scrollDown()));
    }

public slots:
    void scrollDown()
    {
        QScrollArea * area;
        QWidget * view;

        if(qobject_cast<QPushButton>(sender()) == down1) {
            area = & scroll1;
            view = & view1;
        } else if(qobject_cast<QPushButton>(sender()) == down2) {
            area = & scroll2;
            view = & view2;
        } else {
            // Error.
        }

        // Now `area` and `view` point to the right widgets.
        ...
    }

    void scrollUp()
    {
        // The same as before.
    }
};

Another approach would be to extract the actual scrolling instructions to a separate function:

class MainWindow: public QWidget
{
    // Same variables as before
    ...

public:
    MainWindow()
    {
        // Here initialize member variables.
        ...

        connect(up1, SIGNAL(clicked()), this, SLOT(scrollUp1()));
        connect(up2, SIGNAL(clicked()), this, SLOT(scrollUp2()));
        connect(down1, SIGNAL(clicked()), this, SLOT(scrollDown1()));
        connect(down2, SIGNAL(clicked()), this, SLOT(scrollDown2()));
    }

public slots:
    void scrollDown(QScrollArea * area, QWidget * view)
    {
        // Here you scroll over `area` and `view`.
    }

    void scrollDown1()
    {
        scrollDown(scroll1, area1);
    }

    void scrollDown2()
    {
        scrollDown(scroll2, area2);
    }

    // Again, the same for `scrollUp`.
};

Solution 2

There are several mistakes in your code :

  • About the sender of the signal : There is not a QObject called "sender" but a method QObject * QObject::sender() const; which returns a pointer on the sender of the signal.
  • In the if conditions : you are casting a QPushButton** into a QPushButton ((QPushButton) &sender) and you dont compare that thing with your buttons up(2) and down(2).
  • In your connections between slots and signals : the scrollUp and scrollDown slots do not belong to the QPushButton class but to your MainWindow class.

Finally, you should write something like this :

connect(&up,    SIGNAL(clicked()), this, SLOT(scrollUp()));
connect(&up2,   SIGNAL(clicked()), this, SLOT(scrollUp()));
connect(&down,  SIGNAL(clicked()), this, SLOT(scrollDown()));
connect(&down2, SIGNAL(clicked()), this, SLOT(scrollDown()));

void MainVindow::scrollDown() {
    // [...]

    QPushButton * senderButton = qobject_cast<QPushButton *>(this->sender()); 
    // QPushButton * senderButton = (QPushButton *) this->sender(); works too

    if (senderButton == &down) {
        // [...]
    }

    if (senderButton == &down2) {
        // [...]
    }

    // [...]
}

void MainVindow::scrollUp() {
    // [...]

    QPushButton * senderButton = qobject_cast<QPushButton *>(this->sender());
    // QPushButton * senderButton = (QPushButton *) this->sender(); works too

    if (senderButton == &up) {
        // [...]
    }

    if (senderButton == &up2) {
        // [...]
    }
    // [...]
}
Share:
10,269

Related videos on Youtube

Frank
Author by

Frank

Embedded software enthusiast

Updated on June 04, 2022

Comments

  • Frank
    Frank almost 2 years

    For my GUI i would like to have two pairs of buttons that scroll up and down a scrollarea. The first set of buttons should work on say scrollarea1 and the second set of buttons should work on a scrollarea2. The widgets that I put in the scrollarea are called viewport1 and viewport2. Since both both set of buttons should do the same (scrolling up and down) I thought I would make two slots called scrollUp and scrollDown that would handle the scrolling for both sets of buttons. Unfortunately I cannot make this work and need some help. I have tried the following:

    QPushButton up;
    QPushButton down;
    QPushButton up2;
    QPushButton down2;
    
    connect(&up,SIGNAL(clicked()),&up,SLOT(scrollUp()));
    connect(&up2,SIGNAL(clicked()),&up,SLOT(scrollUp()));
    connect(&down,SIGNAL(clicked()),&down,SLOT(scrollDown()));
    connect(&down2,SIGNAL(clicked()),&down,SLOT(scrollDown()));
    
    void MainWindow::scrollDown()
    {
    QScrollArea area;
    QWidget view;
    
    if((QPushButton) &sender = down)
    {
        area=scrollArea;
        view=viewport;
    }
    if((QPushButton) &sender = down2)
    {
        area=scrollArea;
        view=viewport;
    }
    int curpos = area.verticalScrollBar()->value();
    area.verticalScrollBar()->setValue(curpos+15);
    int newpos = area.verticalScrollBar()->value();
    QPoint topLeft = area.viewport()->rect().topLeft();
    view.move(topLeft.x(),topLeft.y()-(newpos));
    }
    
    void MainWindow::scrollUp()
    {
    QScrollArea area;
    QWidget view;
    
    if((QPushButton) &sender = up)
    {
        area=scrollArea;
        view=viewport;
    }
    if((QPushButton) &sender = up2)
    {
        area=scrollArea2;
        view=viewport2;
    }
    int curpos = area.verticalScrollBar()->value();
    area.verticalScrollBar()->setValue(curpos-15);
    int newpos = area.verticalScrollBar()->value();
    QPoint topLeft = area.viewport()->rect().topLeft();
    view.move(topLeft.x(),topLeft.y()-(newpos));
    }
    

    But this doesn´t work for several reasons. I also tried giving the slot some arguments, something like:

    connect(&up,SIGNAL(clicked()),&up,SLOT(scrollUp(scrollarea1,viewport1)));
    connect(&up2,SIGNAL(clicked()),&up,SLOT(scrollUp(scrollarea2,viewport2)));
    

    But again, no succes. Can anybody help me?