首页 > 解决方案 > 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);

有些选项只是名称,因为它们在渲染时看起来不太好。

显示组合框渲染下拉但不是当前的图像

标签: qtqcombobox

解决方案


您的自定义样式项目委托应用于作为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 for C & C++ (QComboBox) 的代码浏览器中执行此操作。希望这可以为您更清楚地阐明问题,现在您知道如何才能实现目标。


推荐阅读