QCombobox не использует пользовательский делегат для отображения текущего элемента

Я использую собственный делегат для рендеринга форматированного текста в QComboBox. Он используется, чтобы позволить пользователям выбирать цвет для отображения переменной на графике. Это работает для элементов в раскрывающемся меню, но не для выбранного элемента. Любая помощь будет оценена по достоинству.

Вот код делегата, который я использую:

class CustomDelegate : public QStyledItemDelegate
{
public:
    CustomDelegate();
protected:
    void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
    QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};

void CustomDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const{
QStyleOptionViewItemV4 optionV4 = option;
    initStyleOption(&optionV4, index);

    QStyle *style = optionV4.widget? optionV4.widget->style() : QApplication::style();

    QTextDocument doc;
    doc.setHtml(optionV4.text);

    /// Painting item without text
    optionV4.text = QString();
    style->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter);

    QAbstractTextDocumentLayout::PaintContext ctx;

    // Highlighting text if item is selected
    if (optionV4.state & QStyle::State_Selected)
        ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));

    QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
    painter->save();
    painter->translate(textRect.topLeft());
    painter->setClipRect(textRect.translated(-textRect.topLeft()));
    doc.documentLayout()->draw(painter, ctx);
    painter->restore();
}

QSize CustomDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const{
QStyleOptionViewItemV4 optionV4 = option;
initStyleOption(&optionV4, index);

QTextDocument doc;
doc.setHtml(optionV4.text);
doc.setTextWidth(optionV4.rect.width());
return QSize(doc.idealWidth(), doc.size().height());
}

Я установил параметры и делегировал для поля со списком, используя аналогичный код, я удалил некоторые параметры, чтобы уменьшить размер кода:

ui->SelectColor->clear();
    ui->SelectColor->addItem("Select Color");
    ui->SelectColor->addItem("<font color='blue'>Blue</font>");
    ui->SelectColor->addItem("<font color='darkBlue'>Dark Blue</font>");
    ui->SelectColor->addItem("<font color='red'>Red</font>");
    ui->SelectColor->addItem("Dark Yellow");
    ui->SelectColor->addItem("<font color='magenta'>Dark Magenta</font>");
    ui->SelectColor->addItem("White");
    ui->SelectColor->setItemDelegate(new CustomDelegate);

Некоторые параметры являются просто именами, потому что они не очень хорошо выглядят при рендеринге.

Изображение, показывающее раскрывающийся список рендеринга поля со списком, но не текущее


person Thomas    schedule 29.04.2019    source источник


Ответы (1)


Ваш делегат элемента в пользовательском стиле применяется к элементам, которые являются частью QComboBox (т.е. во всплывающем окне QComboBox), а не для текущего элемента, который представлен. Самый простой способ добиться того, чего вы хотите, — ввести собственный класс, наследующий QComboBox, а затем переопределить void QWidget::paintEvent(QPaintEvent *event) путем применения изменений, которые вы хотели бы внести, например установить цветной текст. Другой способ (на случай, если вы не можете ввести другой класс, наследующий QComboBox по какой-либо причине ) будет введение фильтра событий, который что-то сразу после QPaintEvent. Однако использование фильтров событий может оказаться сложным, и я бы посоветовал вам просто ввести какой-нибудь другой класс, а затем переопределить событие рисования.

Теперь, если вы хотите отобразить текущий элемент так же, как параметр во всплывающем окне со списком, вы можете сделать следующее (код неполный, и вы должны применить его для своих нужд самостоятельно):

virtual void paintEvent(QPaintEvent* e) override
{
    // QComboBox::paintEvent(e); - this will leave just a rectangle in which you can perform your custom drawings.

    // Will make your option colored at least.
    QPainter p(this);

    QTextDocument doc;
    doc.setHtml(this->currentText());
    doc.drawContents(&p, rect());
}

Наконец, стоит отметить, что рисование QComboBox довольно сложно, и вы возможно, все же придется переписать почти все, что Qt уже сделал для вас, чтобы можно было применить другие стили, которые вы, возможно, захотите не потерять. Чтобы сделать это, вы должны заглянуть в исходный код этого класса. Вы можете сделать это в браузере кода от Woboq для C & C++ (QComboBox). Надеюсь, это прояснило для вас проблему, и теперь вы знаете, что делать, чтобы достичь своей цели.

person Vaidotas Strazdas    schedule 30.04.2019