QWidget visible region doesn't work as expected in case of QSS



  • Dear experts,

    I need your help in understanding the problem.

    I have two requirements for my application.

    • Color the widget background
    • Find the visibilty state of each widgets.

    I have a widget class that has been set to QWidget as parent.

    @
    ChildWidget::ChildWidget(int width, int height, const char* pName, QString colorName, QWidget *parent) :
    QWidget(parent),
    m_pChildWidgetUi(new Ui::ChildWidget),
    m_name(pName)
    {
    m_pChildWidgetUi->setupUi(this);
    setFixedSize(QSize(width, height));
    }
    @

    AFAIK, there are two ways to color the widget

    • QPalette, setAutoFillBackground
    • QSS - Qt Style Sheets.

    I know that QSS is pretty handy compared to other method. But still I want to test both the methods.

    In the constructor, I receive the color and set it using QPalette and auto fill background.

    @
    ChildWidget::ChildWidget(int width, int height, const char* pName, QString colorName, QWidget *parent) :
    QWidget(parent),
    m_pChildWidgetUi(new Ui::ChildWidget),
    m_name(pName)
    {
    m_pChildWidgetUi->setupUi(this);
    setFixedSize(QSize(width, height));

    QPalette pal;
    pal.setColor(QPalette::Background, color);
    pWidget->setAutoFillBackground(true);
    pWidget->setPalette(pal);
    

    }
    @

    I have created few widgets in different sizes, inorder to overlap and check if I can find the visibility states.

    @
    controller.insertWidget(480, 15, "First", "white");
    controller.insertWidget(480, 10, "Fifth", "grey");
    controller.insertWidget(200, 100, "Third", "blue");
    controller.insertWidget(480, 250, "Fourth", "pink");
    controller.insertWidget(480, 100, "Second", "yellow");
    @

    After this, when I tried to print the visible region status, here is the debug log:

    @
    Set visible: true
    Visible region QRegion(size=0), bounds = QRect(0,0 0x0)

    First is OBSCURED
    Set visible: true
    Visible region QRegion(size=0), bounds = QRect(0,0 0x0)

    Fifth is OBSCURED
    Set visible: true
    Visible region QRegion(size=0), bounds = QRect(0,0 0x0)

    Third is OBSCURED
    Set visible: true
    Visible region QRegion(size=1), bounds = QRect(0,100 480x150)

    • 0 QRect(0,100 480x150)

    Fourth is PARTIALLY VISIBLE
    Set visible: true
    Visible region QRegion(size=1), bounds = QRect(0,0 480x100)

    • 0 QRect(0,0 480x100)

    Second is VISIBLE
    @

    This works as I expected. I know that FIRST will not be visible because the SECOND widget is bit bigger in size and that overlaps the FIRST and so on.

    And IsVisible() method always returns true irrepective of its visibility and visibleRegion returns the size "0", that helps me to identifiy whether the widget is visible or not.

    With the above said success, I wanted to try colorizing the widgets using the QSS.

    Without much changes in the code, In the widget constructor, just used the color in the stylesheet:

    @
    ChildWidget::ChildWidget(int width, int height, const char* pName, QString colorName, QWidget *parent) :
    QWidget(parent),
    m_pChildWidgetUi(new Ui::ChildWidget),
    m_name(pName)
    {
    m_pChildWidgetUi->setupUi(this);
    setFixedSize(QSize(width, height));
    setStyleSheet("QWidget {background-color: " + colorName + "}");
    }
    @

    With this change, when I run the code and get the debug log:

    @
    Set visible: true
    Visible region QRegion(size=1), bounds = QRect(0,0 480x15)

    • 0 QRect(0,0 480x15)

    First is VISIBLE
    Set visible: true
    Visible region QRegion(size=1), bounds = QRect(0,0 480x10)

    • 0 QRect(0,0 480x10)

    Fifth is VISIBLE
    Set visible: true
    Visible region QRegion(size=1), bounds = QRect(0,0 200x100)

    • 0 QRect(0,0 200x100)

    Third is VISIBLE
    Set visible: true
    Visible region QRegion(size=1), bounds = QRect(0,0 480x250)

    • 0 QRect(0,0 480x250)

    Fourth is VISIBLE
    Set visible: true
    Visible region QRegion(size=1), bounds = QRect(0,0 480x100)

    • 0 QRect(0,0 480x100)

    Second is VISIBLE
    @

    Here come my problem.
    As like above method, IsVisible() method returns true always. But, visibleRegion() method returns the actual widget size instead of returning the visible region size.

    Puzzles are,
    What is the relation between visibleRegion and Stylesheet?
    If I want to use Stylesheet and find the correct visibility region what should I do?

    I have other approach that would solve this puzzle, but that becomes work around solution for me. I would like to see the experts opinion and take the decision.

    Please help me out.

    Thank you,
    Kumara


  • Moderators

    The isVisible() method has no importance here. It's like an on/off switch. It indicates if the widget is shown or not. Show doesn't imply that it's visible. Totally obscured widget can still be shown.

    The visibleRegion() on the other hand indicates "how much" of it is visible when it's shown. The doc says it's an approximation so it's not guaranteed to be 100% accurate (whole widget is just a very loose approximation of any sub-region). It also states that it is called by repaint() to indicate which regions to draw to.

    I don't actually know the code behind so this is just my speculation, but it seems reasonable to assume that qss drawing is just less optimized and always assumes whole widget to be candidate for repaint, whereas the usual painting just updates the changed portions. That would be why visibleRegion() returns different things with and without qss applied.

    As for the background - you mentioned 2 options, there is also a third. Implement the paintEvent method and just draw a colored rectangle there. I don't know what is the interaction with visibleRegion() with that approach.



  • Hi Chris,

    Thank you for the response. That gives me clarity about visibleRegion().
    May be is it good to call that function as paintableRegion()? ;) Just kidding.

    I can give a try with the third approach that you explained and find the interaction with visibleRegion() and see how it reacts.

    Having you said about the background of visibleRegion(), now I will have think in different way to find the visibility.

    Thank you Chris!

    --Kumara


Log in to reply
 

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