How to pass "ui" object to colors class from mainwindow.cpp



  • In my mainwindow.cpp, I'm reading a colors.ini out of my resource file and colorizing my widgets. This allows me to white label my software to multiple vendors by swapping logos and colors. However, I was wondering if there's a way to make my code more tidy so that I have like a colors.h and colors.cpp, and to pass the ui object to it so that I can interact with my widgets just as easily as I can in mainwindow.cpp, including the IntelliSense popups that occur as I type in QTCreator. For instance, I would like to be inside colors.cpp and type ui->btn and up would pop a list of my widgets starting with btn in their name.

    So, to restate this a little more clearly:

    1. Is there a way to take my mainwindow.cpp ui object and pass it to a Colors class (static class would be fine with me) in colors.cpp/colors.h?

    2. Is there a way to allow this ui object to have the same IntelliSense popups as I type that I enjoy with mainwindow.cpp?

    See, my mainwindow.cpp is already full of other stuff, and I'm trying to thin it down into more organized pieces, each clearly thought out and documented. That's why I want a place to put all this colorization stuff.

    The things I've tried cause symbols missing errors.



  • Okay, I got it to work, although perhaps you can suggest a better tactic:

    1. I created the following colors.h, and skipped the colors.cpp step:
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    class Colors {
    public: // class methods
        Colors(QMainWindow *mw,Ui::MainWindow *ui)
        {
            qDebug() << mw;
            qDebug() << ui;
        }
    };
    
    1. Inside mainwindow.cpp, I added this header:
    #include "colors.h"
    
    1. Then, in mainwindow.cpp, after the setupUI call in the constructor class method, I did:
    Colors *colors = new Colors(this,ui);
    
    1. I didn't have to do anything else except start redoing colors inside the Colors class, using the mw variable if I wanted to work on colors for the MainWindow, or the ui variable if I wanted to work on colors through the ui object.

  • Qt Champions 2016

    Hi are there a reason you do not use style sheets ?
    Besides changing colors, it can change many other things. Like a logo (image)
    like
    http://thesmithfam.org/blog/2009/09/10/qt-stylesheets-tutorial/
    You can then change colors and logo without even recompile.

    You can make Color Class Friend of QMainwinow, and it will be able to use its private members.
    http://www.cprogramming.com/tutorial/friends.html

    But Im not sure why a stylesheet would not be much better. ?



  • @mrjj Good question. I had to keep putting stylesheets on every little thing, whereas with my colors class I can grab things by class and apply things in bulk. I still use stylesheets, but use my colors class to recolor what was already styled. For instance, I may have a series of buttons that are of a certain class, and unfortunately Qt doesn't allow me to put widgets in a certain class and apply a stylesheet to that class. So, my colors class loads a colors.ini in my resource file that is short and sweet. I change that little file, and the whole application changes, while not touching the other styling.

    The way I achieved "class" was to take a little-used property "accessibleDescription" and put something in there like "success", "info", "warning", "danger" (if you are familiar with how Twitter Bootstrap does their color classes). Then, my colors class grabs all the buttons, looks at that property, applies the appropriate color combination from that, and then removes the accessibleDescription value. So, as I draw a widget on a page, I can say, "Oh, well, I'm adding something -- this is an add function button, so I'll want to apply the 'success' style to it," or, I can say, "On this button, I'm removing something, so I'll want to apply the 'danger' style to it."

    It would be nice if a future version of Qt would have a class property on each widget. That way, we could make a global stylesheet where I could take buttons of say, class 'danger', and make them all red. Lacking that, I came up with another system.


  • Lifetime Qt Champion

    Hi,

    You might be interested by this article


  • Qt Champions 2016

    @maximo
    Hi
    Well you can do the same with style sheet. If you apply stylesheet to mainwindow, its
    applies to all widgets within. You can define By class, like sample where
    its all QFrame and subtypes. If you made your own frame, like HappyFrame, you could use that
    as Type also to have it apply to all of that type.
    Here we also say, must to named "TestDisplayFrame" and
    have the dynamic property error set to true.
    So you can group/mass apply with stylesheets.

    QFrame#TestDisplayFrame[error="true"]
    {
    background-color: red;
    border: 2px solid rgba(205, 92, 92, 255);
    border-radius: 20px;
    }

    So you can easy get all of class danger, by use its Type. And if its mixed widget you can use
    the [error="true"] where you just use your own property , that you can easy define in Designer and then
    use in stylesheet. So it can do it already :)



  • @mrjj said:

    So you can easy get all of class danger, by use its Type. And if its mixed widget you can use
    the [error="true"] where you just use your own property , that you can easy define in Designer and then
    use in stylesheet. So it can do it already :)

    Interesting. I'm still a bit new to Qt. What's a "mixed widget"? How do I set "my own property" easily in the Designer? So there's an ability to add a custom property to a widget in the Designer that I can then edit the value on? If so, I could create one called widgetClass where I can use a MainWindow Stylesheet to adjust it.


  • Qt Champions 2016

    @maximo
    By mixed, I mean Like the following situation:
    You have 15 Labels. Only some of them you want to change color of.
    If you do
    QLabel {
    background-color: rgb(170, 85, 127);
    }

    All of them will change.

    Then you can use their Objectname (set in designer)
    QLabel#label_2{
    background-color: rgb(170, 85, 127);
    }
    QLabel#label_3{
    background-color: rgb(170, 85, 127);
    }
    ..
    For those you want to change. (Case important for name!)

    If you then need to do it more dynamic, then in Designer

    Over the Properties List , right of "filter" is Big Green +.

    That let you add new property, you can then check for.

    Do read the link SGaist provided on how to update if you change this
    Dynamic property from code to make it really update.

    So overall you can group on ClassType, Like "All QLabels",
    with subgroups using a dynamic property, so you can say
    All QLabels that has DoMe=true.
    Or simply by names, Like All QLabels, Named a and b and c

    Not saying it is better than your color setup, but just want to note
    that StyleSheet applies from Object set on and all subchildren and
    does provides ways to point to which WIdgets you want to change.

    Note: I had issues getting it to check in Designer when using dynamic properties and had to use
    code. Might have done something wrong. But By Type and by Name works as expected in Designer.



  • @mrjj said:

    I had issues getting it to check in Designer when using dynamic properties and had to use
    code.

    Yeah, I see what you mean. I tried getting the stylesheet to recognize my dynamic property and it just wouldn't do it. I then tried to set the stylesheet from code on the main window, pulling from a CSS in a resource file, and the moment I used QPushButton[buttonClass="danger"]{ blah blah} , it generated a non-fatal runtime error (but still load) that said something like, "could not parse stylesheet for object [some hex number]". I think this is because I need to do the steps for QPROPERTY(), and that looked confusing and difficult for every button on my form, and more work than the way I was doing it in my colors class. Diminishing returns.

    So, I went back to doing it my code way where I read a colors.ini file from the resource file, and then apply that to the objects in a colors class. However, because you showed me how to do a dynamic property, I was able to use this dynamic property in code with .property("buttonClass").toString() so that I didn't have to kludge it by using .accessibleDescription(). So, thanks! :)


  • Qt Champions 2016

    @maximo
    Well, i did try the
    style()->unpolish();
    style()->polish();
    for Mainwindow but ended up checking the dynamic property
    in code and then assign a single style sheet to those I had flagged.
    Maybe you are right and it must be for widgets for it to work.

    Btw if you ever need to do something to all Widgets, its not that much code.

    QList<QWidget *> widgets = findChildren<QWidget *>();
    foreach (QWidget* b, widgets) {
    b->SOMETHING
    }
    

    and you can replace QWidget * with say QPushButton * to get all buttons.

    Anyways, good that you found use for Dynamic Properties.



  • @mrjj said:

    Btw if you ever need to do something to all Widgets

    Yep, I use that very technique in my colors class to iterate the widgets.


  • Qt Champions 2016

    @maximo
    Ok :)
    I am going to test again with stylesheets.
    It would be very nice it it worked as docs says.
    Or at least to understand why it did not.

    Update:
    Ok, one must unpolish/ polish each widget as doing it to
    Mainwindow doesn't seems to work.
    But it also works with
    setStyleSheet(styleSheet());
    in MainWindow to reload (whole) style sheet.

    Update 2:
    Ok. Having qframes with bool error property.
    It will update in Designer, if setting it.
    No code. Sheet on MWindow.
    So it does work with properties it seems.



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