How to set orientation of text in horizontal header ?



  • I've got QTableWidget with horizontal and vertical header. I need to change text orientation in vertical header items to save some place in table. Because the data in table items is just checkBox which can be checked or unchecked. So the question is: is it possible to change text orientation in horizontal header items and if it does, how can I change it ?



  • you can create a delegate to achieve this.
    A header is just a QHeaderView which is derived from QAbstractItemView. So you can create a delegate and set the delegate to the header view. The delegate could do text drawing in any rotation.



  • [quote author="Gerolf" date="1302249490"]you can create a delegate to achieve this.
    A header is just a QHeaderView which is derived from QAbstractItemView. So you can create a delegate and set the delegate to the header view. The delegate could do text drawing in any rotation.[/quote]

    Actually, delegates don't work for QHeaderView rendering. The documentation states:
    [quote]
    Note: Each header renders the data for each section itself, and does not rely on a delegate. As a result, calling a header's setItemDelegate() function will have no effect.[/quote]
    So, subclass QHeaderView and reimplement paintEvent().



  • Oh, sorry, havent seen this,

    But i suggest overwriting paintSection instead of paintEvent :-)



  • Yes, great plan :-)



  • I added a class based by QHeaderView but I can't change orientation of text. Where do I make mistake:
    @protected: void paintSection ( QPainter * painter, const QRect & rect, int logicalIndex ) const{
    if(m_orientation == Qt::Horizontal)
    {
    painter->save();
    QHeaderView::paintSection(painter, rect, logicalIndex);
    painter->restore();
    painter->rotate(90);
    }
    else
    QHeaderView::paintSection (painter,rect,logicalIndex );
    }@



  • You first painting, and then rotating. That doesn't work. First rotate, and then paint. However, I think you will have to do the painting of the background yourself first (reference the implementation of QHeaderView for details on how to do that), then save the painter state, then rotate the painter, and then paint the text. Then, at the end of rotating, you restore the painter.



  • I don't know what text I need to draw, because it's in UI or added by setHorizontalHeaderLabels(setVerticalHeaderLabels), so I need to rotate all containing data in header. How can I store all this data to paint after rotating painter ? And then draw. It also been useful when header item will resize to it's content.



  • Yes, you do know what text to draw, as you have access to the logicalIndex. Reference the implementation of QHeaderView for how drawing is implemented there. The paintSection method in that class -uses- should use the exact same data that you have available in your implementation of paintSection.



  • In Assistant i find only this:
    void QHeaderView::paintSection ( QPainter * painter, const QRect & rect, int logicalIndex ) const [virtual protected]

    Paints the section specified by the given logicalIndex, using the given painter and rect.

    Normally, you do not have to call this function.



  • I mean: open up the source code of QHeaderView to take a peek on how this works in Qt, and use that solution as inspiration on how your own implementation may work. Since we're all developers here, I assume you're not afraid to read source code?



  • Thanks, Andre, I will look at it.



  • I modified my paintSection function like this:
    @if(m_orientation == Qt::Horizontal)
    {
    //////////////////////////////////////////////////////////////////////////
    if (!rect.isValid())
    return;
    // get the state of the section
    QStyleOptionHeader opt;
    initStyleOption(&opt);
    QStyle::State state = QStyle::State_None;
    if (isEnabled())
    state |= QStyle::State_Enabled;
    if (window()->isActiveWindow())
    state |= QStyle::State_Active;

      if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex)
       opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
       ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
    
      // setup the style options structure
      opt.rect = rect;
      opt.section = logicalIndex;
      opt.state |= state;
    
      opt.iconAlignment = Qt::AlignVCenter;
    
      opt.text = model()->headerData(logicalIndex, m_orientation,
       Qt::DisplayRole).toString();
    
      QPointF oldBO = painter->brushOrigin();
    
    
      // the section position
      int visual = visualIndex(logicalIndex);
      Q_ASSERT(visual != -1);
      if (count() == 1)
       opt.position = QStyleOptionHeader::OnlyOneSection;
      else if (visual == 0)
       opt.position = QStyleOptionHeader::Beginning;
      else if (visual == count() - 1)
       opt.position = QStyleOptionHeader::End;
      else
       opt.position = QStyleOptionHeader::Middle;
    
      // the selected position
    
      // draw the section
      painter->rotate(90); // Actually the rotation
      style()->drawControl(QStyle::CE_Header, &opt, painter, this);
    
      painter->setBrushOrigin(oldBO);
      //////////////////////////////////////////////////////////////////////////
     }
     else
      QHeaderView::paintSection (painter,rect,logicalIndex );@
    

    And now I need to resize header to it's contents. So how can I resize header to max length string size ? And it's rotates all my header not each item by 90 degree.



  • I find solution to draw text by searching a forum:
    @painter->save();
    painter->translate(rect.x(), rect.y());
    painter->rotate(90); // or 270
    painter->drawText(0, 0, model()->headerData(logicalIndex, m_orientation,Qt::DisplayRole).toString());
    painter->restore();@
    "Link":http://developer.qt.nokia.com/faq/answer/how_can_i_draw_vertical_text
    But if I draw text by this method I lost my header control and get only text. I mean no system styled header and just text on flat panel. And I still need to resize header by it's content.



  • I would modify your previous version of the code (from the post from yesterday) around line 47. What I would do, is first draw a section without text, by modifying the opt variable:

    @
    //replacing lines 47 - 50

    //store the header text
    QString headerText = opt.text;
    //reset the header text to no text
    opt.text = QString();
    //draw the control (unrotated!)
    style()->drawControl(QStyle::CE_Header, &opt, painter, this);

    painter.save();
    painter->translate(rect.x(), rect.y());
    painter->rotate(90); // or 270
    painter->drawText(0, 0, headerText);
    painter->restore();
    @

    That should take care of the actual drawing.

    As for the re-sizing, I think you need to reimplement sizeHint() to return the right size.



  • I write the following code and I have no result. I have a header without any text at all. I think that save and restore functions for painter has no effect after calling drawControl function. So I thinking about some modifications to draw with QStyle::CE_HeaderSection but can't find any typical examples or any other ideas. I tried to draw replacing QStyle::CE_Header by QStyle::CE_HeaderSection and also have no text in header.



  • How can I get the painter for each item of my header to rotate it ? This must be the way to solve this task. I also tried to use custom style with same code, but also has no result. ("Style examle":http://developer.qt.nokia.com/faq/answer/how_can_i_display_vertical_text_in_the_section_of_a_qheaderview) It will be useful to have such function for QHeaderView like setVerticalText(bool). Maybe it possible to realize it in next Qt release.



  • I found some way to solve this in table widget which I use:
    @QHeaderView * header = m_ui->tableWidget->horizontalHeader();

    int columnCnt = m_ui->tableWidget->columnCount();
    int width = header->width()/columnCnt;
    int height = header->height();

    for(int i = 0; i<columnCnt; i++)
    {
    QTableWidgetItem * item = m_ui->tableWidget->horizontalHeaderItem(i);

    if(item == NULL)
    continue;

    QVariant data = item->data(Qt::DisplayRole);

    if (data.isValid())
    {
    QString text=data.toString();
    item->setData(Qt::DisplayRole, "");
    QPixmap original_button(width, height);
    QPainter original_button_painter(&original_button);
    /* QHeaderView::paintSection(&original_button_painter, QRect(0, 0, width, height), i);*/

    QPixmap pix(width, height);
    QPainter p(&pix);
    p.drawPixmap(0, 0, original_button);

    QRect new_r(0, 0, height, width);
    QMatrix m;
    m.translate(0, height);
    m.rotate(-90);
    p.setWorldMatrix(m, true);
    p.drawText(new_r, Qt::AlignCenter, text);

    item->setIcon(pix);
    item->setSizeHint(QSize( height, width ));
    }
    }@
    This code I place on my dialog which holds table widget in ui file. So the only one question is how to set true sizes of the text? It looks smaller then text in vertical header. Waiting for your code critic and propositions.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.