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. [Solved] PushButton Focus problem in a non-linear Wizard
Forum Updated to NodeBB v4.3 + New Features

[Solved] PushButton Focus problem in a non-linear Wizard

Scheduled Pinned Locked Moved General and Desktop
16 Posts 2 Posters 4.5k Views 1 Watching
  • 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.
  • R Offline
    R Offline
    roseicollis
    wrote on last edited by
    #1

    Hi,

    I’m trying to make a non-linear wizard aplication which will works only with a keyboard. I have all the pages created in a línear way and I have problems trying to make it non linar.

    On the first page (WPrincipal) I have 3 buttons (b1, b2 and b3). Each one sends you to a different page(WP1, WP2 and WP3).

    @
    int WPIni::nextId() const
    {
    if (b1->hasFocus()) //This doesn’t work unless I force it with b1->setFocus() before
    return BaseWizard::PM1;
    else if (b2->hasFocus())
    return BaseWizard::PM2;
    else if (b3->hasFocus())
    return BaseWizard::PM3;
    }
    @
    Where BaseWizard is the QWizard and it has declared:

    @enum {PMIni, PM1,PM2,PM3}@

    @
    setPage(PMIni, page0);
    setPage(PM1, page1);
    setPage(PM2r, page2);
    setPage(PM3, page3);

    setStartId(PMIni);
    @

    The question is: If I put something like that, it works and changes to the right WizardPage I want

    @
    int WPIni::nextId() const
    {
    return BaseWizard::PM1;
    }
    @

    But if I put he code with the ifs (the first code) then it does nothing becuse it doen’t get the ‘hasFocus()’ unless I writte before b1->setFocus() but that is not what I want because what I need is to know when the tab is on that button.
    In other words, what I need is: If I start the aplication, I tab twice to go to third button for example and then I press Enter key, I want to go to WP3.

    I don't know if maybe a connect () for signals and slots would be the answer if it is, then I don't know how to use it 'cause I tried but I didnt succeed...

    Thank you!

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Sounds like you should rather use a set of QRadioButton for that. They would fit more naturally in the work flow.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • R Offline
        R Offline
        roseicollis
        wrote on last edited by
        #3

        Hi again SGaist :)

        I need that buttons to be really big on the screen, so the occupy the 70% of it. That's why I use push buttons so the user can see a really big rectangle button.

        Also I proved to change them to QRadioButton to see if the problem dissapear with that type but not. I still have the same problem: b1->hasFocus() its always false. I use tab to go from one button to another but it seams that the tab focus don't set b1->hasFocus() a true and I don't know how to make it.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Sorry I wasn't clear enough. I proposed the QRadioButton because they feel more natural when dealing with a choice and you could use their checked state to return the right page id. However in your case you can make your QPushButtons checkable, put them in a QButtonGroup and configure that button group to be exclusive. To simplify your code, you can use the addButton ( QAbstractButton * button, int id ) function where the id you give is the page id corresponding to the button, the in nextId you can simply return the QButtonGroup::checkedId() value

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • R Offline
            R Offline
            roseicollis
            wrote on last edited by
            #5

            Hi,

            Ok, if I inderstood well, that is what you mean:

            WPIni.h
            @
            private:
            QPushButton *b1;
            QPushButton *b2;
            QPushButton b3;
            QButtonGroup
            BGroup;
            @

            WPIni.cpp
            @

            WPInicial::WPInicial(QWidget *parent) :
            BasePage(parent),
            b1(new QPushButton),
            b2(new QPushButton),
            b3(new QPushButton),
            BGroup(new QButtonGroup)
            {
            BGroup->addButton(b1,1);
            BGroup->addButton(b2,2);
            BGroup->addButton(b3,3);
            [...]
            }

            int WPIni::nextId() const
            {
            return this->BGroup->checkedId();
            }
            @

            If that is, the nextId always returns -1 and its like if it were the last page.

            Thank you!

            //------------------------------------------------//
            Edited: I also tried putting
            @
            setFocusProxy(b1);
            setFocusPolicy(Qt::TabFocus);
            @

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Did you make the buttons checkable ? Check one by default ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • R Offline
                R Offline
                roseicollis
                wrote on last edited by
                #7

                Hi, now when you start the program you can see 3 big buttons (b1, b2, b3) and then the wizard's buttons (back, next, cancel). This buttons are grey but if the tabfocus is on them, they became blue, so when the app start, b1 is blue and if you press Tab, b1 becames grey and b2 blue.

                Now, if I set the setCheckable() property to true to b1, b2 and b3, then when the app starts b1 is blue but if you Tab, you go directly to Fnish/Next button and you can't reach buttons b2 or b3.

                I put next / finish because in that case next button becames finish button cause it detects that pae as the last one cause nextId() still returns -1)

                Maybe the problem is that I'm doing a different thing than what I need really, I don't know...

                My intention is:

                • App starts with b1 in blue. [Now you can do p.e one of this 2 options]
                • If you press Enter you go to the next page (not to next button) which is WP1.
                • If you press Tab, b1 becames grey and b2 blue (it already does that now), and then if you press Enter you go to WP2.

                I have another question... It's there any run loop? I mean, the tipically loop that is called every second or elapsedtime as the oen used in games to run the update and render loops... So as I know the code into the loop is being read every sec I can do something like:

                @
                if (Keypressed== Enter) then //if in any moment enter is pressed:
                look wthich button has the focus
                depending the button go to the WizardPage wanted.
                endif
                @

                It's an other option to do what I need maybe... It's a posssibility I just thought 'cause I need this to work and it doesn't T_T hehe

                P.D: ischecked and has focus are diferents. I need that focus leads over check, to pick the button with the tab

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  You can use setTabOrder to setup which widget gets the focus after the current when pressing tab. And then the space key to check the button which the user select.

                  However a focused widget doesn't really tell the user that he just choose something. Either he should have a visual feedback like the one QRadioButton proposes or an exclusive checkable button group.

                  The event loop is already running.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • R Offline
                    R Offline
                    roseicollis
                    wrote on last edited by
                    #9

                    Yes, I have already the visual effect becasue as I said, when u tab, the buttons became blue but what I don't know is how to know which is selected because hasFocus() returns( -1), BGroup->checkedId() returns (-1) and so on... -.-''

                    I've solved something but now I have 2 main problems:

                    • If I press P I go to the next page. That is correct. But if I press Enter, nothing happens O.o Does anyone know why??? I want it to function with Enter key (And the same with TAB Key)

                    • The other problem its the same I already had. nextId() ALWAS return - 1; (Visually with tab u see the change of the focus but it seems that for the program there is no button selected)
                      @
                      void WPIni::keyPressEvent(QKeyEvent *event) // definition
                      {
                      event->accept();

                      switch(event->key())
                      {
                      case Qt::Key_Enter:
                      wizard()->next();
                      break;
                      case Qt::key_P:
                      wizard()->next();
                      break;
                      }
                      @

                    @
                    int WPIni::nextId() const
                    {
                    return this->BGroup->checkedId();
                    }
                    @

                    Can I access to that event loop? So I can call a function inside him? I can't see were it is...

                    [EDITED: I saw that http://qt-project.org/doc/qt-4.8/focus.html but I don't see how to implement the filter, and still have the problem htat the tab and enter keys seems to not be recognized in the switch(event- > key) ]

                    1 Reply Last reply
                    0
                    • R Offline
                      R Offline
                      roseicollis
                      wrote on last edited by
                      #10

                      Ok, I solved the filter and tab problem or at least it seems to.

                      But I have the same problem still... (I will explain it agian to make it as clear as possible because I don't really know what to do with that and I need a solution T_T)

                      I have this stylesheet on buttons that make them blue with white letters when tab focus its on them or when u click them
                      @
                      setStyleSheet("QPushButton{background-color:#d5d5d5; font: 20pt; font-weight: bold; } QPushButton:focus{background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #d5d5d5, stop: 1 #8888a8); color: white;}");
                      @

                      The thing is that is u click them or u use tab, their color change as it has to.
                      Example:
                      You are on b1 which is blue (b2 and b3 are grey).
                      You tab.
                      B1 becames grey, b2 blue and b3 stays grey.
                      you tab or you click b3.
                      b1 is grey, b2 is grey, b3 is blue.

                      Well... If the program know who has to be blue... WHY CAN't I KNOW which button is?!!!!

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Because the focus changed before nextId is called e.g. the Next button got it.

                        If you really want to work only with the focus, subclass QPushButton, emit a signal when focusIn is called then in your QWizardPage, catch that signal and update the next id value based on the sender of that signal.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        0
                        • R Offline
                          R Offline
                          roseicollis
                          wrote on last edited by
                          #12

                          I didn't know about that FocusIn/Out functions.

                          I think I will need a middle class (BaseButton) to reimplement that functions and emit the signal I am instered to?

                          What I have now is a really big mess on my mind -.-'' (I'm sorry but I'm new with Qt and all that at once exceeds me and the more things I try that I see here or in other post, the worst that works....) So I'll apreciate a lot if you can expecify that a little bit more or tell me what I am making wrong or what shold I put down and where:

                          My structure:

                          • class BaseWizard : public QWizard
                          • class BasePage : public QWizardPage -> All WizardPages inherite from that
                          • class BaseButton : public QPushButton -> New class. The QPushButton will inheritance from it to get when they are on focus
                          • class WPInicial : public BasePage -> WP initial that will see the user.The 3 buttons that it have have to redirect to WP1, WP2, y WP3.

                          BaseButton.cpp:
                          @
                          void BaseButton::focusInEvent(QFocusEvent *e)
                          {
                          if (e->reason() == Qt::TabFocusReason)
                          {
                          QPushButton::focusInEvent(e);
                          emit(focussed(true));
                          }
                          }
                          void BaseButton::focusOutEvent(QFocusEvent *e)
                          {
                          if (e->reason() == Qt::TabFocusReason)
                          {
                          QPushButton::focusOutEvent(e);
                          emit(focussed(false));
                          }
                          }
                          void BaseButton::setFocusb1(bool value)
                          {
                          if (value)
                          setFocus();
                          }
                          @

                          BaseButton.h

                          @
                          class BaseButton : public QPushButton
                          {
                          Q_OBJECT
                          public:
                          BaseButton(QWidget *parent = 0);
                          ~BaseButton();

                          signals:
                          void focussed(bool hasFocus);
                          private slots:
                          void setFocusb1(bool value);

                          public:
                          virtual void focusInEvent(QFocusEvent *e);
                          virtual void focusOutEvent(QFocusEvent *e);
                          };
                          @

                          WPInicial.h (The buttons declaration now with basebutton)
                          @
                          BaseButton *_b1;
                          BaseButton *_b2;
                          BaseButton *_b3;
                          @
                          WPInicial.cpp
                          @
                          In the constructor:
                          _b1->installEventFilter(this);
                          _b2->installEventFilter(this);
                          _b3->installEventFilter(this);

                          connect (_b1, SIGNAL(focussed(bool)),_b1, SLOT(setFocusb1(bool)));
                          connect (_b2, SIGNAL(focussed(bool)),_b2, SLOT(setFocusb1(bool)));
                          connect (_b3, SIGNAL(focussed(bool)),_b3, SLOT(setFocusb1(bool)));
                          

                          @

                          If you think that I dont need BaseButton to get the focus then tell me so I can delete it.

                          Any help to fix that mess and be able to get the focus of a button will be very apreciated :) Meanwhile I'll continue with that mess...

                          Thank you so much

                          1 Reply Last reply
                          0
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            Let's simplify things a bit:

                            @
                            BaseButton.cpp:
                            void BaseButton::focusInEvent(QFocusEvent *e)
                            {
                            if (e->reason() == Qt::TabFocusReason)
                            {
                            emit focussed();
                            }
                            QPushButton::focusInEvent(e);
                            }

                            BaseButton.h
                            class BaseButton : public QPushButton
                            {
                            Q_OBJECT
                            public:
                            BaseButton(QWidget *parent = 0);
                            ~BaseButton();

                            signals:
                            void focussed();

                            protected:
                            virtual void focusInEvent(QFocusEvent *e);
                            };
                            WPInicial.h (The buttons declaration now with basebutton)
                            BaseButton *_b1;
                            BaseButton *_b2;
                            BaseButton *_b3;
                            QSignalMapper _mapper;
                            int _nextId;
                            WPInicial.cpp
                            In the constructor:
                            _mapper.setMapping(_b1, 0);
                            _mapper.setMapping(_b2, 1);
                            _mapper.setMapping(_b3, 2);
                            connect (_b1, SIGNAL(focussed()),&mapper, SLOT(map()));
                            connect (_b2, SIGNAL(focussed()),&mapper, SLOT(map()));
                            connect (_b3, SIGNAL(focussed()),&mapper, SLOT(map()));
                            connect(&_mapper, SIGNAL(mapped(int)), SLOT(buttonFocussed(int)));

                            void WPInicial::buttonFoccussed(int nextId)
                            {
                            _nextId = nextId;
                            }
                            @

                            [edit: Corrected typos]

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            0
                            • R Offline
                              R Offline
                              roseicollis
                              wrote on last edited by
                              #14

                              Hi SGaist, thank you for all your help and for taking the time to write it for me :) This have became an alleviation for me really big.

                              I have made those changes to run it:
                              (note: I'm using Qt5)

                              WPinicial.h
                              @public slots:
                              void buttonFoccussed(int nextId);@

                              WPInicial.cpp
                              @ _mapper.setMapping(_b1, 0); //the compiler said addMapping didnt exists.
                              _mapper.setMapping(_b2, 1);
                              _mapper.setMapping(_b3, 2);@

                              And then I have had to do that:

                              @int WPInicial::nextId() const
                              {
                              if (_b1->hasFocus())
                              return BaseWizard::Page1;
                              else if (_b2->hasFocus())
                              return BaseWizard::Page2;
                              else if (_b3->hasFocus())
                              return BaseWizard::Page3;
                              }@

                              Page1,2,3 .... its the name of every WizarPage I gave in the enum.
                              I had to make that because your code never goes to WPInicial::buttonFoccussed(int nexId) function so _nextId never gets the right number...
                              With the override of nextId() I have a solution for my problem but now I'm wondering why does your code never go to buttonFocussed ??? I'm trying to understand how Qt's work with the signals and your code sound totally logic for me...

                              (Note: I changed buttonFoccussed to buttonFocussed so that isn't the problem)

                              1 Reply Last reply
                              0
                              • SGaistS Offline
                                SGaistS Offline
                                SGaist
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                Because my emit line had a typo and a mix between QSignalMapper and QDataWidgetMapper…

                                You can replace 1,2,3 with BaseWizard::Page1 and friends so you only need to return _nextId

                                Interested in AI ? www.idiap.ch
                                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                1 Reply Last reply
                                0
                                • R Offline
                                  R Offline
                                  roseicollis
                                  wrote on last edited by
                                  #16

                                  Ahh!! Ok, I understood it like internals idof the function even when I saw the Class reference -.-''

                                  Thank you so much!

                                  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