Results 1 to 2 of 2

Thread: Creating diagonal table headers

  1. #1
    Join Date
    Jul 2013
    Posts
    7
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Creating diagonal table headers

    Hi--

    I'm trying to create diagonal table headers. So far, it's kind of working, but I'm running into what might be deep problems. My goal is to create a table that looks like this:

    Screen Shot 2013-09-07 at 8.36.15 AM.jpg

    So far, I have subclassed the header and added a custom delegate, getting me here:

    Screen Shot 2013-09-08 at 1.36.49 PM.jpg

    The diagonal and text elements are in the right spot, but they're being drawn on top of by other paint commands or are being stopped by the widgets boundaries.

    Questions:
    1) How can I expand the header boundaries so that my diagonal lines don't get truncated?
    2) How can I draw the diagonal lines on top of the table, instead of having them be draw on top of?


    diagonal_table.cpp
    Qt Code:
    1. #include "diagonal_table.h"
    2. #include <qnamespace.h>
    3.  
    4. #include <Qt>
    5.  
    6. DiagonalTable::DiagonalTable(QWidget *parent) : QTableView(parent)
    7. {
    8. DiagonalHeaderView *horizontalDiagonalHeader = new DiagonalHeaderView(Qt::Horizontal, this);
    9. DiagonalHeaderView *verticalDiagonalHeader = new DiagonalHeaderView(Qt::Vertical, this);
    10. setHorizontalHeader(horizontalDiagonalHeader);
    11. setVerticalHeader(verticalDiagonalHeader);
    12.  
    13. setItemDelegate(new MyDelegate(this));
    14. setShowGrid(false);
    15.  
    16. }
    17.  
    18. DiagonalHeaderView::DiagonalHeaderView(Qt::Orientation orientation, QWidget *parent) : QHeaderView(orientation, parent)
    19. {
    20.  
    21. }
    22.  
    23. void DiagonalHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
    24. {
    25. if (!rect.isValid())
    26. return;
    27.  
    28. initStyleOption(&opt);
    29.  
    30. opt.text = model()->headerData(logicalIndex, orientation(), Qt::DisplayRole).toString();
    31.  
    32.  
    33. // the section position
    34. int visual = visualIndex(logicalIndex);
    35. Q_ASSERT(visual != -1);
    36. if (count() == 1)
    37. opt.position = QStyleOptionHeader::OnlyOneSection;
    38. else if (visual == 0)
    39. opt.position = QStyleOptionHeader::Beginning;
    40. else if (visual == count() - 1)
    41. opt.position = QStyleOptionHeader::End;
    42. else
    43. opt.position = QStyleOptionHeader::Middle;
    44. opt.orientation = orientation();
    45.  
    46. // Get rotation, and wrap to (-180, 180]
    47. double rotation = model()->headerData(logicalIndex, orientation(), DiagonalTable::RotationRole).toFloat();
    48. while (rotation > 180)
    49. rotation -=360;
    50. while (rotation <= -180)
    51. rotation +=360;
    52.  
    53. int separatorLength;
    54. int sumLinePositionX;
    55. int sumLinePositionY;
    56. int textOffsetX;
    57. int textOffsetY;
    58. int textWidth = opt.fontMetrics.width(opt.text);
    59. int textHeight = opt.fontMetrics.height();
    60.  
    61. switch (orientation()) {
    62. case Qt::Horizontal:
    63. {
    64. // Cast parent so that we can use its methods
    65. DiagonalTable * diagonalTable = dynamic_cast<DiagonalTable *>(this->parent());
    66. if (diagonalTable == NULL)
    67. Q_ASSERT(0);
    68.  
    69. // Calculate the rectangle for the box in which we will draw
    70. int firstRow = model()->headerData(logicalIndex, orientation(),DiagonalTable::RowRole).toInt();
    71.  
    72. sumLinePositionX = rect.bottomLeft().x();
    73. sumLinePositionY = rect.bottomLeft().y();
    74.  
    75. for (int i=0; i<firstRow; i++) {
    76. int rowHeight = diagonalTable->rowHeight(i+1);
    77. sumLinePositionY += rowHeight;
    78. }
    79.  
    80. textOffsetX = rect.width()/2 + textHeight/2;
    81. textOffsetY = 0;
    82.  
    83. }
    84. break;
    85. case Qt::Vertical:
    86. {
    87. if (rotation == 0) {
    88. style()->drawControl(QStyle::CE_Header, &opt, painter, this);
    89. } else {
    90. // Cast parent so that we can use its methods
    91. DiagonalTable * diagonalTable = dynamic_cast<DiagonalTable *>(this->parent());
    92. if (diagonalTable == NULL)
    93. Q_ASSERT(0);
    94.  
    95. // Calculate the rectangle for the box in which we will draw
    96. int firstColumn = model()->headerData(logicalIndex, orientation(), DiagonalTable::ColumnRole).toInt();
    97.  
    98. sumLinePositionX = rect.bottomRight().x();
    99. sumLinePositionY = rect.bottomRight().y();
    100.  
    101. for (int i=0; i<firstColumn; i++) {
    102. int columnWidth = diagonalTable->columnWidth(i+1);
    103. sumLinePositionX += columnWidth;
    104. }
    105.  
    106. textOffsetX = 0;
    107. textOffsetY = -rect.height()/2 + textHeight/2;
    108. }
    109. }
    110. break;
    111. }
    112.  
    113. // Paint the diagonal line
    114. // Adjust for rotation
    115. if (rotation > -90 && rotation < 90)
    116. separatorLength = 30;
    117. else
    118. separatorLength = 90;
    119. painter->setRenderHint(QPainter::Antialiasing);
    120. painter->translate(sumLinePositionX, sumLinePositionY);
    121. painter->rotate(rotation);
    122. painter->drawLine(0, 0, separatorLength, 0);
    123.  
    124. // Paint text
    125. painter->resetTransform();
    126. // Adjust for rotation
    127. if (rotation > -90 && rotation < 90) {
    128. painter->translate(sumLinePositionX + textOffsetX, sumLinePositionY + textOffsetY);
    129. painter->rotate(rotation);
    130. painter->translate(2, 0); // Shift text up (along new axis)
    131. } else {
    132. painter->translate(sumLinePositionX + textOffsetX, sumLinePositionY + textOffsetY);
    133. painter->rotate(rotation + 180); // Always draw text from left to right
    134. painter->translate(-textWidth - 2, 0); // Back text up (along new axis)
    135. }
    136. painter->setFont(font()); // This font should be system dependent. Not sure how to get this.
    137. painter->drawText(0, 0, opt.text);
    138.  
    139. }
    140.  
    141.  
    142. void MyDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
    143. {
    144. int row = index.row();
    145. int col = index.column();
    146.  
    147. int firstRow = index.model()->headerData(col, Qt::Horizontal,DiagonalTable::RowRole).toInt();
    148. if (row < firstRow) {
    149. } else {
    150. QPen pen;
    151. int shift = 18; // This makes no sense yet, but for whatever reason the colors are shifted when drawn in the table
    152. pen.setColor(QColor(143+shift, 142+shift, 147+shift));
    153. pen.setWidth(1);
    154. painter->setPen( pen );
    155.  
    156. painter->drawRect( option.rect.x()-1, option.rect.y()-1, option.rect.width(), option.rect.height() );
    157. QItemDelegate::paint( painter, option, index );
    158. }
    159.  
    160. }
    To copy to clipboard, switch view to plain text mode 

    diagonal_table.h
    Qt Code:
    1. #ifndef DIAGONALTABLE_H
    2. #define DIAGONALTABLE_H
    3. #include <QWidget>
    4. #include <QHeaderView>
    5. #include <QItemDelegate>
    6. #include <QPainter>
    7. #include <QTableView>
    8.  
    9. class DiagonalTable : public QTableView
    10. {
    11. Q_OBJECT
    12.  
    13. public:
    14. enum {RotationRole = Qt::UserRole + 0,
    15. RowRole = Qt::UserRole + 1,
    16. ColumnRole = Qt::UserRole + 2};
    17.  
    18. public:
    19. explicit DiagonalTable(QWidget *parent = 0);
    20. ~DiagonalTable();
    21.  
    22. };
    23.  
    24.  
    25. class MyDelegate : public QItemDelegate {
    26. public:
    27. MyDelegate( QObject *parent ) : QItemDelegate( parent ) { }
    28. void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
    29. };
    30.  
    31. class DiagonalHeaderView : public QHeaderView
    32. {
    33. Q_OBJECT
    34.  
    35. public:
    36. DiagonalHeaderView(Qt::Orientation orientation, QWidget *parent = 0);
    37. ~DiagonalHeaderView();
    38. void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
    39.  
    40. };
    41.  
    42. #endif // DIAGONALTABLE_H
    To copy to clipboard, switch view to plain text mode 

    mainwindow.cpp
    Qt Code:
    1. #include "mainwindow.h"
    2. #include "ui_mainwindow.h"
    3. #include "diagonal_table.h"
    4. #include <QStandardItemModel>
    5.  
    6. MainWindow::MainWindow(QWidget *parent) :
    7. QMainWindow(parent),
    8. ui(new Ui::MainWindow)
    9. {
    10. ui->setupUi(this);
    11.  
    12.  
    13. QStandardItemModel *sim = new QStandardItemModel(0,0,ui->tableView);
    14. ui->tableView->setModel(sim);
    15.  
    16. QStringList horizontalHeaderLabels;
    17. horizontalHeaderLabels << "Output channel" << "Channel type" << "Live view" << "Curve 1" << "Curve 2" << "Roll" << "Pitch" << "Yaw";
    18. sim->setHorizontalHeaderLabels(horizontalHeaderLabels);
    19.  
    20. // Set horizontal header rotation
    21. sim->setHeaderData(0, Qt::Horizontal, -150, DiagonalTable::RotationRole);
    22. sim->setHeaderData(1, Qt::Horizontal, -150, DiagonalTable::RotationRole);
    23. sim->setHeaderData(2, Qt::Horizontal, -150, DiagonalTable::RotationRole);
    24. sim->setHeaderData(3, Qt::Horizontal, -45, DiagonalTable::RotationRole);
    25. sim->setHeaderData(4, Qt::Horizontal, -45, DiagonalTable::RotationRole);
    26. sim->setHeaderData(5, Qt::Horizontal, -45, DiagonalTable::RotationRole);
    27. sim->setHeaderData(6, Qt::Horizontal, -45, DiagonalTable::RotationRole);
    28. sim->setHeaderData(7, Qt::Horizontal, -45, DiagonalTable::RotationRole);
    29.  
    30. // Set row for horizontal header. All cella above this point will be empty
    31. sim->setHeaderData(0, Qt::Horizontal, 1, DiagonalTable::RowRole);
    32. sim->setHeaderData(1, Qt::Horizontal, 1, DiagonalTable::RowRole);
    33. sim->setHeaderData(2, Qt::Horizontal, 1, DiagonalTable::RowRole);
    34.  
    35. QStringList verticalHeaderLabels;
    36. verticalHeaderLabels << "Live view" << "Channel 1" << "Channel 2" << "Channel 3"
    37. << "Channel 4" << "Channel 5" << "Channel 6";
    38. sim->setVerticalHeaderLabels(verticalHeaderLabels);
    39.  
    40. // Set vertical header rotation
    41. sim->setHeaderData(0, Qt::Vertical, -150, DiagonalTable::RotationRole);
    42.  
    43. // Set column for vertical header. All cells to the left of this point will be empty
    44. sim->setHeaderData(0, Qt::Vertical, 3, DiagonalTable::ColumnRole);
    45.  
    46. for (int j=0; j < sim->rowCount(); j++) {
    47. for (int i=0; i < sim->columnCount(); i++) {
    48. int firstRow = sim->headerData(i, Qt::Horizontal,DiagonalTable::RowRole).toInt();
    49. if (j < firstRow)
    50. continue;
    51.  
    52. sim->setItem(j,i,new QStandardItem("-1.00"));
    53. }
    54. }
    55.  
    56. ui->tableView->resizeColumnsToContents();
    57. }
    58.  
    59. MainWindow::~MainWindow()
    60. {
    61. delete ui;
    62. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Apr 2012
    Location
    India.
    Posts
    88
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Creating diagonal table headers

    See the below link which creates hierarchical headers, might be helpful to you.

    http://qt-apps.org/content/show.php/...content=103154

  3. The following user says thank you to Rajesh.Rathod for this useful post:

    MarkoSan (1st August 2014)

Similar Threads

  1. Replies: 2
    Last Post: 28th August 2013, 22:53
  2. Replies: 0
    Last Post: 4th May 2011, 13:33
  3. How to make table headers with custom background?
    By kremuwa in forum Qt Programming
    Replies: 1
    Last Post: 14th March 2010, 17:51
  4. QHeaderView -- diagonal headers?
    By vycke in forum Qt Programming
    Replies: 7
    Last Post: 29th April 2008, 00:54
  5. creating table plugin
    By mgurbuz in forum Qt Programming
    Replies: 3
    Last Post: 28th April 2006, 14:50

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.