K120
K120

Reputation: 371

QT Stylesheet for HLine/VLine color

I'm pretty new to this Qt thing and its whole stylesheet system. My background of HTML/CSS helps a little to understand the system, but a lot of things just happens for no apparent reason....or don't happen.

Anyway, the mystery of the HLINE and the VLINE and how to change the lines' color is just a mystery for me. I learned from other questions and various fora that it's linked to the QFrame elements. And I can change the color of the line if I just use something like

QFrame
{
color: red;
}

But this of course changes the color of tons of other things that uses a QFrame as well. I could of course go into the HLINE element and put color: red; in there and that works fine, but my app requires that I put everything in a single stylesheet that gets loaded into the app. So styling individual elements is not an option.

A solution would look something like

QFrame HLine, QFrame VLine
{
color: red;
}

Upvotes: 12

Views: 20068

Answers (5)

Alex Nevskiy
Alex Nevskiy

Reputation: 407

You can leave Qt's hlines and build up your own very easy. For frames you want looks like hline add property "class" as "HLine" (for example), in designer or in c++ code:

frame->setProperty("class", "HLine")

. Then, you can define in main view's or in global app stylesheet something like this:

QFrame.HLine {
    border: none;
    border-bottom: 2px solid red;
} 

and you will get horizontal two pixels red line.

Upvotes: 0

Milosz Blizniak
Milosz Blizniak

Reputation: 21

According to QDarkStyleSheet issue, You could use:

QFrame[width="3"], QFrame[height="3]

These selectors, they seem to work cross-platform, and they are unlikely to change. Probably better than using enum values as ints, as they are likely to change with Qt versions, and line styling are not, as they fulfill certain requirements.

Upvotes: 2

waldyrious
waldyrious

Reputation: 3844

HLine and VLine are tricky to style. It's worth taking a look at the "Detailed Description" section of the documentation. For a quick fix, I found that this set of rules allows customizing the appearance of such lines via stylesheet in a reliable and relatively clean manner:

QFrame[frameShape="4"],
QFrame[frameShape="5"]
{
    border: none;
    background: red;
}

This works regardless of the frameShadow property, which otherwise affects their appearance and the effect of style rules. Keep in mind that the width of the lines are not 1px by default -- this can be changed using the min-width, max-width, min-height or max-height properties, as appropriate.

For a more detailed overview of my findings, read along.


Most QFrames have the QFrame::Plain frameShape by default, but HLine and VLine's default frameShape is QFrame::Sunken. This means that they are not really lines, but thin boxes that contain a mid-line that's used to provide the 3D effect. From the documentation:

The mid-line width specifies the width of an extra line in the middle of the frame, which uses a third color to obtain a special 3D effect. Notice that a mid-line is only drawn for Box, HLine and VLine frames that are raised or sunken.

If you set the frameShape to Plain, this midline is still visible, and can be styled with the color property (note: that's not a background-color or border-color!)

But this doesn't work for a HLine/VLine that's left with the default Sunken appearance. One way to fix this could be to set separate styles for Plain and Sunken QFrames by using attribute selectors with the decimal values of the property enums (which are described in the documentation in hehadecimal), like so:

/* Reference (from doc.qt.io/qt-5/qframe.html#types):
 * - frameShape[4] --> QFrame::HLine = 0x0004
 * - frameShape[5] --> QFrame::VLine = 0x0005
 * - frameShadow[16] --> QFrame::Plain = 0x0010 (default for most widgets)
 * - frameShadow[48] --> QFrame::Sunken = 0x0030 (default for HLine/VLine)
 */
QFrame[frameShape="4"][frameShadow="16"],
QFrame[frameShape="5"][frameShadow="16"]
{
    ...
}

QFrame[frameShape="4"][frameShadow="48"],
QFrame[frameShape="5"][frameShadow="48"]
{
    ...
}

but since the styles that work for HLine/VLine with QFrame::Sunken also work for those with QFrame::Plain, it's usually a waste to do so. I show them above for educational value only about how to use attribute selectors.

The best approach is to treat the QFrame as the box that it is, and either (1) set border-top or border-right coupled with a max-height: 0px (or max-width for a VLine), to ensure the inside of the box doesn't take up space in the layout; or (2) use a background color coupled with border: none (in which case, max-height/width should be 1 or larger, otherwise the QFrame is invisible). The latter is the solution I'd recommend, as shown in the first code block above.

Hope this helps!

Upvotes: 16

york.beta
york.beta

Reputation: 1827

QFrame[frameShape="4"] /* QFrame::HLine == 0x0004 */
{
    color: red;
}

QFrame[frameShape="5"] /* QFrame::VLine == 0x0005 */
{
    color: green;
}

Upvotes: 20

s4eed
s4eed

Reputation: 7891

but my app requires that i put everything in a single stylesheet that gets loaded into the app.

You can use Conflict Resolution. Suppose that you have a QMainWindow object with lots of widgets on it . Set these style sheets for the maindionw style sheet :

QLabel#label{
    background-color: rgb(255, 170, 255);
}
QPushButton#pushButton{

    color: rgb(0, 0, 255);
}
QFrame#line{
    background-color: rgb(0, 170, 255);
}

The first css just changes a QLabel name label on your mainwindow and set its back color to rgb(255, 170, 255). The next will change text color of a QPushButton named pushButton to (0,0,255);. The third one change property of a line.Lines are just a QFrame.
So the solution that I can offer is to place your css in a file and then load this file using QFile and QTextStream and then set the contents of the file for css of your main winodw or main widget using setStyleSheet ( const QString & styleSheet ) function. or If you are using creator just right click on your main window and select change stylesheet and then paste your css. But bear in mind that you should use conflict resolution.

Upvotes: 1

Related Questions