Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSignalMapper and QSpinBox with 2 parameters
Forum Updated to NodeBB v4.3 + New Features

QSignalMapper and QSpinBox with 2 parameters

Scheduled Pinned Locked Moved Solved General and Desktop
15 Posts 4 Posters 3.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    mulfycrowh
    wrote on last edited by
    #1

    Hi,

    I have a QSpinBox and I would like to connect it to a slot with 2 parameters when clicking on the arrows. The signal used is valueChanged() from the spinbox The first parameter for the slot would be the spinbox value (imageindex in the slot) and the second one is also an integer (number in the slot).
    I wrote this:

    QSignalMapper*  signalMapper = new QSignalMapper(this);
    connect(ui.spinBox_Image_Output, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), signalMapper, static_cast<void(QSignalMapper::*)()>(&QSignalMapper::map));
    signalMapper->setMapping(ui.spinBox_Image_Output, number);
    connect(signalMapper, static_cast<void(QSignalMapper::*)(int)>(&QSignalMapper::mapped), this, &Gen::setImageIconOutput);
    

    The declaration for the slot is:

    void setImageIconOutput(const int number, const int imageindex);
    

    There is a trouble when compiling because number of parameters in signal and slot doesn't match. How should I write it ?

    Many thanks

    raven-worxR 1 Reply Last reply
    0
    • M mulfycrowh

      Hi,

      I have a QSpinBox and I would like to connect it to a slot with 2 parameters when clicking on the arrows. The signal used is valueChanged() from the spinbox The first parameter for the slot would be the spinbox value (imageindex in the slot) and the second one is also an integer (number in the slot).
      I wrote this:

      QSignalMapper*  signalMapper = new QSignalMapper(this);
      connect(ui.spinBox_Image_Output, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), signalMapper, static_cast<void(QSignalMapper::*)()>(&QSignalMapper::map));
      signalMapper->setMapping(ui.spinBox_Image_Output, number);
      connect(signalMapper, static_cast<void(QSignalMapper::*)(int)>(&QSignalMapper::mapped), this, &Gen::setImageIconOutput);
      

      The declaration for the slot is:

      void setImageIconOutput(const int number, const int imageindex);
      

      There is a trouble when compiling because number of parameters in signal and slot doesn't match. How should I write it ?

      Many thanks

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      @mulfycrowh said in QSignalMapper and QSpinBox with 2 parameters:

      There is a trouble when compiling because number of parameters in signal and slot doesn't match. How should I write it ?

      the only way to achieve this is to connect the signal-mapper to a slot and in this slot you emit a signal with the 2 parameters.

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      1
      • hskoglundH Offline
        hskoglundH Offline
        hskoglund
        wrote on last edited by
        #3

        Hi just want to add, you could skip sending the imageindex (i.e. the value from the spinbox) thus making your setImageIconOutput() slot requiring only 1 parameter (signalmapper = happy).

        Then to retrieve the spinbox value in setImageIconOutput(), you could just get it from the spinbox control again.

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mulfycrowh
          wrote on last edited by
          #4

          I tried:

          connect(ui.spinBox_Image_Output, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](int imageindex) {setImageIconOutput(number, imageindex);});
          

          but I don't get the correct first parameter at run time. I mean number in the slot.

          VRoninV 2 Replies Last reply
          0
          • M mulfycrowh

            I tried:

            connect(ui.spinBox_Image_Output, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](int imageindex) {setImageIconOutput(number, imageindex);});
            

            but I don't get the correct first parameter at run time. I mean number in the slot.

            VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by
            #5

            @mulfycrowh replace [&] with [this,number]

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            M 1 Reply Last reply
            1
            • hskoglundH Offline
              hskoglundH Offline
              hskoglund
              wrote on last edited by
              #6

              Don't want to be a pessimist here, but since the lambda captures the number variable, later when the signal fires and the lambda is called, changes to that number variable isn't visible.

              Perhaps, try storing the numbers in say a QMap<int,int> where the imageindex is the key.

              VRoninV 1 Reply Last reply
              1
              • hskoglundH hskoglund

                Don't want to be a pessimist here, but since the lambda captures the number variable, later when the signal fires and the lambda is called, changes to that number variable isn't visible.

                Perhaps, try storing the numbers in say a QMap<int,int> where the imageindex is the key.

                VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #7

                @hskoglund You fell in my same mistake, see here: https://forum.qt.io/topic/69718/connect-cause-exception-triggered-beginner/7 (this treats pointers but this case is identical in principal)

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                1 Reply Last reply
                0
                • hskoglundH Offline
                  hskoglundH Offline
                  hskoglund
                  wrote on last edited by
                  #8

                  @VRonin Wow that was a thorough discussion!
                  The lambda's capturing stuff can be tricky, for example. I see in your last post:

                  ...
                  QObject::connect(mainTimer,&QTimer::timeout,[&](){qDebug() << *myString;});
                  QObject::connect(mainTimer,&QTimer::timeout,[=](){qDebug() << *myString;});
                  ...
                  

                  Both should work fine (with some luck) because the lambda is capturing the pointer, not the string data itself.
                  But in this example with number it's an int, so it's captured fully by [number]. But [&] should've worked, maybe number is recreated as a new instance before the signal is fired?

                  1 Reply Last reply
                  0
                  • M mulfycrowh

                    I tried:

                    connect(ui.spinBox_Image_Output, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](int imageindex) {setImageIconOutput(number, imageindex);});
                    

                    but I don't get the correct first parameter at run time. I mean number in the slot.

                    VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #9

                    @hskoglund QObject::connect(mainTimer,&QTimer::timeout,[&](){qDebug() << *myString;}); crashes because myString went out of scope so the OS should get angry if I try and read unassigned memory.
                    Here I think it's the same, number probably either changes value or goes out of scope so passing it by value to the lambda before changing it should work. @mulfycrowh will tell us.

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    0
                    • VRoninV VRonin

                      @mulfycrowh replace [&] with [this,number]

                      M Offline
                      M Offline
                      mulfycrowh
                      wrote on last edited by
                      #10

                      @VRonin Thank you VRonin. It runs perfectly !

                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        mulfycrowh
                        wrote on last edited by
                        #11

                        I made a lot of tests and there is sometimes a trouble about the parameter number passed to the slot setImageIconOutput. It sometimes equals to 0 and that induces an exception.

                        In fact I have 2 QSpinBox. The first one gives the index of items and each item has several images. The second one lets you change the index of the image and display it.

                        So I have a first connection for the first spinbox:

                        connect(ui.spinBox1, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Gen::updateOutput);
                        

                        updateOutput is as following:

                        void Gen::updateOutput(int number)
                        {
                        	
                        	--number;
                        	setImageOutputSpinboxMaximum(m_outputImage[number].size());
                        	ui.spinBox2->setValue(1);
                        	setImageIconOutput(number, 1);
                        	if (!alreadyConnected) {
                        		alreadyConnected = true;
                        		connect(ui.spinBox2, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this, number](int imageindex) {setImageIconOutput(number, imageindex); });
                        	}
                        }
                        

                        setImageIconOutput is as following:

                        void Gen::setImageIconOutput(const int number, int imageindex)
                        {
                        	QPixmap pic;
                        	QString suffix;
                        	QString msg;
                        
                        	--imageindex;
                        	suffix = m_tools->ordinalSuffix(imageindex+1);
                        	msg = msg.append(suffix);
                        	msg = msg.append(msg_imageFileInCommandFile);
                        	ui.spinBox_Image_Output->setSuffix(msg);
                        
                        	pic.loadFromData(m_outputImage[number][imageindex], "PNG");
                        	ui.Image_Icon_Output->setPixmap(pic);
                        
                        }
                        

                        The exception occurs for example when I choose the 3rd item (25 pictures) and chose the last picture (clicking on the down arrow of spinbox2).
                        With debugger on VS2015, I see that parameters passed to setImageIconOutput are 0 and 25 instead of 2 and 25: number is false. The exception comes because the first item only has 22 pictures and is obviously on line:

                        pic.loadFromData(m_outputImage[number][imageindex], "PNG");
                        

                        If you have any idea ...
                        Thanks

                        1 Reply Last reply
                        0
                        • hskoglundH Offline
                          hskoglundH Offline
                          hskoglund
                          wrote on last edited by
                          #12

                          Hi, if you never set alreadyConnected to true, for example by commenting it out:
                          // alreadyConnected = true;
                          Still get the bug?

                          1 Reply Last reply
                          0
                          • M Offline
                            M Offline
                            mulfycrowh
                            wrote on last edited by
                            #13

                            Yes I still have the bug. I started without using alreadyConnected.
                            Please replace ui.spinBox_Image_Output with ui.spinBox2 in setImageIconOutput

                            1 Reply Last reply
                            0
                            • hskoglundH Offline
                              hskoglundH Offline
                              hskoglund
                              wrote on last edited by
                              #14

                              Hmm maybe you got bitten by the duplicate/multiple connections for same signal/slot syndrome, you could try doing a disconnect just before the connect with lambda flavor:

                              ...
                                  setImageIconOutput(number, 1);
                                  disconnect(ui.spinBox2, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),0,0);
                                  connect(ui.spinBox2, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this, number](int imageindex) {setImageIconOutput(number, imageindex); });
                              }
                              ...
                              
                              M 1 Reply Last reply
                              1
                              • hskoglundH hskoglund

                                Hmm maybe you got bitten by the duplicate/multiple connections for same signal/slot syndrome, you could try doing a disconnect just before the connect with lambda flavor:

                                ...
                                    setImageIconOutput(number, 1);
                                    disconnect(ui.spinBox2, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),0,0);
                                    connect(ui.spinBox2, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this, number](int imageindex) {setImageIconOutput(number, imageindex); });
                                }
                                ...
                                
                                M Offline
                                M Offline
                                mulfycrowh
                                wrote on last edited by
                                #15

                                @hskoglund Thank you very much. It's OK !

                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved