【问题标题】:QStyledItemDelegate partially select text of default QLineEdit editorQStyledItemDelegate 部分选择默认 QLineEdit 编辑器的文本
【发布时间】:2016-09-23 18:38:01
【问题描述】:

我有一个QStyledItemDelegate 的子类,目前它没有重新实现任何功能(为简单起见)。

使用默认的QStyledItemDelegate 实现,当用户开始编辑QTableView 中的文本时,代理会使用模型中的文本绘制QLineEdit,并选择所有文本(突出显示所有文本以进行编辑)。

文本代表文件名,例如“document.pdf”。允许用户编辑整个文本,但是,我只想首先突出显示基本名称部分(“文档”)而不是后缀(“pdf”)。我怎样才能做到这一点? (我不需要这样做的逻辑,我需要知道如何让QStyledItemDelegate 突出显示部分文本)

我试过了:

请提供帮助,并在此先感谢您。非常感谢您选择文本的前 3 个字符的代码 sn-p。

【问题讨论】:

  • 当角色为Qt::EditRole 时,您可以让模型返回不带扩展名的文件名。但这样一来,用户将无法更改扩展名。
  • 如果您希望扩展是可编辑的,您不需要绘制选择,您需要在行编辑上真正设置选择以排除扩展。您提到的第二种方法对您不起作用。
  • 覆盖setEditorData 并设置您想要的选择应该可以正常工作。但是在Qt source code 中,您可以在setEditorData 之后看到对le->selectAll(); 的调用。不幸的是,这意味着您在setEditorData 中所做的任何选择都会在该呼叫中发生变化。这就是为什么您的第一种方法行不通的原因。
  • @Mike 关于如何选择文本的一部分有什么建议吗?

标签: c++ qt qstyleditemdelegate


【解决方案1】:

正如我对问题的 cmets 所述,子类化 QStyledItemDelegate 并尝试在 setEditorData 中设置任何默认选择的问题如下:

void setEditorData(QWidget* editor, const QModelIndex &index)const{
    QStyledItemDelegate::setEditorData(editor, index);
    if(index.column() == 0){ //the column with file names in it
        //try to cast the default editor to QLineEdit
        QLineEdit* le= qobject_cast<QLineEdit*>(editor);
        if(le){
            //set default selection in the line edit
            int lastDotIndex= le->text().lastIndexOf("."); 
            le->setSelection(0,lastDotIndex);
        }
    }
}

在视图调用我们的setEditorDatahere之后(在Qt代码中),当编辑器小部件是QLineEdit时,它会尝试调用selectAll()here。这意味着我们在setEditorData 中提供的任何选择都会在之后更改。

我能想到的唯一解决方案是以排队的方式提供我们的选择。因此,我们的选择是在执行回到事件循环时设置的。这是工作示例:

#include <QApplication>
#include <QtWidgets>

class FileNameDelegate : public QStyledItemDelegate{
public:
    explicit FileNameDelegate(QObject* parent= nullptr)
        :QStyledItemDelegate(parent){}
    ~FileNameDelegate(){}

    void setEditorData(QWidget* editor, const QModelIndex &index)const{
        QStyledItemDelegate::setEditorData(editor, index);
        //the column with file names in it
        if(index.column() == 0){
            //try to cast the default editor to QLineEdit
            QLineEdit* le= qobject_cast<QLineEdit*>(editor);
            if(le){
                QObject src;
                //the lambda function is executed using a queued connection
                connect(&src, &QObject::destroyed, le, [le](){
                    //set default selection in the line edit
                    int lastDotIndex= le->text().lastIndexOf(".");
                    le->setSelection(0,lastDotIndex);
                }, Qt::QueuedConnection);
            }
        }
    }
};

//Demo program

int main(int argc, char** argv){
    QApplication a(argc, argv);

    QStandardItemModel model;
    QList<QStandardItem*> row;
    QStandardItem item("document.pdf");
    row.append(&item);
    model.appendRow(row);
    FileNameDelegate delegate;
    QTableView tableView;
    tableView.setModel(&model);
    tableView.setItemDelegate(&delegate);
    tableView.show();

    return a.exec();
}

这听起来像是一个 hack,但我决定写这个,直到有人有更好的方法来解决这个问题。

【讨论】:

  • 非常感谢迈克。这可以完美地与您的代码进行非常小的修改以删除行 if(index.column() == 0) 因为我正在编辑列> 0。它看起来确实是一种解决方法,您认为值得提交吗向 Qt 报告错误以提供更好的 API 来访问小部件,以便用户可以完全控制它?非常感谢:)
  • @CSLover ,不客气。这就是我所说的意思,如果你有文件名,你需要将它更改为列:)
  • @CSLover ,我不太确定错误报告。但就个人而言,我认为这真的不值得提交错误报告。他们似乎为QLineEdits 调用了le-&gt;selectAll(),因此覆盖setEditorData 的用户没有义务调用selectAll() 以默认选择其行编辑中的文本。省略该调用可能会导致许多已编写的代码显示QLineEdit,默认情况下没有选择。
  • 很公平。再次感谢,非常感谢。
  • 这可以通过覆盖 QLineEdit 的方法来完成吗?我希望默认情况下不选择文本,但我正在努力制作与您的连接调用等效的 python。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多