enter image description here

I would like to change text orientation of tablewidget's vertical header. I intend to change it from the default horizontal to vertical . Bottom to top.

1

Best Answer


Displaying vertical text in table headers

Unfortunately, QHeaderView does not support custom delegates. However, we can subclass QHeaderView and override paintSection and sectionSizeFromContents and paint the text vertically there. Note that we can reuse the same base implementation that takes various factors into account while rendering (e.g. if the mouse pointer is over the header, if the user is clicking on the header, ...) and get all of these considerations for free. Here is how I would implement such a class:

//a header view that renders text verticallyclass VerticalHeaderView : public QHeaderView {public:explicit VerticalHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr): QHeaderView(orientation, parent) {}void paintSection(QPainter *painter, const QRect &rect,int logicalIndex) const override {QPointF rectCenter = QRectF(rect).center();painter->save();//rotate around rectCenterpainter->translate(rectCenter.x(), rectCenter.y());painter->rotate(-90.0);painter->translate(-rectCenter.x(), -rectCenter.y());//apply the same transformation on the rectQRect rectCopy = painter->worldTransform().mapRect(rect);//use base paintSection method after applying required transformationsQHeaderView::paintSection(painter, rectCopy, logicalIndex);painter->restore();}QSize sectionSizeFromContents(int logicalIndex) const override {//get sizeHint from base sizeHint methodQSize val = QHeaderView::sectionSizeFromContents(logicalIndex);//swap height and widthreturn QSize(val.height(), val.width());}};

To use the above class, we need to set it on our QTableView/QTableWidget using setVerticalHeader() (it can be used as the table's horizontal header too, but this doesn't make sense in most of the cases). Here is a complete example that shows the above class in action:

screenshot

#include <QtWidgets>//a header view that renders text verticallyclass VerticalHeaderView : public QHeaderView {public:explicit VerticalHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr): QHeaderView(orientation, parent) {}void paintSection(QPainter *painter, const QRect &rect,int logicalIndex) const override {QPointF rectCenter = QRectF(rect).center();painter->save();//rotate around rectCenterpainter->translate(rectCenter.x(), rectCenter.y());painter->rotate(-90.0);painter->translate(-rectCenter.x(), -rectCenter.y());//apply the same transformation on the rectQRect rectCopy = painter->worldTransform().mapRect(rect);//use base paintSection method after applying required transformationsQHeaderView::paintSection(painter, rectCopy, logicalIndex);painter->restore();}QSize sectionSizeFromContents(int logicalIndex) const override {//get sizeHint from base sizeHint methodQSize val = QHeaderView::sectionSizeFromContents(logicalIndex);//swap height and widthreturn QSize(val.height(), val.width());}};int main(int argc, char *argv[]) {QApplication a(argc, argv);//setup model with dummy dataQStandardItemModel model(0, 1);for(int i=0; i<5; i++) {model.appendRow(new QStandardItem(QStringLiteral("Lorem ipsum dolor sit ""amet, consectetur adipiscing elit, sed do eiusmod tempor ""incididunt ut labore et dolore magna aliqua. Ut enim ad ""minim veniam, quis nostrud exercitation ullamco laboris ""nisi ut aliquip ex ea commodo consequat.")));model.setHeaderData(i, Qt::Vertical,QDate::currentDate().toString("dd-MM-yyyy"),Qt::DisplayRole);model.setHeaderData(i, Qt::Vertical, Qt::AlignCenter, Qt::TextAlignmentRole);}//setup viewQTableView view;VerticalHeaderView headerView(Qt::Vertical);view.setVerticalHeader(&headerView); //set our custom headerviewview.verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);view.setModel(&model);view.show();return a.exec();}

Displaying vertical text in table cells *

You can write a delegate class that renders text vertically. You would need to override paint and sizeHint and provide your code there. It is also possible to reuse the same base implementation after applying the required transformations. Here is how I would implement such a class:

//a delegate that renders text verticallyclass VerticalTextDelegate : public QStyledItemDelegate {public:explicit VerticalTextDelegate(QObject *parent = nullptr): QStyledItemDelegate(parent){}virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const override {QStyleOptionViewItem optionCopy = option;QPointF rectCenter = QRectF(option.rect).center();painter->save();//rotate around rectCenterpainter->translate(rectCenter.x(), rectCenter.y());painter->rotate(-90.0);painter->translate(-rectCenter.x(), -rectCenter.y());//apply the same transformation on the rectoptionCopy.rect = painter->worldTransform().mapRect(option.rect);//use base paint method after applying required transformationsQStyledItemDelegate::paint(painter, optionCopy, index);painter->restore();}virtual QSize sizeHint(const QStyleOptionViewItem &option,const QModelIndex &index) const override {//get sizeHint from base sizeHint methodQSize val = QStyledItemDelegate::sizeHint(option, index);//swap height and widthreturn QSize(val.height(), val.width());}};

Here is a complete example that uses the above class:

screenshot

#include <QtWidgets>//a delegate that renders text verticallyclass VerticalTextDelegate : public QStyledItemDelegate {public:explicit VerticalTextDelegate(QObject *parent = nullptr): QStyledItemDelegate(parent){}virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const override {QStyleOptionViewItem optionCopy = option;QPointF rectCenter = QRectF(option.rect).center();painter->save();//rotate around rectCenterpainter->translate(rectCenter.x(), rectCenter.y());painter->rotate(-90.0);painter->translate(-rectCenter.x(), -rectCenter.y());//apply the same transformation on the rectoptionCopy.rect = painter->worldTransform().mapRect(option.rect);//use base paint method after applying required transformationsQStyledItemDelegate::paint(painter, optionCopy, index);painter->restore();}virtual QSize sizeHint(const QStyleOptionViewItem &option,const QModelIndex &index) const override {//get sizeHint from base sizeHint methodQSize val = QStyledItemDelegate::sizeHint(option, index);//swap height and widthreturn QSize(val.height(), val.width());}};int main(int argc, char *argv[]) {QApplication a(argc, argv);//setup model with dummy dataQStandardItemModel model(0, 2);for(int i=0; i<5; i++) {model.appendRow({new QStandardItem(QDate::currentDate().toString("dd-MM-yyyy")),new QStandardItem(QStringLiteral("Lorem ipsum dolor sit ""amet, consectetur adipiscing elit, sed do eiusmod tempor ""incididunt ut labore et dolore magna aliqua. Ut enim ad ""minim veniam, quis nostrud exercitation ullamco laboris ""nisi ut aliquip ex ea commodo consequat."))});model.setData(model.index(i, 0), Qt::AlignCenter, Qt::TextAlignmentRole);}//setup view and delegateQTableView view;VerticalTextDelegate delegate;view.verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);view.setItemDelegateForColumn(0, &delegate);view.setModel(&model);view.show();return a.exec();}

Apparently, I misinterpreted the question when I first answered it, but I am leaving this as a separate section as it might be useful for future readers.