如何为 QTableWidget 添加自动完成

How to add Autocompletion for QTableWidget

我想做的是开始在 table 单元格中输入一些数据,它会显示完成建议,但到目前为止没有成功。

我尝试在单元格中添加 QLineEdit,但有没有办法在不将 QLineEdit 用作 cellWidget 的情况下完成此操作?

编辑:

通过覆盖 QItemDelegate 使其工作 class

Autocomplete_Delegate.h


#include <QItemDelegate>
#include <QModelIndex>
#include <QLineEdit>
#include <QCompleter>

class Autocomplete_Delegate : public QItemDelegate {
public:
    Autocomplete_Delegate(QObject *parent, QStringList model);
    ~Autocomplete_Delegate();
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
    void setEditorData(QWidget *editor, const QModelIndex &index) const override;

private:
    QStringList model;
};

Autocomplete_Delegate..cpp

Autocomplete_Delegate::Autocomplete_Delegate(QObject *parent, QStringList model) : QItemDelegate(parent), model(model) {}

Autocomplete_Delegate::~Autocomplete_Delegate() {
    model.clear();
}

QWidget *Autocomplete_Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
    QWidget *editor = QItemDelegate::createEditor(parent, option, index); //* Create the editor so it looks native to the tablewidget
    QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); //* create a linedit so it behaves like a line edit and cast the editor to line edit
    QCompleter *completer = new QCompleter(model, parent); //* make a completer and pass in the wordlist
    completer->setCaseSensitivity(Qt::CaseInsensitive); //* set the case senstivity
    lineEdit->setCompleter(completer); //* set the completor on line edit
    return lineEdit;
}

void Autocomplete_Delegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
    QString data = index.model()->data(index, Qt::EditRole).toString(); //* get the data from the model -> the cell
    QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
    lineEdit->setText(data); //* set the data in the editor
}

感谢@eyllanesc 的想法。

您可以使用与 QTableWidgetItem 关联的角色,并使用委托创建一个 QCompleter,您的模型将在其中建立和更新。

#include <QtWidgets>

enum CustomRoles{
    ListCompleterRole = Qt::UserRole + 1000
};

class CompletedDelegate: public QStyledItemDelegate{
public:
    using QStyledItemDelegate::QStyledItemDelegate;
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const{
        QWidget* editor = QStyledItemDelegate::createEditor(parent, option, index);
        if(QLineEdit *le = qobject_cast<QLineEdit *>(editor)){
            QStringListModel *model = new QStringListModel(le);
            QCompleter *completer = new QCompleter(le);
            completer->setModel(model);
            le->setCompleter(completer);
        }
        return editor;
    }
    void setEditorData(QWidget *editor, const QModelIndex &index) const{
        QStyledItemDelegate::setEditorData(editor, index);
        if(QLineEdit *le = qobject_cast<QLineEdit *>(editor)){
            if(QCompleter *completer = le->completer()){
                if(QStringListModel *model = qobject_cast<QStringListModel *>(completer->model())){
                    QVariant v = index.data(CustomRoles::ListCompleterRole);
                    if (v.canConvert<QStringList>()){
                        QStringList options = v.value<QStringList>();
                        model->setStringList(options);
                    }
                }
            }
        }
    }
};

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

    QStringList words = {
        "astonishing", 
        "agreement", 
        "appeal", 
        "autonomy", 
        "accompany", 
        "articulate", 
        "article", 
        "amuse", 
        "advertise",
        "admiration"
    };

    QTableWidget w(1, 1);
    CompletedDelegate *delegate = new CompletedDelegate(&w);
    w.setItemDelegate(delegate);

    QTableWidgetItem *item = new QTableWidgetItem;
    item->setData(CustomRoles::ListCompleterRole, words); // update options
    w.setItem(0, 0, item);

    w.show();
    return a.exec();
}