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. QComboBox Signal FocusInEvent or Highlighted/Activated?

QComboBox Signal FocusInEvent or Highlighted/Activated?

Scheduled Pinned Locked Moved General and Desktop
15 Posts 4 Posters 10.6k 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.
  • P Offline
    P Offline
    poporacer
    wrote on last edited by
    #1

    I have a Dialog form that has a table on it that is populated by some comboboxes(3 total). After the table is populated, I don't want the user to accidently change the table by changing the data in the comboboxes. If the user clicks (or selects an item in the combobox) I want a messsagebox that asks if the user really wants to change the table and if not, set the comboindex to what it was prior to the user clicking on the comboboox. I think there are a few ways to achieve this but I am not sure which would be the best way.

    1. If the table is not empty, set combox property setEnabled (false) //This doesn't seem to be a property but would be the easiest and probably the best way... if unabled, no changes can be made.

    2. If the table is not empty, check combobox if item is activated //I need to be able to revert to the original selected item if the user clicked the combobox accidentily. I haven't tried this as I am not sure if it will work without setting member variables to store the current selected item in each combobox. Once an item is activated, isn't it the current item? Or would currentIndex still return the original index before committing the selection?

    3. Capture the FocusInEvent on the combobox and check the table to see if it is not empty. //I tried this as it seemed the best method but I ran accross several problems.

    Here is the code I used and the problems I ran accross:
    in Constructor
    @ui->cmbName->installEventFilter(this);@

    Function
    @bool MainPage::eventFilter (QObject *object, QEvent *event)
    {
    if (event->type()==QEvent::FocusIn)
    {
    int row =lapModel->rowCount();

        if (object== ui->cmbName)
        {
              if(!row ==0)
              {
                int test=QMessageBox::warning(this,"Run Table loaded", "If you select a new Name, \n "
                                          "a new table will be loaded. \n"
                                           "Do you want to load a new table?",
                                           QMessageBox::Yes | QMessageBox::No );
                    if (test==QMessageBox::No)
                    {
                        ui->txtLineDescription->setFocus();
                        return false;
                    }
                    else
                    {
                        return true;
                    }
              }
    
        }
    

    }
    return true;
    }@

    When I use the
    @ui->cmbName->installEventFilter(this);@
    the combobox is not visible. Even if I implement show() after. When I populate the comboboxes, i blocked signals, but in stepping through the program it looks like this function gets called when each item is added to the combobox. I don't think the combobox will contain so many elements as to create a problem but it doesn't seem effecient.

    I am sure that subclassing of some sort would work, but as I am a newbie I am not sure how to go about it.

    What are the thoughts on what would be the best way to achieve this? And a little bit of code (or a lot if you are motivated...lol) to get me heading in the right direction

    1 Reply Last reply
    0
    • F Offline
      F Offline
      Franzk
      wrote on last edited by
      #2

      You have to let your base class eventFilter() implementation take over at some point. Probably the last line should read:
      @return QMainWindow::eventFilter(object, event);@
      Assuming of course that you are here deriving from QMainWindow.

      "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

      http://www.catb.org/~esr/faqs/smart-questions.html

      1 Reply Last reply
      0
      • P Offline
        P Offline
        poporacer
        wrote on last edited by
        #3

        I am not sure where I should put the return statement you mentioned. If it is in the function, isn't the return state bool? Also, I did recode the function for the "selected" event and as I suspected, the combobox has changed when this event has fired, so I tried the "highlighted" event and it works pretty close to what I need. The only issue is sometimes the popup remains open. I even tried a hidePopup at the end of the function and it still remains open. Any ideas?

        1 Reply Last reply
        0
        • G Offline
          G Offline
          goetz
          wrote on last edited by
          #4

          Put the statement where it is supposed to. It depends on the actual implementation of your method. At least replace the last "return true" with the call of the base class' implementation.

          http://www.catb.org/~esr/faqs/smart-questions.html

          1 Reply Last reply
          0
          • P Offline
            P Offline
            poporacer
            wrote on last edited by
            #5

            Well, I am a newbie at Qt so it is taking a bit to sink in. I changed the last return true with @return QMainWindow::eventFilter(object, event);@ And I got a compile error of
            error: cannot call member function 'virtual bool QObject::eventFilter(QObject*, QEvent*)' without object So I thought that maybe it should reflect the class It is in and changed it to: @return MainPage::eventFilter(object, event); @ This compiled but crashed. I degugged the program and it was a continuous loop.
            Where do I go from here?

            I am still not sure if this is the best method to accomplish what I want to do. Any comments on what would be the best method and how to fix the hidePopup issue I mentioned?

            1 Reply Last reply
            0
            • F Offline
              F Offline
              Franzk
              wrote on last edited by
              #6

              If you call MainPage::eventFilter() you get a recursive function, which causes a stack overflow, which crashes your program. What does MainPage inherit from? QWidget? In that case you should call QWidget::eventFilter().

              "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

              http://www.catb.org/~esr/faqs/smart-questions.html

              1 Reply Last reply
              0
              • P Offline
                P Offline
                poporacer
                wrote on last edited by
                #7

                I am still getting a recursive function, except this time in a different part. I changed the return to:
                @return QDialog::eventFilter(object, event);@ Once a user clicks on the comboBox and the event filter fires, it keeps looping as if the focusInEvent is being called. I am lost.

                1 Reply Last reply
                0
                • F Offline
                  F Offline
                  Franzk
                  wrote on last edited by
                  #8

                  Give us the full project or a fully compiling example of the problem, please.

                  "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

                  http://www.catb.org/~esr/faqs/smart-questions.html

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    giesbert
                    wrote on last edited by
                    #9

                    [quote author="poporacer" date="1299217306"]I am still getting a recursive function, except this time in a different part. I changed the return to:
                    @return QDialog::eventFilter(object, event);@ Once a user clicks on the comboBox and the event filter fires, it keeps looping as if the focusInEvent is being called. I am lost.[/quote]

                    You will end up in an endless loop if you work that way on focus in event. The reason is very simple:

                    Your combo box gets the focus, you put it to the QMessageBox. With closing the message box, it returns to the combo box, which results in calling the event filter... Hope you see the loop. And you also explicitly set the focus.

                    The base class event filter normally does nothing so returning false in the end should also work. True filters the event out, see "documentation":http://doc.qt.nokia.com/latest/qobject.html#eventFilter .

                    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
                    • G Offline
                      G Offline
                      goetz
                      wrote on last edited by
                      #10

                      [quote author="Gerolf" date="1299230208"]The base class event filter normally does nothing so returning false in the end should also work. True filters the event out, see "documentation":http://doc.qt.nokia.com/latest/qobject.html#eventFilter .[/quote]

                      You never know if the base class' event filter does something, so it is good practice to call it. If it is "empty", it returns false anyways, if not it works as expected. Only leave the call to the base class' implementation out if you're absolutely sure what you are doing and you know for sure that you do not want the base class functionality. and even if the base's event filter is empty now, this might change in the future. So, call it and forget it :-)

                      This holds not only for eventFilter, but for the vast majority of virtual functions in Qt.

                      http://www.catb.org/~esr/faqs/smart-questions.html

                      1 Reply Last reply
                      0
                      • P Offline
                        P Offline
                        poporacer
                        wrote on last edited by
                        #11

                        @Gerolf, Thanks for the link to the documentation. now I understand it better, you return true if you captured the event and do not want any further processing and false if you want to continue with normal event processing... Correct? But I don't see where I explicitly set the focus to the combobox. I do set the focus to another widget. I did this to try to prevent the recursiveness.
                        @Volker, You say that it is good practice to call the base class' event filter. I am not sure what you mean by this. Are you saying that in pest practices, it should be included in the end as I have it or instead of returning false you should always
                        @return QDialog::eventFilter(object, event);@
                        ??
                        And after seeing how often the focusInEvent is triggered, I think I will change it to mouseClick
                        Thanks!

                        [EDIT: fixed @-tags, Volker]

                        1 Reply Last reply
                        0
                        • G Offline
                          G Offline
                          goetz
                          wrote on last edited by
                          #12

                          [quote author="poporacer" date="1299385172"@Volker, You say that it is good practice to call the base class' event filter. I am not sure what you mean by this. Are you saying that in pest practices, it should be included in the end as I have it or instead of returning false you should always
                          @return QDialog::eventFilter(object, event);@
                          ??
                          And after seeing how often the focusInEvent is triggered, I think I will change it to mouseClick
                          Thanks!
                          [/quote]

                          For all the cases where you do not handle the event yourself, call the base class' implementation and return its value. For the cases where you handle the event yourself, you must decide if the base class should get the event too; most times the answer is "yes", but there is no general guideline here.

                          Be aware that this holds for almost every virtual method that you reimplement, not only eventFilter.

                          http://www.catb.org/~esr/faqs/smart-questions.html

                          1 Reply Last reply
                          0
                          • P Offline
                            P Offline
                            poporacer
                            wrote on last edited by
                            #13

                            Well, I still had the recursive errors and the combobox wouldn't show. I could not figure it out. I finally tried something out of the blue and it worked. I am not sure why but this is what worked for those searching.
                            My widget was subclassed from a QDialog so I thought the proper method to return was @return QDialog::eventFilter(object, event); @
                            But that didn't work. Here is what I have to make it work:
                            In .h file
                            @bool eventFilter (QObject*, QEvent*);@

                            In constructor
                            @MainPage::MainPage(QWidget *parent) :
                            QDialog(parent), //note: the base class is QDialog...correct?
                            ui(new Ui::MainPage)
                            {
                            ui->cmbName->installEventFilter(this);
                            ui->cmbStreet->installEventFilter(this)@
                            }
                            Method:

                            @bool MainPage::eventFilter (QObject *object, QEvent *event)
                            {

                            int row =addressModel->rowCount();
                            
                            if (!row ==0)
                            {
                            
                            
                                if (object== ui->cmbName)
                                {
                                      if (event->type()==QEvent::MouseButtonPress)
                                      {
                                        int test=QMessageBox::warning(this,"Table loaded", "If you select a new Name, \n "
                                                                  "a new table will be loaded. \n"
                                                                   "Do you want to load a new table?",
                                                                   QMessageBox::Yes | QMessageBox::No );
                                            if (test==QMessageBox::No)
                                            {
                                                ui->txtName->setFocus();
                                                return true;
                                            }
                                            else
                                            {
                                                ui->txtName->setText("");
                                                setLapTable("FName = ''"); //this resets the table view to a blank table
                                                return QObject::event( event); // note: Return QObject! This change made it work
                                            }
                                      }
                            
                                }
                                else if(object==ui->cmbStreet)
                                {
                                      if (event->type()==QEvent::MouseButtonPress)
                                      {
                                        int test=QMessageBox::warning(this,"Table loaded", "If you select a new street, \n "
                                                                  "a new table will be loaded. \n"
                                                                   "Do you want to load a new table?",
                                                                   QMessageBox::Yes | QMessageBox::No );
                                            if (test==QMessageBox::No)
                                            {
                                                ui->txtLineDescription->setFocus();
                                                return true;
                                            }
                                            else
                                            {
                                                ui->txtName->setText("");
                                                setLapTable("FName = ''"); //this resets the table view to a blank table
                                                return QObject::event( event); // note..Return QObject! This change made it work
                                            }
                                      }
                                return QObject::event( event);
                               }
                            
                            return QObject::event( event);
                            

                            }
                            return QObject::event( event); //I thought you would return to the base class.QDialog?
                            }@
                            This works as it should!
                            Thanks for your help!

                            1 Reply Last reply
                            0
                            • G Offline
                              G Offline
                              goetz
                              wrote on last edited by
                              #14

                              Returning QObject::event() is definiteley wrong! Don't do this! You might end up in an endlessloop too!

                              Return QDialog::eventFilter(). If that is going to create an endless loop, you should evaluate why!

                              Also, I suspect the QMessageBox to mess up things. A whole bunch of events is generated during its execution and until the flow of control returns to the event filter.

                              Some other remarks:

                              First:
                              @
                              if (!row ==0)
                              // you know of
                              if(row != 0)
                              @

                              Second:
                              Check at first for the event type. You do net need the row if you are not dealing with a mouse press event:

                              @
                              bool MainPage::eventFilter (QObject *object, QEvent *event) {
                              if(event->type() != QEvent::MouseButtonPress)
                              return QDialog::eventFilter(object, event);

                              int row = addressModel->rowCount();
                              if(row == 0)
                              return QDialog::eventFilter(object, event);

                              if(object == ui->cmbName) {
                              // do your work here
                              } else if(object == ui->cmbStreet) {
                              // do your work here
                              }

                              // just in case we fall through
                              return QDialog::eventFilter(object, event);
                              }
                              @

                              http://www.catb.org/~esr/faqs/smart-questions.html

                              1 Reply Last reply
                              0
                              • P Offline
                                P Offline
                                poporacer
                                wrote on last edited by
                                #15

                                Thanks,
                                It works like it should, and your code is more condensed! I will get it figured out eventually! Thanks for all the help!

                                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