QSS - change ONLY top and bottom borders of a QFrame



  • Hey,

    I'm not experienced with CSS/QSS, but how could I set ONLY the top and bottom borders of a QFrame to be, for example, black and have a width of 2px, while the left and right borders would remain unaffected? Also, how do I do this WITHOUT affecting other widgets belonging to the QFrame? I'm curious to see methods through both code and QT Designer -> change styleSheet.

    Thank you!!


  • Moderators

    Basically you can't. Using any style turns native (or the style's built-in) styling off. This means either you style the whole frame or none of it. You can't do both.
    Setting the style in designer or from code is exactly the same. If you set it from the designer, uic (the ui compiler) will generate a call to setStyleSheet() exactly as you would from code.
    As to how to limit the scope of the style - the easiest is to give the frame a name, and then just refer to that name in the stylesheet. You can do that either from designer or from code. Here's a code example:

    ui->someFrame->setObjectName("Foo");
    ui->someFrame->setStyleSheet("#Foo { border-top: 2px solid black; }");
    


  • @Chris-Kawa Thank you very much, it seems to work. Sadly, now I've run into another problem: I've got a QTableWidget with 2 columns and it has 2 entries. In all the 4 occupied columns, I have QFrames (the first column contains objects of a class that extends QFrame and the other column objects of another class that extends QFrame). I tried using the setObjectName, setStyleSheet you provided in both these classes (even tried different object names for them), but the borders (top and bottom, I've only changed those) for the item in the second entry, second column, do not display properly (they seem like translated, in that they seem to have proper distance between them, but they're considerably lower (maybe more than 5p or even 10p?) than they should be. Could this be cause by the fact that I've called QTableWidget::resizeColumnsToContents() or something?

    The code I've used for one of the classes is [I've done this in THE classes themselves, calling the two methods in the constructor just as I've shown, NOT outside. I hope this is not wrong] :
    setObjectName("Foo");
    setStyleSheet("#Foo { border-top: 2px solid black; border-bottom: 2px solid black; }");
    and for the other:
    setObjectName("Foo2");
    setStyleSheet("#Foo2 { border-top: 2px solid black; border-bottom: 2px solid black; }");

    This is pretty much how it would look (please ignore the unclear text under/over the top problematic porder and the red underline, those are because of my editing of the photo)

    EDIT: I'm setting the widgets in the cells using the setCellWidget method of QTableWidget.
    EDIT2: If I open the problematic QFrame with the .show method in the main method, it displays its borders properly (just like it's displayed in the first entry of the table). I wonder what's causing this.
    EDIT3: Adding more entries to the table seems to have the same effect: only the first entry is shown properly, the others having the same problem.

    Borders problem



  • Regarding the problem in the post just above, apparently it works properly if I call QTableWidget::resizeRowsToContents() and QTableWidget::resizeColumnsToContents() after adding each new entry (maybe I should just call them for the newly added entry to be more efficient (resizeRowToContents and resizeColumnToContents).

    EDIT:
    @Chris-Kawa I don't know why I can't flag your post as the answer to my question :(. Still, I've upvoted it and marked the topic as solved. Thank you for your help :).


  • Moderators

    I don't know why calling resizeRowsToContents after each widget would help. Seems a bad idea for performance.
    Anyway, I was toying around and made a small example that more or less reflects what you have in the picture. It doesn't seem to suffer from the issue you brought up. Maybe you can use any of it.

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QTableWidget w;
        w.setColumnCount(2);
        w.setRowCount(2);
        w.verticalHeader()->hide();
        w.horizontalHeader()->setStretchLastSection(true);
        w.setHorizontalHeaderLabels({ "Author", "Message" });
        w.setStyleSheet("#Foo { border-top: 2px solid black; border-bottom: 2px solid black; }");
        w.show();
    
        for (int row = 0; row < 2; ++row)
            for (int col = 0; col < 2; ++col)
            {
                auto lay = new QGridLayout();
    
                if (col == 1)
                {
                    lay->addWidget(new QLabel("Sent:"), 0, 0);
                    lay->addWidget(new QPushButton("Quote"), 0, 1);
                    lay->addWidget(new QLabel(), 2, 0);
                    lay->setColumnStretch(0, 1);
                    lay->setColumnStretch(1, 0);
                    auto line = new QFrame();
                    line->setFrameShape(QFrame::HLine);
                    lay->addWidget(line, 1, 0, 1, 2);
                }
    
                auto frame = new QFrame();
                frame->setLayout(lay);
                frame->setObjectName("Foo");
                w.setCellWidget(row, col, frame);
            }
    
        w.resizeRowsToContents();
        return a.exec();
    }
    

    The result is something like this:
    table widget example



  • Thtat's interesting. Thank you very much. I wonder if the problem could have been caused by the fact that initially, my QFrames were QWidgets and then I modified the files (.h, .cpp, .ui) in order to make them QFrames so that I could use the border.


  • Moderators

    You don't need a QFrame to style the borders using qss. Plain QWidget can have borders too.


Log in to reply