简体   繁体   中英

How can I have a frozen horizontal header in a scrollable QTableWidget?

I am creating a single-column QTableWidget for my application ( _tw ). I want this QTableWidget to be scrollable, both vertically and horizontally. I hid the vertical header but I need the horizontal header. The problem is that I can't get a "frozen" (insensible to horizontal scroll) horizontal header, and the text of this header is often hidden in the scroll. Furthermore, after the vertical scroll bar, I can see pixels of my horizontal header, which is unwanted.

I have tried to tackle the issue differently, as I already struggled to make this table scrollable horizontally. Unsucessfully, I tried to repositionate the header each time the scroll bar is moved. Even if I failed, this feels more like a workaround than a solution.

_tw->setHorizontalScroolBarPolicy(Qt::ScrollBarAlwaysOn);
_tw->setHorizontalScroolMode(QAbstractItemView::ScrollPerPixel);
_tw->verticalHeader()->hide();
_tw->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
_tw->horizontalHeader()->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
_tw->horizontalHeader()->setFixedHeight(_headerHeight);
_tw->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);

_tw->horizontalHeader()->setFixedWitdh(_tableWidth);
_tw->setFixedWidth(_tableWidth);

_tw->setColumnWidth(0, _tableWidth + _offset);

I expect the horizontal header to be at the same width of the table, and insensible to scroll. It is currently not the case: the header has the size of the column (bigger than what is displayed on the screen). Since the headter text is aligned horizontally, it is not shown and moves with the scroll.

You can try creating a custom class that will apply header-like area to any QAbstractScrollArea (including QTableWidget ) and setting viewport margins on your tablewidget. You won't need to mangle with header not beeing scrolled, but if you need some header-like behaviour, you will need to do it manually.

Untested code:

class Header: public QWidget
{
public:
    Header(QAbstractScrollArea* parent=nullptr): QWidget(parent)
    {
        setFixedSize(parent->width(), 40);
    }

    virtual void paintEvent(QPaintEvent* event)
    {
        QPainter painter(this);
        QFont font("Arial");
        QFontMetrics fm(font);
        QRect txtRect;
        QString txt = "Header_name";
        txtRect = fm.boundingRect(txt).trabslated(dx, dy);//translate it to position you want
        painter.setFont(font);
        painter.painter.drawText(txtRect, txt);
    }
};

Then set viewport margins on your tablewidget, something like this:

_tw->setViewportMargins(0, 40, 0, 0);

Then just create instance of Header :

Header *header = new Header(_tw);

If this code works - Romha Korev gets the credit. I took the idea from his answer to this question .

Hope this helps.

All the others solutions I tried gave me some pixel gaps that I found too noticeable. I decided to go big, and create a custom QWidget specifically for answering this problem.

Basically I just created a QWidget simply containing the QTableWidget , with no header. For the sake of keeping everything at the same size, I aded a line, which is going to stay empty and will be hidden by a QPushButton . I give this line the height I want for my header, for the same reason.

After modifying the behaviour of the QTableWidget so it would skip the first line, I created a QPushButton with my custom widget as the parent. Fortunately enough in my application, they have the same look as the other QHeader . To make the button "on top of" the empty line, since this is a custom widget, a simple button->move(0, 2); did the trick.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM