[SOLVED] How to move a widget in a gridlayout



  • Hello, I am trying to implement a simple 15 puzzle, and at the moment I am using a qGridLayout to lay my qPushButtons and I am trying to connect the function move() in order to move a button to a specified place when it is clicked. In order to do so I would like to pass the id of the button as a parameter of move() (I am using QButtonGroup as a container).

    #ifndef MOVINGPUZZLE_H
    #define MOVINGPUZZLE_H
    
    #include <QMainWindow>
    #include <QObject>
    #include <QWidget>
    #include <QApplication>
    #include <QLayout>
    #include <QButtonGroup>
    #include <QPushButton>
    #include <QString>
    #include <cmath>
    
    class MovingPuzzle : public QApplication
    {
        Q_OBJECT
        public:
            MovingPuzzle(int argc, char* argv[]);
            QMainWindow m_MainWindow;
            QGridLayout *myGrid;
            QButtonGroup *myGroup;
    
        public slots:
            void move(int id);
    };
    
    #endif // MOVINGPUZZLE_H
    

    and my implementation file

    
    #include "movingpuzzle.h"
    
    const int Num=16;
    
    MovingPuzzle::MovingPuzzle(int argc, char* argv[])
        :QApplication(argc, argv)
    {
        QWidget *mainWid = new QWidget(&m_MainWindow);
    
        m_MainWindow.setCentralWidget(mainWid);
    
        myGrid = new QGridLayout;
    
        myGroup = new QButtonGroup;
        QPushButton *newBut;
    
        for(int row=0;row<sqrt(Num);row++)
            for(int col=0;col<sqrt(Num);col++)
            {
                QString id = QString::number((col+1)+(row*sqrt(Num)));
    
                if(((col+1)+(row*sqrt(Num)))<Num)
                {
                    newBut = new QPushButton(id);
    
                    myGroup->addButton(newBut,id.toInt());
    
                    myGrid->addWidget(newBut,row,col);
    
                    connect(myGroup->button(id.toInt()),SIGNAL(clicked()),this,SLOT(move(id.toInt())));
                }
            }
    
        mainWid->setLayout(myGrid);
    }
    
    void MovingPuzzle::move(int id)
    {
        myGrid->addWidget(myGroup->button(id),3,3);
    }
    

    The problem is that the program is giving me hard times passing the id as a parameter, hence the connection does not work. As you can see for the moment I am sending all the buttons to a specified place (3,3) but in the future I will implement it so that every button will be sent to the empty spot.



  • Use QSignalMapper (http://doc.qt.io/qt-5/qsignalmapper.html) to pass the button id to your moveslot



  • So is it wrong to pass arguments through a slot?



  • Instead of connecting each buttons clicked signal to a slot. You can use the QButtonGroup's buttonClicked(int id) signal which includes the pressed button's id.



  • I get that it is more efficient to proceed like you suggest but I can't figure out what is wrong with my implementation. Any ideas?



  • The problem is here:

    ...SLOT(move(id.toInt())...

    The SIGNAL() and SLOT() macros expect the declaration of the parameters. You should have something like 'SLOT(move(const int))' in the connect line. The function would be called from the button using emit (something like 'emit clicked(123)' which would end up calling your slot as 'move(123)').

    The signal mapper sounds like the right idea.



  • Thank you, I had a bit of a read around signal mappers and they seem like the perfect tool for what I need.



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.