Results 1 to 6 of 6

Thread: QPushButton gets stuck drawing pressed when transfer of focus to button interrupted

  1. #1
    Join Date
    Nov 2010
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default QPushButton gets stuck drawing pressed when transfer of focus to button interrupted

    Hello

    I have some forms with input fields that provide warnings to the user when the fields looses focus (if something is wrong of course). To that end I’ve created my own control that inherits from QLineEdit. For this question consider the extremely simple field that will pop a message box whenever focus is lost when there is text in the control. The actual controls have more logic but all are supposed to pop a message box.

    Qt Code:
    1. class test_line_edit : public QLineEdit
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. test_line_edit(QWidget * parent = 0) : QLineEdit(parent)
    7. {}
    8.  
    9. ~test_line_edit(){}
    10.  
    11. protected:
    12. virtual void focusOutEvent(QFocusEvent * e)
    13. {
    14. if(!text().isEmpty())
    15. {
    16. msg.setText(tr("Test"));
    17. msg.exec();
    18. setFocus(Qt::OtherFocusReason);
    19. }
    20. else
    21. {
    22. QLineEdit::focusOutEvent(e);
    23. }
    24. }
    25.  
    26. };
    To copy to clipboard, switch view to plain text mode 

    Now say I have a simple form with just one of these controls and a QPushButton. If the user types in the control and then clicks the button the messagebox pops but the button gets stuck being drawn looking like it’s pressed. How can I make that stop? As best I can tell the QPushButton’s pressed signal is getting fired but that is all I can hear from the button. Since these test_line_edit controls are going to be used everywhere on many different forms I’m hoping there is something I can change inside the test_line_edit class that will fix the problem. Running Qt 4.7.0 on Windows using Visual Studio 2010.

    I’ve seen this bug and not sure if it’s related since it’s a different platform and I’m not actually holding the button down: http://bugreports.qt.nokia.com/browse/QTBUG-7901

    Here’s a full program that demonstrates the problem (warning: some code generated from the VS plugin)

    main.h:
    Qt Code:
    1. #include <QtGui/QMainWindow>
    2.  
    3. #include <QtCore/QVariant>
    4. #include <QtGui/QAction>
    5. #include <QtGui/QApplication>
    6. #include <QtGui/QButtonGroup>
    7. #include <QtGui/QHeaderView>
    8. #include <QtGui/QMainWindow>
    9. #include <QtGui/QMenuBar>
    10. #include <QtGui/QPushButton>
    11. #include <QtGui/QStatusBar>
    12. #include <QtGui/QToolBar>
    13. #include <QtGui/QVBoxLayout>
    14. #include <QtGui/QWidget>
    15.  
    16. #include <QLineEdit>
    17. #include <QMessageBox>
    18.  
    19. class test_line_edit : public QLineEdit
    20. {
    21. Q_OBJECT
    22.  
    23. public:
    24. test_line_edit(QWidget * parent = 0) : QLineEdit(parent)
    25. {}
    26.  
    27. ~test_line_edit(){}
    28.  
    29. protected:
    30. virtual void focusOutEvent(QFocusEvent * e)
    31. {
    32. if(!text().isEmpty())
    33. {
    34. msg.setText(tr("Test"));
    35. msg.exec();
    36. //setFocus(Qt::OtherFocusReason);
    37. }
    38. else
    39. {
    40. QLineEdit::focusOutEvent(e);
    41. }
    42.  
    43. QLineEdit::focusOutEvent(e);
    44. }
    45.  
    46. };
    47.  
    48. QT_BEGIN_NAMESPACE
    49.  
    50. class Ui_btn_drawing_testClass
    51. {
    52. public:
    53. QWidget *centralWidget;
    54. QVBoxLayout *verticalLayout;
    55. test_line_edit *line_edit;
    56. QMenuBar *menuBar;
    57. QToolBar *mainToolBar;
    58. QStatusBar *statusBar;
    59.  
    60. void setupUi(QMainWindow *btn_drawing_testClass)
    61. {
    62. if (btn_drawing_testClass->objectName().isEmpty())
    63. btn_drawing_testClass->setObjectName(QString::fromUtf8("btn_drawing_testClass"));
    64. btn_drawing_testClass->resize(167, 127);
    65. centralWidget = new QWidget(btn_drawing_testClass);
    66. centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
    67. verticalLayout = new QVBoxLayout(centralWidget);
    68. verticalLayout->setSpacing(6);
    69. verticalLayout->setContentsMargins(11, 11, 11, 11);
    70. verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
    71. line_edit = new test_line_edit(centralWidget);
    72. line_edit->setObjectName(QString::fromUtf8("line_edit"));
    73.  
    74. verticalLayout->addWidget(line_edit);
    75.  
    76. btn = new QPushButton(centralWidget);
    77. btn->setObjectName(QString::fromUtf8("btn"));
    78.  
    79. verticalLayout->addWidget(btn);
    80.  
    81. btn_drawing_testClass->setCentralWidget(centralWidget);
    82. menuBar = new QMenuBar(btn_drawing_testClass);
    83. menuBar->setObjectName(QString::fromUtf8("menuBar"));
    84. menuBar->setGeometry(QRect(0, 0, 167, 20));
    85. btn_drawing_testClass->setMenuBar(menuBar);
    86. mainToolBar = new QToolBar(btn_drawing_testClass);
    87. mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
    88. btn_drawing_testClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
    89. statusBar = new QStatusBar(btn_drawing_testClass);
    90. statusBar->setObjectName(QString::fromUtf8("statusBar"));
    91. btn_drawing_testClass->setStatusBar(statusBar);
    92.  
    93. retranslateUi(btn_drawing_testClass);
    94.  
    95. QMetaObject::connectSlotsByName(btn_drawing_testClass);
    96. } // setupUi
    97.  
    98. void retranslateUi(QMainWindow *btn_drawing_testClass)
    99. {
    100. btn_drawing_testClass->setWindowTitle(QApplication::translate("btn_drawing_testClass", "btn_drawing_test", 0, QApplication::UnicodeUTF8));
    101. btn->setText(QApplication::translate("btn_drawing_testClass", "PushButton", 0, QApplication::UnicodeUTF8));
    102. } // retranslateUi
    103.  
    104. };
    105.  
    106. namespace Ui {
    107. class btn_drawing_testClass: public Ui_btn_drawing_testClass {};
    108. } // namespace Ui
    109.  
    110. QT_END_NAMESPACE
    111.  
    112. class btn_drawing_test : public QMainWindow
    113. {
    114. Q_OBJECT
    115.  
    116. public:
    117. btn_drawing_test(QWidget *parent = 0, Qt::WFlags flags = 0): QMainWindow(parent, flags)
    118. {
    119. ui.setupUi(this);
    120. }
    121. ~btn_drawing_test(){}
    122.  
    123. private:
    124. Ui::btn_drawing_testClass ui;
    125.  
    126. protected slots:
    127. void on_btn_clicked()
    128. {
    129. int breakpoint = 5;
    130. }
    131. void on_btn_pressed()
    132. {
    133. int breakpoint = 5;
    134. }
    135. void on_btn_toggled(bool)
    136. {
    137. int breakpoint = 5;
    138. }
    139. };
    To copy to clipboard, switch view to plain text mode 

    main.cpp:
    Qt Code:
    1. #include <QtGui/QApplication>
    2. #include "main.h"
    3.  
    4.  
    5.  
    6. int main(int argc, char *argv[])
    7. {
    8. QApplication a(argc, argv);
    9. btn_drawing_test w;
    10. w.show();
    11. return a.exec();
    12. }
    To copy to clipboard, switch view to plain text mode 

    Thank you for your help and please let me know if I can provide any more information.

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QPushButton gets stuck drawing pressed when transfer of focus to button interrupt

    If the user types in the control and then clicks the button the messagebox pops but the button gets stuck being drawn looking like it’s pressed. How can I make that stop?
    The reason for this is that you are calling you message box in a modal state with exec().
    This causes the applications even loop to wait for the message box to be dismissed, and therfore, the paintEvent for the pushbuttons is not being handled until the message box is not dismissed.
    What you can do is:
    1. Rethink your design. If the user is shifting input focus from a control, when the application logic states that this should not be allowed, its better to force the focus to stay on the focused control than to send a message box.
    You could in addition to forcing the focus, have somewhere a message saying why it is being done, similar to what many applications do in the status bar.
    2. Show the message box with show() and not exec(), but then it wont be modal, can be covered by other windows, and can bring to that that it will be immediately covered by another window so that the user not even notice it was popped.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  3. #3
    Join Date
    Nov 2010
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QPushButton gets stuck drawing pressed when transfer of focus to button interrupt

    Got it answered here without having to resort to either option (unless something comes up in the future but seems to work so far): http://stackoverflow.com/questions/4...tton-is-interr

  4. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QPushButton gets stuck drawing pressed when transfer of focus to button interrupt

    if it works for you - Great!
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  5. #5
    Join Date
    Nov 2010
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QPushButton gets stuck drawing pressed when transfer of focus to button interrupt

    Well we haven’t made all the dialogs yet nor run through all the testing so something could come up. I’m still fairly new to Qt but the only potential problem I see is something getting between the creation of a user QEvent in test_line_edit::focusOutEvent and it getting processed in test_line_edit::customEvent. Do you know if that’s possible? Seems like it might be but I don’t really know under what conditions… Also are there any other obvious problems with this approach that I might be missing?

  6. #6
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QPushButton gets stuck drawing pressed when transfer of focus to button interrupt

    Well, again, you can bend anything and force anything.
    But I still think that the problem is a design problem, not an implementation problem.
    You can work around design problem by forcing stuff, but then you are on slippery road of surprises.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

Similar Threads

  1. Replies: 4
    Last Post: 16th September 2011, 02:10
  2. Replies: 6
    Last Post: 4th October 2010, 03:19
  3. QPushButton gets stuck
    By mhoover in forum Qt Programming
    Replies: 1
    Last Post: 22nd May 2010, 23:22
  4. Qt/Mac - Stuck with user focus
    By sergant in forum Qt Programming
    Replies: 1
    Last Post: 24th January 2009, 08:56
  5. Replies: 3
    Last Post: 26th September 2006, 12:16

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.