Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QGroupBox title vertical alignment

I have QGroupBox in my UI. The basic style is 2px width border, border radius and the title being vertically centered.

I used the following style to my stylesheet (which is in a .qrc, applied in the main using app->setStylesheet):

QGroupBox {
    border: 1px solid #22a4bc;
    border-radius: 0px;
}

QGroupBox::title {
    subcontrol-origin: margin;
    subcontrol-position: top; /* position at the top center */
}

The problem is, the title is now a few pixel down, and actually over the element IN the groupbox.

I want to set it centered. I tried vertical-align, subcontrol-align, subcontrol-alignment, even top: -5px which actually centers the title, but trim the text that is higher than the border. I didn't find any answer here on SO or on the Qt forum that resolve my problem.

Does anybody know how to set the title's vertical alignment to back center? (I use C++, Qt 5.2.1 / msvc2012, Qt Creator 3.6.1 / Windows 7)

like image 576
Krapow Avatar asked Sep 11 '25 07:09

Krapow


2 Answers

I understood my mistake: According to the box model (margin > border > padding > content), the origin of my text was in the margin. But there were no margin in my QGroupBox, so it was weird.

I came up with this style which does what I want:

QGroupBox {
    border: 1px solid #22a4bc;
    border-radius: 0px;
    padding-top: 10px;
    margin-top: 5px;
}

QGroupBox:title {
    subcontrol-origin: margin;
    subcontrol-position: top center;
    margin-left: 3px;
    margin-right: 3px;
}
like image 138
Krapow Avatar answered Sep 13 '25 03:09

Krapow


Now, I am still relatively new to Qt, but in the interest of trying to help others who also have only recently started learning Qt, I wanted to explain what's going on here in a little more detail.


Issue: Default margin size

First, any time you set a style sheet in Qt, it overrides whatever style sheet was defined before that.

Part of what @Krapow ran into is how their title was being cut off when they tried to manually move it back into place using the top property. This seems to be due to the same underlying issue that's causing the title to be drawn below the border line. The documentation points to this being an issue resulting from default values of unset properties. From Qt's box model documentation:

The margin, border-width, and padding properties all default to zero. In that case, all four rectangles (margin, border, padding, and content) coincide exactly.

Since the border-width is set within the border property, the border box would no longer overlap the other boxes. Even though the title's origin is tied to a zero-width box, assuming the content box's size is non-zero, the content box would have enough room for the title to be drawn and doesn't get cut off when drawn below the border. Because the margin is a zero-width box, however, the edge of the widget is right at the top edge of the border. This means that manually moving the title into place causes the top part of the title to move out of the bounds of the widget where it can't be drawn.

For reference, this is how the different boxes in the box model are defined:

Depiction of the box model - from Qt's box model webpage (From Qt's page on the box model)

The margin falls outside the border. The border is drawn between the margin and the padding. The padding falls inside the border, between the border and the actual contents. The content is what is left from the original widget or subcontrol once we have removed the margin, the border, and the padding.


More generally

The main take-away from all of this is to make sure to always try to define the key properties for whatever stylesheet you're editing. This can be tricky, as I haven't found any single location that defines all of the stylesheet properties available for each QWidget, but the Qt Stylesheet Reference can give some hints as to what's available. (Note that there are probably additional places to look within the documentation, but this is the easiest place I've found to look so far).

Another example of a key property to set for QGroupBox is the subcontrol-origin. According to Qt's Stylesheet Reference,

subcontrol-origin: The origin rectangle of the subcontrol within the parent element. If this property is not specified, the default is padding.

So this property will default to padding if you don't explicitly set it. This means that even if you properly add space in the margin for the title, it will still be drawn below the border unless manually moved higher using the bottom/top property.


My Solution

Getting back to the question more specifically though - the solution I've found is to make sure that you explicitly define the margin size so that there is enough space for the title to be drawn (it isn't actually necessary to define the padding size, unless you want a different visual spacing between the border/title and the widget's content). Afterwards, you can then reposition the title, if needed. In my case, this ended up looking like

QGroupBox {
     border: 1px solid #22a4bc;
     border-radius: 0px;
     margin-top: 7px;  /* <- Adds space for title to exist above border */
}

QGroupBox::title {  
     subcontrol-origin: margin;  /* <- Explicitly define or will be set to padding */
     subcontrol-position: top center;  
     margin-left: 3px;
     margin-right: 3px;
     left: 5px;
}

(For those using PyQt, like me, this is written the same regardless of whether you're using C++ or Python, since this is written in QSS (Qt Style Sheet, which is based on the CSS language. I just wrote the comments in the code above using C++ style comments to maintain the same code style as the original question)

like image 42
dustin_dawind Avatar answered Sep 13 '25 01:09

dustin_dawind