views:

1876

answers:

4

QCombobox set Item delegate not painting for current Item..

I am trying to create a combo box showing different line types (Solid, Dotted, Dash etc). Currently i am setting item delegate for its content so as to draw/paint line type instead of displaying names. All line types are drawing currectly but as soon as i am selecting any line type from the combobox, the current index of combo box is displaying just the line name and not painting it. How can i make it paint the selected line type on the current combo box index?

A: 

I think I've encountered this problem before, having a delegate that displays the line correctly in the drop-down menu but not in the combo box itself.

The documentation (http://doc.trolltech.com/4.4/qcombobox.html) states that:

"For the text and icon in the combobox label, the data in the model that has the Qt::DisplayRole and Qt::DecorationRole is used."

I suspect that an approach which involves a model that returns suitable data for the DecorationRole might work, but it could be problematic to get it to behave just the way you want it to.

David Boddie
A: 

You can also save your images to icons and use QComboBox::setIconSize() to avoid scaling.

Luper Rouch
A: 

Just override paintEvent. Here is some sketch code:

void PenComboBox::paintEvent( QPaintEvent* pEvent)
{
  QComboBox::paintEvent( pEvent);
  QVariant itemData = this->itemData( this->currentIndex(), Qt::DisplayRole);
  if( !itemData.isNull() && qVariantCanConvert<QPen>( itemData))
  {
    QPainter painter(this);
    // .. etc
  }
}
Cătălin Pitiș
+1  A: 

Delegate to paint items in combo popup:

class LineStyleDelegate(QtGui.QItemDelegate):

    def __init__(self, object, parent = None):
        QtGui.QItemDelegate.__init__(self, parent)

    def paint(self, painter, option, index):
        data = index.model().data(index, QtCore.Qt.UserRole)
        if data.isValid() and data.toPyObject() is not None:
            data = data.toPyObject()
            painter.save()

            rect = option.rect
            rect.adjust(+5, 0, -5, 0)

            pen = QtGui.QPen()
            pen.setColor(QtCore.Qt.black)
            pen.setWidth(3)
            pen.setStyle(data)
            painter.setPen(pen)

            middle = (rect.bottom() + rect.top()) / 2

            painter.drawLine(rect.left(), middle, rect.right(), middle)
            painter.restore()

        else:
            QtGui.QItemDelegate.paint(self, painter, option, index)

        painter.drawLine(rect.left(), middle, rect.right(), middle)
        painter.restore()

    else:
        QtGui.QItemDelegate.paint(self, painter, option, index)

paintEvent to paint current item in combo. You can, of course, paint it manually, but there is the simple way to draw combo box control itself (if you want an arrowbutton or smth in the current):

def paintEvent(self, e):
    data = self.itemData(self.currentIndex(), QtCore.Qt.UserRole)
    if data.isValid() and data.toPyObject() is not None:
        data = data.toPyObject()
        p = QtGui.QStylePainter(self)
        p.setPen(self.palette().color(QtGui.QPalette.Text))

        opt = QtGui.QStyleOptionComboBox()
        self.initStyleOption(opt)
        p.drawComplexControl(QtGui.QStyle.CC_ComboBox, opt)

        painter = QtGui.QPainter(self)
        painter.save()

        rect = p.style().subElementRect(QtGui.QStyle.SE_ComboBoxFocusRect, opt, self)
        rect.adjust(+5, 0, -5, 0)

        pen = QtGui.QPen()
        pen.setColor(QtCore.Qt.black)
        pen.setWidth(3)
        pen.setStyle(data)
        painter.setPen(pen)

        middle = (rect.bottom() + rect.top()) / 2

        painter.drawLine(rect.left(), middle, rect.right(), middle)
        painter.restore()

    else:
        QtGui.QComboBox.paintEvent(self, e)
Max