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. How to disable a button in the slot function?
QtWS25 Last Chance

How to disable a button in the slot function?

Scheduled Pinned Locked Moved General and Desktop
23 Posts 5 Posters 36.1k 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.
  • U Offline
    U Offline
    udrnrso
    wrote on 29 Mar 2011, 06:30 last edited by
    #1

    Hi All,
    I am new to QT, and I wanna disable a button when I clicked another button, but it seems that it didnt work correctlly, the button2 was disable after the slot was return . I have no idea what happened , help me out, please! Any help will be appreciated.
    here is my code:

    @
    void on_button1_clicked()
    {
    button2.setEnable(false);
    //do other things that may take serveral seconds
    }
    @

    1 Reply Last reply
    0
    • G Offline
      G Offline
      giesbert
      wrote on 29 Mar 2011, 07:13 last edited by
      #2

      Hi,

      I'm a bit confused. You want to disable the button, and when it's disabled, it's a problem?

      By the way, it seams you are using widgets as members, this is not what you should do. You should use pointers to widgets, as the widgets are deleted via their parent-child relationship by Qt automatically.

      Nokia Certified Qt Specialist.
      Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

      1 Reply Last reply
      0
      • A Offline
        A Offline
        andre
        wrote on 29 Mar 2011, 07:17 last edited by
        #3

        Disabling a button will result in a redraw. That happens when the eventloop gets a chance to run, which you don't give it because your "other things that may take several seconds" are where your application spends its time. There are several ways to fix this, but I think for a beginner processEvents() is the easiest*:

        @
        #include <QApplication>

        void on_button1_clicked()
        {
        button2.setEnabled(false);
        QApplication::processEvents();
        //do other things that may take serveral seconds

        button2.setEnabled(true);
        }
        @

        As a side note: it is smart to give your buttons more descriptive names than just "button1" and "button2". Personally, I use names like "cmdStartLongAction" and "cmdCancel". For those, you understand what they do without reading the code.

        *) Even though I'm not a big fan of it myself, and try to avoid it if possible.

        1 Reply Last reply
        0
        • G Offline
          G Offline
          giesbert
          wrote on 29 Mar 2011, 07:34 last edited by
          #4

          But take care:

           *QApplication::processEvents();*
          

          opens the event loop and your synchronous flow is not synchronous!
          It might be that user interactions / signals from other threads etc. come in here and do some (long time) operation. This is only meant as a hint, as it might bring problems to open the event loop.

          If you only want the drawing to be done, you can use one of the following:

          1.) this excludes all use actions.

          @
          #include <QApplication>

          void on_button1_clicked()
          {
          button2.setEnabled(false);
          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
          //do other things that may take serveral seconds

          button2.setEnabled(true);
          }
          @

          2.) another way is to draw the button directly:

          @
          #include <QApplication>

          void on_button1_clicked()
          {
          button2.setEnabled(false);
          button2.repaint(); // this does an repaint
          //do other things that may take serveral seconds

          }
          @

          Nokia Certified Qt Specialist.
          Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

          1 Reply Last reply
          0
          • A Offline
            A Offline
            andre
            wrote on 29 Mar 2011, 07:39 last edited by
            #5

            I did not say that I'm not a big fan for nothing ;-)

            There are other approaches. Perhaps you should re-think if you actually want to block your entire program for a few seconds while it is processing your things. Personally, I would not like that. A UI needs to be snappy and responsive, no matter if the program is doing work or not.

            1 Reply Last reply
            0
            • U Offline
              U Offline
              udrnrso
              wrote on 29 Mar 2011, 08:29 last edited by
              #6

              [quote author="Andre" date="1301383065"]Disabling a button will result in a redraw. That happens when the eventloop gets a chance to run, which you don't give it because your "other things that may take several seconds" are where your application spends its time. There are several ways to fix this, but I think for a beginner processEvents() is the easiest*: @ #include <QApplication> void on_button1_clicked() { button2.setEnabled(false); QApplication::processEvents(); //do other things that may take serveral seconds button2.setEnabled(true); } @ As a side note: it is smart to give your buttons more descriptive names than just "button1" and "button2". Personally, I use names like "cmdStartLongAction" and "cmdCancel". For those, you understand what they do without reading the code. *) Even though I'm not a big fan of it myself, and try to avoid it if possible. [/quote]

              thx for reply!

              I have tried what you wrote as above ,but it didnt work, and I also tried button2.repaint(); but still
              , no effect! what should I do now? Use QThread or ?

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on 29 Mar 2011, 08:43 last edited by
                #7

                Then, perhaps, we misunderstood what your exact problem is. Could you try to re-word your original question to try to make more clear what you want to achieve?

                1 Reply Last reply
                0
                • U Offline
                  U Offline
                  udrnrso
                  wrote on 29 Mar 2011, 12:47 last edited by
                  #8

                  [quote author="Andre" date="1301388222"]Then, perhaps, we misunderstood what your exact problem is. Could you try to re-word your original question to try to make more clear what you want to achieve?[/quote]

                  Sorry for my poor English and thx for your patience! I have two buttons : button1 and button2 ,when I click button1, just before doing other work, disable button2, when the work done, enable button2``that is all I wanna do ! must I use thread?

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andre
                    wrote on 29 Mar 2011, 12:51 last edited by
                    #9

                    No, you don't need to use threads. In fact, given the level of Qt you seem to have, I would recommend you ignore them for the time being :)

                    1 Reply Last reply
                    0
                    • G Offline
                      G Offline
                      giesbert
                      wrote on 29 Mar 2011, 14:03 last edited by
                      #10

                      If you just don't want to react on button 2 while the work from button 1 is ongoing, you don't need to disable the button. If everything is running in main thread, there will be no button handling until the slot is finished.

                      Can you please provide a small, running app to check where the error is located. I'm sure, the way with repaint or processEvents works.

                      Nokia Certified Qt Specialist.
                      Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        andre
                        wrote on 29 Mar 2011, 14:38 last edited by
                        #11

                        Well, I guess you would want to have visual feedback that an action will not be taken, and thus, disable the button.

                        1 Reply Last reply
                        0
                        • U Offline
                          U Offline
                          udrnrso
                          wrote on 29 Mar 2011, 14:56 last edited by
                          #12

                          [quote author="Andre" date="1301409493"]Well, I guess you would want to have visual feedback that an action will not be taken, and thus, disable the button. [/quote]

                          Yes, that is exactly what I want.I complied and ran the app on vmware, does it matter?

                          1 Reply Last reply
                          0
                          • U Offline
                            U Offline
                            udrnrso
                            wrote on 30 Mar 2011, 13:43 last edited by
                            #13

                            [quote author="Gerolf" date="1301407400"]If you just don't want to react on button 2 while the work from button 1 is ongoing, you don't need to disable the button. If everything is running in main thread, there will be no button handling until the slot is finished. Can you please provide a small, running app to check where the error is located. I'm sure, the way with repaint or processEvents works.[/quote]
                            I tried processEvents on windows, it works, while on linux, that doesnt work. It confused me.
                            Finally , I combine repaint and processEvents as following, it works on both windows and linux now.
                            I have no idea why?
                            @
                            void on_button1_clicked()
                            {
                            ui->button2->setEnabled(false);
                            repaint(ui->button2->rect());
                            QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
                            // Do something
                            ui->button2->setEnabled(true);

                            }
                            @

                            1 Reply Last reply
                            0
                            • G Offline
                              G Offline
                              giesbert
                              wrote on 30 Mar 2011, 14:45 last edited by
                              #14

                              you should use repaint in a different manner:

                              @
                              void on_button1_clicked()
                              {
                              ui->button2->setEnabled(false);
                              ui->button2->repaint();
                              // Do something
                              ui->button2->setEnabled(true);
                              }
                              @

                              perhaps then it also works on linux?
                              You call repaint typically on the widget you want to repaint, not on yourself with a rectangle of a child. This could lead to no repaint (as your own area is hidden behind the child --> no redraw of your widget is needed).

                              Nokia Certified Qt Specialist.
                              Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                              1 Reply Last reply
                              0
                              • U Offline
                                U Offline
                                udrnrso
                                wrote on 30 Mar 2011, 15:43 last edited by
                                #15

                                [quote author="Gerolf" date="1301496355"]you should use repaint in a different manner: @ void on_button1_clicked() { ui->button2->setEnabled(false); ui->button2->repaint(); // Do something ui->button2->setEnabled(true); } @ perhaps then it also works on linux? You call repaint typically on the widget you want to repaint, not on yourself with a rectangle of a child. This could lead to no repaint (as your own area is hidden behind the child --> no redraw of your widget is needed).[/quote]
                                Thx for your answer!
                                Dear Gerolf , I tried your code, also, it perform the same way , unless I put a processEvents() behind ui->button2->repaint(); Is it a bug ?

                                1 Reply Last reply
                                0
                                • G Offline
                                  G Offline
                                  giesbert
                                  wrote on 30 Mar 2011, 15:46 last edited by
                                  #16

                                  as per description (and my current usage) repaint should repaint emediatly. In the "docs":http://doc.qt.nokia.com/latest/qwidget.html#repaint there is stated:

                                  [quote]
                                  Repaints the widget directly by calling paintEvent() immediately, unless updates are disabled or the widget is hidden.

                                  We suggest only using repaint() if you need an immediate repaint, for example during animation. In almost all circumstances update() is better, as it permits Qt to optimize for speed and minimize flicker.

                                  Warning: If you call repaint() in a function which may itself be called from paintEvent(), you may get infinite recursion. The update() function never causes recursion.
                                  [/quote]

                                  Nokia Certified Qt Specialist.
                                  Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                                  1 Reply Last reply
                                  0
                                  • A Offline
                                    A Offline
                                    andre
                                    wrote on 30 Mar 2011, 15:49 last edited by
                                    #17

                                    According to the documentation, repaint() should trigger an immediate repaint. If it doesn't, then indeed I think you have a bug on your hands.

                                    1 Reply Last reply
                                    0
                                    • I Offline
                                      I Offline
                                      ivan.todorovich
                                      wrote on 30 Mar 2011, 20:45 last edited by
                                      #18

                                      Couldn't it be a VMWare problem?
                                      I mean, from my own experience with VMWare, sometimes it repaints blocks just like it were a VNC window. And if it is trying to get the window's contents to paint it on the host when the event loop is blocked it might fail.

                                      Maybe we should try the same code on a linux host. Unfortunately I don't have it right now.

                                      o_o Sorry for my rusted english.

                                      1 Reply Last reply
                                      0
                                      • R Offline
                                        R Offline
                                        Revu
                                        wrote on 12 Apr 2011, 07:03 last edited by
                                        #19

                                        Hi All,
                                        If there are some 'N' buttons that need to be disabled with the same scenario,then how that can be achieved? With the complexity that the slots are interconnected with the independent windows.Like button1 click activates an independent window that has a slot to activate another independent window.With the use of modal dialog this can be achieved only between two windows then how about the rest of the active window?

                                        Every fall is to raise higher than Before.

                                        1 Reply Last reply
                                        0
                                        • A Offline
                                          A Offline
                                          andre
                                          wrote on 12 Apr 2011, 07:33 last edited by
                                          #20

                                          If you have multiple active windows in your application, and you want a modal dialog that is modal relative to all of them, you need an ApplicationModal dialog box. You can make that by using QDialog::setModel(true) or by using QWidget::setWindowModality(Qt::ApplicationModal).

                                          For disabling and enabling a whole host of widgets in one go, I would change the setup from the last page a bit. Instead of directly disabling and enabling your buttons, I would either simply use signals and slots or use a list of widgets. Using the signal/slot method, you would declare a signal like this:

                                          in the class declaration
                                          @
                                          signals:
                                          void enableButton(bool);
                                          @

                                          Then, of course, you need to hookup your buttons to this signal, for instance in your constructor:
                                          @
                                          //make sure this runs once, for instance by putting it in the constructor
                                          connect (this, SIGNAL(enableButton(bool)), m_ui->button1, SLOT(setEnabled(bool)));
                                          connect (this, SIGNAL(enableButton(bool)), m_ui->button2, SLOT(setEnabled(bool)));
                                          connect (this, SIGNAL(enableButton(bool)), m_ui->button3, SLOT(setEnabled(bool)));
                                          //...
                                          connect (this, SIGNAL(enableButton(bool)), m_ui->buttonN, SLOT(setEnabled(bool)));
                                          @

                                          In your method, you then do something like this:
                                          @
                                          #include <QApplication>

                                          void on_button1_clicked()
                                          {
                                          emit enableButton(false);
                                          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
                                          //do other things that may take serveral seconds

                                          emit enableButton(true);
                                          }
                                          @

                                          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