How can I insert a checkbox into the header of my view?

Currently there is no API to insert widgets in the header, but you can paint the checkbox yourself in order to insert it into the header.

What you could do is to subclass QHeaderView, reimplement paintSection() [doc.qt.nokia.com] and then call drawPrimitive() [doc.qt.nokia.com] PE_IndicatorCheckBox in the section where you want to have this checkbox.

You would also need to reimplement the mousePressEvent() [doc.qt.nokia.com] to detect when the checkbox is clicked, in order to paint the checked and unchecked states.

The example below illustrates how this can be done:

  1. #include <QtGui>
  2.  
  3. class MyHeader : public QHeaderView
  4. {
  5. public:
  6.   MyHeader(Qt::Orientation orientation, QWidget * parent = 0) : QHeaderView(orientation, parent)
  7.   {}
  8.  
  9. protected:
  10.   void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
  11.   {
  12.     painter->save();
  13.     QHeaderView::paintSection(painter, rect, logicalIndex);  
  14.     painter->restore();
  15.     if (logicalIndex == 0)
  16.     {
  17.       QStyleOptionButton option;
  18.       option.rect = QRect(10,10,10,10);
  19.       if (isOn)
  20.         option.state = QStyle::State_On;
  21.       else
  22.         option.state = QStyle::State_Off;
  23.       this->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter);
  24.     }
  25.                
  26.   }
  27.   void mousePressEvent(QMouseEvent *event)
  28.   {
  29.     if (isOn)
  30.       isOn = false;
  31.     else
  32.       isOn = true;
  33.     this->update();
  34.     QHeaderView::mousePressEvent(event);
  35.   }
  36. private:
  37.   bool isOn;
  38. };
  39.  
  40.  
  41. int main(int argc, char **argv)
  42. {
  43.   QApplication app(argc, argv);
  44.   QTableWidget table;
  45.   table.setRowCount(4);
  46.   table.setColumnCount(3);
  47.  
  48.   MyHeader *myHeader = new MyHeader(Qt::Horizontal, &table);
  49.   table.setHorizontalHeader(myHeader);  
  50.   table.show();
  51.   return app.exec();
  52. }

To have all your other checkboxes checked, you could use the pressed() signal which should be fired from the mousePressEvent() [doc.qt.nokia.com] and connect it to a custom slot where you set all your checkboxes checked or unchecked. See:

2 comments

August 8, 2010

Picture of kenji kenji

Ant Farmer

The checkbox is partially displayed in Mac OS X. And the position of checkbox is not correct in Windows, Cleanlook, Plastique and so on.

September 30, 2010

Picture of eduardhc eduardhc

Lab Rat

A couple of (possible) improvements:

  • You might use style()->drawControl() instead of style()->drawPrimitive(): this way, it draws a full control, not only the internal tick mark
  • You can also pass the whole section rect to the call, and drawControl() wil draw the widget left-aligned.
  • Use updateSection() instead of update(): for any unknown reason, I wasn’t receiving the painting events until the mouse left the header area. Quite weird…

Anyway, big thanks for the code tip. It’s really working fine for me right now.

Write a comment

Sorry, you must be logged in to post a comment.