Search code examples
c++qtqt5qt-designerqtstylesheets

How to change the styleSheet properties at runtime?


I'm using Qt, 5.9, Windows. I'm trying to change the styleSheet properties after my program started, so the user can customize the appearance of the program.

I have not created a styleSheet file. Instead, in Qt's Design mode, I go to the properties of the element I'm trying to change, click the "styleSheet" property, and add properties I want to change in the window displayed by Qt. Check the image 1* for the example. The red box shows where I add the styleSheet property and the green box shows where I click to get to the popup window that lets me add a styleSheet property.

Image 2* shows how the .ui code is written when I add styleSheet properties this way. The red box here shows how the code is written automatically in the .ui file.

In the Edit menu of the menuBar, I placed a submenu called "Appearance", with a few pre-set options of colors of the program and an option to customize the program yourself. In image 3*, you can see the menu.

Images 1, 2 and 3, respectively.

When the user clicks one of the color options, it should change the styleSheet properties of the program, so the colors match the color chosen. The problem happens here. Image 4 shows the code for clicking in these color options:

Color options commands

In the red square, the errors I have been getting, and the respective lines that produced them. In the yellow square, two of many trials I have made. In the blue square, the most seemingly effective tries. The one in line 21 wasn't compiled when I took the screenshot, but it only complained after compilation (but it did complained!). It says "notr" is not defined in this scope. So I tried declaring it. The one in line 22 is gave me an error when I tried "string notr", saying that the string was not defined in this scope. I included the <stdlib.h>, and changed it to "std::string notr", but it is still complaining. Like you can see in the red box, it says "expected primary-expression before 'notr'".

What does it mean? How do I fix this, so I can change the styleSheet properties of my elements? I thought of using styleSheet files for the pre-set colors, but I would like to avoid, if possible, using more files than needed. Also, how would the user be able o set a custom styleSheet, if the options are pre-set?

Thanks for the attention and help.

P.S.: Just as a bonus question. I'm trying changing basic colors first, then start advancing. Ultimately, I want to be able to reproduce something like Substance Look and Feel, its way of handling colors, making gradients, or giving the titleBar more than one color. Does anyone know what route to take? I believe styleSheets are too weak to reproduce those effects, so I would like to know how else could I change a program to look even more like Susbtance's skins. Thanks again.

*Images 1, 2 and 3 appear in the same image file, because StackOverflow wouldn't let me post more than 2 images.


Solution

  • The function setProperty() according to the documentation:

    Sets the value of the object's name property to value.

    If the property is defined in the class using Q_PROPERTY then true is returned on success and false otherwise. If the property is not defined using Q_PROPERTY, and therefore not listed in the meta-object, it is added as a dynamic property and false is returned.

    That is, the property must be defined in the class with that macro, but stylesheet does not meet those requirements so you will not be able to access with that method.

    To dynamically change that property you must use the setStyleSheet(). For example in your case:

    void MainWindow::on_actionBlack_triggered()
    {
        centralWidget()->setStyleSheet("background-color: rgb(78, 78, 78);");
    }
    
    void MainWindow::on_actionBlack_Piano_triggered()
    {
       //another color
        centralWidget()->setStyleSheet("background-color: rgb(111, 111, 111);");
    }
    
    void MainWindow::on_actionPok_dex_Orange_triggered()
    {
       //another color
        centralWidget()->setStyleSheet("background-color: rgb(123, 22, 111);");
    }
    

    Note:

    • Try to avoid using std::string, you must use QString.

    • The instruction some_function(type_variable name_variable = some_value); is not a valid C/C++ syntax

    When in the design xml:

    <property name="styleSheet">
     <string notr="true"> background-color: rgb (78, 78, 78);
     font 10pt &quot;Arial&quot;;
     color: rgb(220, 220, 220);<string>
    </property>
    

    notr="true" means that when you want to use the Qt translation system, this string will not be taken into account: No Translations.

    That xml is never used by the compiler directly, which converts those .ui files to .h with the name ui_yourdesign.h.

    The setStyleSheet() function is part of QWidget, so any class that inherits from QWidget can use it, ie QMenubar, QLineEdit, QTextEdit.

    For example the xml you display:

    enter image description here

    Show that theBar menu is being applied to the property, that instruction could be changed through C ++ with the following statement:

    ui->menuBar->setStyleSheet("background-color: rgb (78, 78, 78); font 10pt; color: rgb(220, 220, 220);")