PDA

View Full Version : Vertical label on table horizontal header



ipkiss
7th November 2012, 16:06
Hi,

I am trying to have the text on a horizontal header displayed vertically (i.e. rotated 90°).
I tried the implementation given here (http://qt-project.org/faq/answer/how_can_i_display_vertical_text_in_the_section_of_ a_qheaderview), but there are several issues. Here they are, ordered by increasing gravity:



The vertical header is modified, not the horizontal one. This bug is easy to fix, we just need to replace line 12 with:

if (!hv || hv->orientation() != Qt::Horizontal)

Even though I tried applying my new style only to a particular table (myTable->setStyle(myProxyStyle)), all the tables in the application are modified. How can I avoid that?


Last but not least, the height of the horizontal header is not adjusted to take into account the size of the label. As a result, the text is truncated (and thus mostly useless). I tried two approaches to solve this problem:

override QProxyStyle::sizeForContents(). I expected that it would be called for ContentsType CT_HeaderSection, but unfortunately it is not (it is however called for each view item, which doesn't help).
override QProxyStyle::subControlRect(). I hoped that it would be called for SubControl SE_HeaderLabel, but it is not.

Does anyone have a suggestion about how to solve this problem?


Note: I'm using Qt 4.8.

davethomaspilot
11th February 2014, 19:28
Old thread, I know. I'm interested in the same thing.


For your 2) I set the style on the specific tableView like this:

ui->tableView->setStyle(new MyStyle(ui->tableView->style()));

I did this before assigned the view to the model:

ui->tableView->setModel(model);


On 1)
Thanks for pointing out the need to change if (!hv || hv->orientation() != Qt::Horizontal). My horizontal headers weren't changing at all, and I just gave up.

I still have the same issue 3--working it now.

I really like to rotate header text, since frequently the header is wider than any of the column contents for columns that contain short data items (e.g single characters, booleans, etc). With rotated headers, I can then size each column of the table for the maximum expected data size, rather than the width required to see the label.

A workaround for 3) that works for me is to set the minimum height of the column:

ui->tableView->horizontalHeader()->setMinimumHeight(150);

Also, I wanted the text to read from bottom to top,not top to bottom. So, I used -90 for the rotate and changed the painter::translate to use bottomLeft. Then I decided I like -45 better than -90. Here's what I ended up with:



void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter,
const QWidget *widget = 0) const
{
if (element == QStyle::CE_HeaderLabel) {
const QHeaderView *hv = qobject_cast<const QHeaderView *>(widget);
if (!hv || hv->orientation() != Qt::Horizontal)
return QProxyStyle::drawControl(element, option, painter, widget);
const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option);
painter->save();
// painter->translate(header->rect.topLeft());
painter->translate(header->rect.bottomLeft());

painter->rotate(-45);
painter->drawText(0,0,header->text);
painter->restore();
return;
}
return QProxyStyle::drawControl(element, option, painter, widget);
}
};