March 10, 2011

rovshanb rovshanb
Lab Rat
6 posts

[Solved] Painting in custom delegate

 

Hi, I’ve created a custom delegate for use in in a class derived from QTableView. This delagate must display as a checkbox centered horizontally and vertically in table cell. I’ve managed to implement createEditor, setEditorData, setModelData and updateEditorGeometry methods correctly. Now I’m trying to implement the paint method. Below is my code:

  1. void BooleanDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
  2. {
  3.     QVariant value=index.data();
  4.     if (!value.isValid() || qVariantCanConvert<bool>(value)) {
  5.         bool boolVal = value.isValid() ? value.toBool() : defaultValue;
  6.  
  7.         QStyle *style=qApp->style();
  8.  
  9.         QStyleOptionViewItem modifiedOption(option);
  10.  
  11.         QRect checkBoxRect=style->subElementRect(QStyle::SE_CheckBoxIndicator, &option);
  12.         int centerX=option.rect.left() + qMax(option.rect.width()/2-checkBoxRect.width()/2, 0);
  13.         int centerY=option.rect.top() + qMax(option.rect.height()/2-checkBoxRect.height()/2, 0);
  14.         modifiedOption.rect.moveTo(centerX, centerY);
  15.  
  16.         if(boolVal){
  17.             modifiedOption.state |= QStyle::State_On;
  18.         }
  19.  
  20.         style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &modifiedOption, painter);
  21.     }else {
  22.         QStyledItemDelegate::paint(painter, option, index);
  23.     }
  24. }

On Linux this code works fine, also on Windows XP and Windows 7 with classic style everything is OK.But when I switch to modern styles (on Windows XP and 7) checkbox gets rendered at the bottom right corner of the table cell. On the other hand if I comment out these lines:

  1. QRect checkBoxRect=style->subElementRect(QStyle::SE_CheckBoxIndicator, &option);
  2. int centerX=option.rect.left() + qMax(option.rect.width()/2-checkBoxRect.width()/2, 0);
  3. int centerY=option.rect.top() + qMax(option.rect.height()/2-checkBoxRect.height()/2, 0);
  4. modifiedOption.rect.moveTo(centerX, centerY);

then checkbox gets rendered at the top left corner of the cell in Linux and Windows classic styles (and at the center on Windows modern styles). I tried setting modifiedOption.decorationAlignment and displayAlignment to Qt::AlignHCenter | Qt::AlignVCenter but it did not help.

How should I fix it? I want checkbox to be displayed at the center all the time.

Thanks in advance!

3 replies

March 10, 2011

rovshanb rovshanb
Lab Rat
6 posts

I think I found solution:

  1. void BooleanDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
  2.                          const QModelIndex &index) const
  3. {
  4.     QVariant value=index.data();
  5.     if (!value.isValid() || qVariantCanConvert<bool>(value)) {
  6.         bool boolVal = value.isValid() ? value.toBool() : defaultValue;
  7.  
  8.         QStyle *style=qApp->style();
  9.  
  10.         QRect checkBoxRect=style->subElementRect(QStyle::SE_CheckBoxIndicator, &option);
  11.         int chkWidth=checkBoxRect.width();
  12.         int chkHeight=checkBoxRect.height();
  13.  
  14.         QStyleOptionViewItem modifiedOption(option);
  15.         modifiedOption.rect.moveTo(0, 0);
  16.         modifiedOption.rect.setSize(QSize(chkWidth, chkHeight));
  17.         if(boolVal){
  18.             modifiedOption.state |= QStyle::State_On;
  19.         }
  20.  
  21.         QPixmap checkboxPixmap(chkWidth, chkHeight);
  22.         QPainter pixmapPainter(&checkboxPixmap);
  23.         pixmapPainter.fillRect(0, 0, chkWidth, chkHeight, index.row()%2==0 ? qApp->palette().base() : qApp->palette().alternateBase());
  24.         style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &modifiedOption, &pixmapPainter);
  25.  
  26.         int centerX=option.rect.left() + qMax(option.rect.width()/2-chkWidth/2, 0);
  27.         int centerY=option.rect.top() + qMax(option.rect.height()/2-chkHeight/2, 0);
  28.  
  29.         painter->drawPixmap(centerX, centerY, chkWidth, chkHeight, checkboxPixmap);
  30.     }else {
  31.         QStyledItemDelegate::paint(painter, option, index);
  32.     }
  33. }

This seems to work in all scenarios.

March 10, 2011

rovshanb rovshanb
Lab Rat
6 posts

Final version (just in case it will be useful to someone else):

  1. void BooleanDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
  2.                          const QModelIndex &index) const
  3. {
  4.     QVariant value=index.data();
  5.     if (!value.isValid() || qVariantCanConvert<bool>(value)) {
  6.         bool boolVal = value.isValid() ? value.toBool() : defaultValue;
  7.  
  8.         QStyle *style=qApp->style();
  9.  
  10.         QRect checkBoxRect=style->subElementRect(QStyle::SE_CheckBoxIndicator, &option);
  11.         int chkWidth=checkBoxRect.width();
  12.         int chkHeight=checkBoxRect.height();
  13.  
  14.         int centerX=option.rect.left() + qMax(option.rect.width()/2-chkWidth/2, 0);
  15.         int centerY=option.rect.top() + qMax(option.rect.height()/2-chkHeight/2, 0);
  16.         QStyleOptionViewItem modifiedOption(option);
  17.         modifiedOption.rect.moveTo(centerX, centerY);
  18.         modifiedOption.rect.setSize(QSize(chkWidth, chkHeight));
  19.         if(boolVal){
  20.             modifiedOption.state |= QStyle::State_On;
  21.         }
  22.  
  23.         style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &modifiedOption, painter);
  24.     }else {
  25.         QStyledItemDelegate::paint(painter, option, index);
  26.     }
  27. }

July 7, 2011

p91paul p91paul
Lab Rat
26 posts

this post is old, but not too much to say thank you! :D

 
  ‹‹ Qml applications is not working in emulator using meego sdk 1.1      winId and WinIdChange ››

You must log in to post a reply. Not a member yet? Register here!