Results 1 to 4 of 4

Thread: Awful flickering with QGridLayout on Mac OS X

  1. #1
    Join Date
    Mar 2010
    Posts
    319
    Thanks
    1
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Awful flickering with QGridLayout on Mac OS X

    Hi,

    I am using a QGridLayout to show some widgets which I create on the fly, then delete, create others, etc. This all works fine, but on Mac OS X I get a really awful flickering (despite using setUpdatesEnabled()) while it's all fine on Windows and Linux.

    I have created a small Qt project which reproduces the problem (see below). I would really appreciate if someone could tell me whether I missed something obvious or whether it's a 'bug' on Mac OS X.

    Cheers, Alan.

    Test.pro:
    Qt Code:
    1. QT += core gui
    2.  
    3. TARGET = Test
    4. TEMPLATE = app
    5.  
    6. SOURCES += main.cpp\
    7. mainwindow.cpp
    8.  
    9. HEADERS += mainwindow.h
    To copy to clipboard, switch view to plain text mode 
    main.cpp:
    Qt Code:
    1. #include <QtGui/QApplication>
    2. #include "mainwindow.h"
    3.  
    4. int main(int argc, char *argv[])
    5. {
    6. QApplication a(argc, argv);
    7. MainWindow w;
    8. w.show();
    9.  
    10. return a.exec();
    11. }
    To copy to clipboard, switch view to plain text mode 
    mainwindow.cpp:
    Qt Code:
    1. #include "mainwindow.h"
    2.  
    3. #include <QGridLayout>
    4. #include <QPushButton>
    5.  
    6. MainWindow::MainWindow(QWidget *parent) :
    7. QMainWindow(parent)
    8. {
    9. mWidget = new QWidget(this);
    10.  
    11. mLayout = new QGridLayout(mWidget);
    12.  
    13. mWidget->setLayout(mLayout);
    14.  
    15. populate();
    16.  
    17. setCentralWidget(mWidget);
    18.  
    19. this->resize(600, 300);
    20. }
    21.  
    22. void MainWindow::populate()
    23. {
    24. setUpdatesEnabled(false);
    25.  
    26. for (int i = 0, iMax = mLayout->count(); i < iMax; ++i) {
    27. QLayoutItem *item = mLayout->takeAt(0);
    28.  
    29. delete item->widget();
    30. delete item;
    31. }
    32.  
    33. for (int i = 0; i < 3; ++i)
    34. for (int j = 0; j < 3; ++j) {
    35. QPushButton *button = new QPushButton("Click me!", mWidget);
    36.  
    37. connect(button, SIGNAL(clicked()), this, SLOT(populate()));
    38.  
    39. mLayout->addWidget(button, i, j);
    40. }
    41.  
    42. setUpdatesEnabled(true);
    43. }
    To copy to clipboard, switch view to plain text mode 
    mainwindow.h:
    Qt Code:
    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3.  
    4. #include <QMainWindow>
    5.  
    6.  
    7. class MainWindow : public QMainWindow
    8. {
    9. Q_OBJECT
    10.  
    11. public:
    12. explicit MainWindow(QWidget *parent = 0);
    13.  
    14. private:
    15. QWidget *mWidget;
    16. QGridLayout *mLayout;
    17.  
    18. private Q_SLOTS:
    19. void populate();
    20. };
    21.  
    22. #endif
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Awful flickering with QGridLayout on Mac OS X

    This is a little strange, because according to this code, your MainWindow isn't even visible yet at the time you call the populate() method - populate() is called during MainWindow's construction, prior to it being made visible via show(). You must mean that the flicker occurs when one of the buttons is clicked and the slot calls populate(), right?

    My guess is that it is some issue related to deleting the widget whose clicked() signal is being handled during the execution of the slot. Possibly in Mac OS, the underlying graphics system is trying to update the button to reflect its new clicked state, and the rug has been yanked out from under it.

    Try adding a button or menu item that is not going to be dynamically deleted and use that to invoke the populate slot, and see if the flicker problem still occurs. If it does, it might be due to some recursion or iteration in the layout size recalculation - turning off updates won't prevent events from being added to the queue, I don't think.

    You could also try deleting the layout itself in the repopulate method and adding a whole new layout along with the contents.

  3. #3
    Join Date
    Mar 2010
    Posts
    319
    Thanks
    1
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Awful flickering with QGridLayout on Mac OS X

    Quote Originally Posted by d_stranz View Post
    This is a little strange, because according to this code, your MainWindow isn't even visible yet at the time you call the populate() method - populate() is called during MainWindow's construction, prior to it being made visible via show(). You must mean that the flicker occurs when one of the buttons is clicked and the slot calls populate(), right?
    Yes, sorry, the flicker does indeed occur when you click one of the buttons which will replace all existing buttons with new ones.

    Quote Originally Posted by d_stranz View Post
    My guess is that it is some issue related to deleting the widget whose clicked() signal is being handled during the execution of the slot. Possibly in Mac OS, the underlying graphics system is trying to update the button to reflect its new clicked state, and the rug has been yanked out from under it.

    Try adding a button or menu item that is not going to be dynamically deleted and use that to invoke the populate slot, and see if the flicker problem still occurs. If it does, it might be due to some recursion or iteration in the layout size recalculation - turning off updates won't prevent events from being added to the queue, I don't think.
    Well, the code I provided is just some example code and as it happens, in my application, I replace the contents of the grid layout as a result of selecting a menu item (among other things) and I still get the flickering.

    Quote Originally Posted by d_stranz View Post
    You could also try deleting the layout itself in the repopulate method and adding a whole new layout along with the contents.
    Yes, I thought of that after posting my message. I guess I will have to give it a try and see how it goes.

  4. #4
    Join Date
    Mar 2010
    Posts
    319
    Thanks
    1
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Awful flickering with QGridLayout on Mac OS X

    Ok, I had a go at replacing the layout with another one, but no matter what I tried the flickering was still there. Then, I somehow thought about using a QStackedWidget object and add/remove a widget to/from to mimick what I was trying to achieve, and... well no more flickering! So, though I wish it didn't have to be so cumbersome, it at least works. Here is the changed code...

    mainwindow.cpp:
    Qt Code:
    1. #include "mainwindow.h"
    2.  
    3. #include <QGridLayout>
    4. #include <QPushButton>
    5. #include <QStackedWidget>
    6.  
    7. MainWindow::MainWindow(QWidget *parent) :
    8. QMainWindow(parent),
    9. mGridWidget(0),
    10. mGridLayout(0)
    11. {
    12. mStackedWidget = new QStackedWidget(this);
    13.  
    14. populate();
    15.  
    16. setCentralWidget(mStackedWidget);
    17.  
    18. this->resize(600, 300);
    19. }
    20.  
    21. void MainWindow::populate()
    22. {
    23. setUpdatesEnabled(false);
    24.  
    25. // Create a layout for our new widget and populate it
    26.  
    27. QWidget *newGridWidget = new QWidget(this);
    28. QGridLayout *newGridLayout = new QGridLayout(newGridWidget);
    29.  
    30. static int counter = 0;
    31.  
    32. ++counter;
    33.  
    34. for (int i = 0; i < 3; ++i)
    35. for (int j = 0; j < 3; ++j) {
    36. QPushButton *button = new QPushButton(QString("Click me! [%1]").arg(QString::number(counter)), newGridWidget);
    37.  
    38. connect(button, SIGNAL(clicked()), this, SLOT(populate()));
    39.  
    40. newGridLayout->addWidget(button, i, j);
    41. }
    42.  
    43. // Set newGridLaout as a layout for newGridWidget
    44.  
    45. newGridWidget->setLayout(newGridLayout);
    46.  
    47. // Add newGridWidget to mStackedWidget
    48.  
    49. mStackedWidget->addWidget(newGridWidget);
    50.  
    51. // Get rid of mGridWidget and mGridLayout (and of its contents)
    52.  
    53. if (mGridWidget) {
    54. mStackedWidget->removeWidget(mGridWidget);
    55.  
    56. for (int i = 0, iMax = mGridLayout->count(); i < iMax; ++i) {
    57. QLayoutItem *item = mGridLayout->takeAt(0);
    58.  
    59. delete item->widget();
    60. delete item;
    61. }
    62.  
    63. delete mGridLayout;
    64. delete mGridWidget;
    65. }
    66.  
    67. // Keep track of newGridWidget and newGridLayout
    68.  
    69. mGridWidget = newGridWidget;
    70. mGridLayout = newGridLayout;
    71.  
    72. setUpdatesEnabled(true);
    73. }
    To copy to clipboard, switch view to plain text mode 

    mainwindow.h:
    Qt Code:
    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3.  
    4. #include <QMainWindow>
    5.  
    6.  
    7. class MainWindow : public QMainWindow
    8. {
    9. Q_OBJECT
    10.  
    11. public:
    12. explicit MainWindow(QWidget *parent = 0);
    13.  
    14. private:
    15. QStackedWidget *mStackedWidget;
    16.  
    17. QWidget *mGridWidget;
    18. QGridLayout *mGridLayout;
    19.  
    20. private Q_SLOTS:
    21. void populate();
    22. };
    23.  
    24. #endif
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. Flickering problem
    By yagabey in forum Qt Programming
    Replies: 2
    Last Post: 5th May 2010, 12:25
  2. GraphicsItem is flickering
    By anafor2004 in forum Qt Programming
    Replies: 3
    Last Post: 30th September 2009, 11:44
  3. Flickering
    By Pembar in forum Qt Programming
    Replies: 2
    Last Post: 19th May 2009, 19:21
  4. QtOgreFramework flickering with qt 4.5
    By Angelo Moriconi in forum Qt Programming
    Replies: 2
    Last Post: 6th April 2009, 10:52
  5. Delete a QGridLayout and New QGridLayout at runtime
    By sabeesh in forum Qt Programming
    Replies: 1
    Last Post: 5th November 2007, 13:01

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.