[SOLVED] Possible bug in QApplication::setPalette() - what to do?



  • OS: Windows 7
    Qt: 5.3.0

    I have been having trouble changing the palette of one of my applications. It looked fine, but after certain other applications had been run (in particular ones that made Aero switch from "Glass" to "Basic"), the colors were messed up. After a lot of searching I wrote a "minimal" example to find out if I made a mistake or if Qt is having trouble.

    It seems Qt has a bug here and after all my work I really want to bring this to some attention in hopes of this getting fixed. Ideas of how/where to fix this are welcome, too!

    main.cpp:
    @#include "dialog.h"
    #include <QApplication>
    #include <QColor>
    #include <QPalette>
    #include <QStyleFactory>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    /*switch style to Fusion; windows, windowsxp and windowsvista did not show
     * this particular problem even though their palette seems to be changed as
     * well (maybe a redraw is necessary?)*/
    QApplication::setStyle(QStyleFactory::create("Fusion"));
    
    //change a single color for testing purposes
    QColor color("green");//arbitrary
    QPalette p = qApp->palette();//use standard as base
    p.setColor(QPalette::Window, color);
    qApp->setPalette(p);
    
    //show the window
    Dialog w;
    w.show();
    return a.exec&#40;&#41;;
    

    }@

    dialog.h:
    @#ifndef DIALOG_H
    #define DIALOG_H

    #include <QDialog>

    class Dialog : public QDialog
    {
    Q_OBJECT
    public:
    Dialog(QWidget *parent = 0);
    };

    #endif // DIALOG_H@

    dialog.cpp (minimal):
    @#include "dialog.h"
    #include <QApplication>
    #include <QHBoxLayout>
    #include <QMenuBar>

    Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
    {
    this->setMinimumSize(200, 200);

    QHBoxLayout *hbox = new QHBoxLayout(this);
    QMenuBar *menu = new QMenuBar(this);
    
    hbox->addWidget(menu);
    

    }@

    Running this application shows a green menubar as well as a green background. Running an Aero-manipulating application afterwards resets the color of the palette, the menubar now returns to its default colors. The rest of this application does not, however - somehow the palette has been changed in the background without all the widgets updating immediately. The only one I found so far that immediately changes color is QMenuBar.

    Here a slightly longer version of the last piece of code, including some rudimentary output.

    dialog.cpp (with output):
    @#include "dialog.h"
    #include <QApplication>
    #include <QHBoxLayout>
    #include <QMenuBar>
    #include <QPushButton>

    Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
    {
    this->setMinimumSize(200, 200);

    QHBoxLayout *hbox = new QHBoxLayout(this);
    QMenuBar *menu = new QMenuBar(this);
    
    hbox->addWidget(menu);
    
    //all of the rest is to visualize the changes
    QPushButton *button = new QPushButton("Print Palette");
    hbox->addWidget(button);
    
    //print the whole active palette to the console
    connect(button, &QPushButton::clicked, this, [button]()
    {
        QPalette p = qApp->palette();
        QStringList roles;
        roles << "WindowText" << "Button" << "Light" << "Midlight" << "Dark"
              << "Mid" << "Text" << "BrightText" << "ButtonText" << "Base"
              << "Window" << "Shadow" << "Highlight" << "HighlightedText"
              << "Link" << "LinkVisited" << "AlternateBase" << "NoRole"
              << "ToolTipBase" << "ToolTipText";
        for(int i = int(QPalette::Window) ; i < int(QPalette::Window) + 1 ; i ++)//can easily be modified to show the whole palette
        {
            qDebug("%s: %s", qPrintable(roles.at(i)),
                             qPrintable(p.color(QPalette::Active, QPalette::ColorRole(i)).name()));
        }
    });
    

    }@

    Result for this test:
    Just by launching (and exiting) another application, the Qt application changes the "probe-color" (set in main.cpp):
    Before: QPalette::Window: #008000
    After: QPalette::Window: #f0f0f0

    I assume this is a bug, so what can I do about it?


  • Moderators

    Thanks for the detailed research. I think the first thing to do is to try if it is still present in Qt 5.3.1.

    Then, you can search if it is a known bug, and optionally report a new one by following this "guide":https://qt-project.org/wiki/ReportingBugsInQt



  • I can't try it out under Qt5.3.1. I am running Windows in a virtual machine with a non-supported graphics card, and I read something about the bundled QtCreator (falsesly, it is mentioned as a bug) requiring OpenGL to even be launched. Since I use that environment to develop a piece of software, I don't want to break everything just to check for a bug that most likely is not yet fixed anyway (it has been around since Qt5, maybe Qt5.1, but I never bothered to track it down).

    I am currently trying to set up everything for bug-reporting/committing changes, but the instructions are quite fuzzy.


  • Moderators

    OK, to sum it up:

    • go to "bugreports.qt-project.org":bugreports.qt-project.org
    • register if you do not have an account already
    • create new issue using a button (top-right)
    • fill in all the details
    • suggest changes to the bug reporting guide, if you can: we want the process to be as smooth and easy to get into, as possible


  • Until now I have no idea where the bug comes from or how to fix it. The operating system requests a palette change, Qt forgets about its current palette and jumps back to the default one. May be within qapplication_p, but my guess is worth a lot less than anyody elses.

    Thanks, by the way. All of this does seem a bit complicated, but I hope it is not going to eat more than another hour.



  • As a note of closure:
    After some debugging I filed a bug-report and this is indeed a deficiency with QApplication. A fix is supposedly difficult to do, although I didn't get too much feedback on the bug-report. But at least there is a way to work around the problem: Whenever the systems style is changed, the application receives an event (one that is currently undocumented). Intercepting this QEvent::ThemeChange in the main widgets QWidget::event() method allows to at least undo the OSes style change. Somewhat ugly due to flickering but a lot better than before.

    As far as I know this event has been implemented somewhat recently, so this workaround will probably not work for Qt4 (even though the bug exists there, too).


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.