首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >QPushButton使用QStyledItemDelegate时油漆方法面临的问题

QPushButton使用QStyledItemDelegate时油漆方法面临的问题
EN

Stack Overflow用户
提问于 2022-09-22 06:41:18
回答 1查看 194关注 0票数 4

我已经为QTableView中的一个列实现了QSortFilterProxyModel,因为我们使用QSortFilterProxyModel来筛选表视图。我将此委托设置为如下所示的一列.

代码语言:javascript
运行
复制
table_->setItemDelegateForColumn(11, new PushButtonDelegate(table_));

PushButtonDelegate是从QStyledItemDelegate派生的,我重写了createEditor, setEditorData, setModelData, updateEditorGeometry, and paint方法,如下所示.

代码语言:javascript
运行
复制
PushButtonDelegate::PushButtonDelegate(QObject* parent) :QStyledItemDelegate(parent)
{
    if (const auto table_view = qobject_cast<QTableView*>(parent))
    {
        my_widget_ = table_view;
        btn_ = new QPushButton(button_text_, my_widget_);
        btn_->hide();
        //my_widget_->setMouseTracking(true);
        connect(my_widget_, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(CellEntered(QModelIndex)));
        is_one_cell_in_edit_mode_ = false;
    }
}
QWidget* PushButtonDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        const auto btn = new QPushButton(parent);
        const auto value = index.data().toString();
        btn->setCheckable(true);
        btn->setChecked(value == "Yes" ? true : false);
        btn->setFocusPolicy(Qt::NoFocus);
        connect(btn, SIGNAL(clicked(bool)), this, SLOT(UpdateUseButton(bool)));

        return btn;
    }
    else
    {
        return QStyledItemDelegate::createEditor(parent, option, index);
    }
}

void PushButtonDelegate::UpdateUseButton(bool checked) const
{
    if (const auto selection_button = dynamic_cast<QPushButton*>(sender()))
    {
        const QString value = selection_button->text();
        selection_button->setText(value == "Yes" ? "No" : "Yes");
        selection_button->setChecked(value == "Yes" ? false : true);
        selection_button->setCheckable(true);
    }
}

void PushButtonDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        const auto value = index.model()->data(index, Qt::EditRole).toString();
        const auto pb = dynamic_cast<QPushButton*>(editor);
        pb->setChecked(value == "Yes" ? true : false);
        pb->setText(value);
        pb->setCheckable(true);
    }
    else
    {
        QStyledItemDelegate::setEditorData(editor, index);
    }
}

void PushButtonDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        const auto pb = dynamic_cast<QPushButton*>(editor);
        const auto value = pb->text();
        pb->setChecked(value == "Yes" ? true : false);
        pb->setCheckable(true);
        const auto ptr = dynamic_cast<QSortFilterProxyModel*>(model);
        ptr->setData(index, value, Qt::EditRole);
    }
    else
    {
        QStyledItemDelegate::setModelData(editor, model, index);
    }
}

void PushButtonDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        painter->save();
        btn_->setGeometry(option.rect);
        const auto value = index.data().toString();
        btn_->setCheckable(true);
        btn_->setText(value);
        btn_->setChecked(value == "Yes" ? true : false);

        if (value == "Yes")
            painter->fillRect(option.rect, option.palette.highlight());
        else
            painter->fillRect(option.rect, option.palette.shadow());

        const QPixmap map = btn_->grab();
        painter->drawPixmap(option.rect.x(), option.rect.y(), map);

        painter->restore();
    }
    else
    {
        QStyledItemDelegate::paint(painter, option, index);
    }
}

void PushButtonDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    editor->setGeometry(option.rect);
}

我面临以下问题..。

我必须点击3次按钮才能将文本从“否”更改为“是”。yes)...

  1. 按钮的高亮显示不合适(当文本为时,应该突出显示按钮)。

需要帮助..。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-25 15:08:12

需要单击3次单元格才能更改值的原因是,您需要双击才能编辑(这将创建编辑器),并需要另一次单击才能调用UpdateUseButton。您不需要这样做,您可以在创建编辑器时执行单击。实际上,您甚至不需要UpdateUseButton,因为您可以在setModelData中进行必要的更改。将下面的插槽添加到PushButtonDelegate

代码语言:javascript
运行
复制
void commitAndCloseEditor();

然后像这样实现这个类:

代码语言:javascript
运行
复制
QWidget* PushButtonDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        const auto btn = new QPushButton(parent);
        const auto value = index.data().toString();
        btn->setCheckable(true);
        btn->setChecked(value == "Yes" ? true : false);
        btn->setFocusPolicy(Qt::NoFocus);
        
        // You don't need this, you can update your data in setModelData instead
        // connect(btn, SIGNAL(clicked(bool)), this, SLOT(UpdateUseButton(bool)));
        
        // the click will commit the data and close the editor
        // we connect it with a queued connection so that the slot is called after this function exits
        connect(btn, &QPushButton::clicked, this, &PushButtonDelegate::commitAndCloseEditor, Qt::QueuedConnection);
        emit btn->clicked(false); // perform a click programatically to that the commitAndCloseEditor will be called after we exit this function 
        return btn;
    }
    else
    {
        return QStyledItemDelegate::createEditor(parent, option, index);
    }
}

void PushButtonDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        //nothing to do when you are in your delegate column
    }
    else
    {
        QStyledItemDelegate::setEditorData(editor, index);
    }
}

void PushButtonDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        // set your model data here
        model->setData(index, (index.data().toString() == "Yes") ? "No" : "Yes");
    }
    else
    {
        QStyledItemDelegate::setModelData(editor, model, index);
    }
}

void PushButtonDelegate::commitAndCloseEditor()
{
    auto* editor = qobject_cast<QWidget*>(sender());
    emit commitData(editor);
    emit closeEditor(editor);
}

注意,我使用了一个Qt::QueuedConnnection来连接clicked信号。这确保commitAndCloseEditor槽在createEditorsetEditorData退出后被调用(在每个函数的开头使用print语句很容易检查)。如果您删除了排队连接,那么commitAndCloseEditor将在createEditor返回实际编辑器之前被调用,因此,由于编辑器尚未打开,插槽将什么也不做。

现在对于paint方法..。似乎btn_->setChecked是没有在按钮中正确显示背景色的原因。我不知道为什么会这样,但解决办法是使用样式表,如下所示:

代码语言:javascript
运行
复制
void PushButtonDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    if (index.model()->headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString() == constants::kUse)
    {
        painter->save();
        btn_->setGeometry(option.rect);
        const auto value = index.data().toString();
        
        btn_->setText(value);
        
        QString stylesheet = QString("background-color: %1").arg((value == "Yes") ? "green" : "red"  );
        btn_->setStyleSheet(stylesheet);

        const QPixmap map = btn_->grab();
        painter->drawPixmap(option.rect.x(), option.rect.y(), map);

        painter->restore();
    }
    else
    {
        QStyledItemDelegate::paint(painter, option, index);
    }
}

现在,通过双击来切换该值,结果(在我的Windows框上)如下所示:

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73810341

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档