1

我正在尝试为 QLineEdit 实现自动完成。

在这里看我的代码:

#ifndef COMPLETER_H
#define COMPLETER_H
#include <QCompleter>
#include <QString>
#include <QStringList>
#include <QLineEdit>

class Completer:public QCompleter
{
Q_OBJECT
public:
    explicit Completer(QStringList stringList, QObject *parent=0);
    virtual QString pathFromIndex(const QModelIndex &index)const;
    virtual QStringList splitPath(const QString&)const;

public slots:
    void onLineEditTextChanged() const;
private:
    mutable int cursorPos_;
};


class ExpressionLineEdit: public QLineEdit
{
    Q_OBJECT
    public:
        explicit ExpressionLineEdit(QWidget *parent=0);
    private:
        QStringList stringList;
        Completer *completer_;
};
#endif // COMPLETER_H





#include <completer.h>
#include <QDebug>
Completer::Completer(QStringList stringList, QObject *parent)
    : QCompleter(stringList,parent)
    , cursorPos_(-1)
{

}

ExpressionLineEdit::ExpressionLineEdit(QWidget* parent)
    : QLineEdit(parent)
{
    stringList << "minRoute" << "minPitch" << "minSpacing";
    completer_ = new Completer(stringList, this);
    setCompleter(completer_);

    QObject::connect(this, SIGNAL(textChanged(const QString&)),
            completer_, SLOT(onLineEditTextChanged()));

    QObject::connect(this, SIGNAL(cursorPositionChanged(int, int)),
            completer_, SLOT(onLineEditTextChanged()));
}

QString Completer::pathFromIndex(const QModelIndex &index) const
{
    QString newStr = index.data(Qt::EditRole).toString();
    ExpressionLineEdit *lineEdit = qobject_cast<ExpressionLineEdit*>(parent());
    QString str = lineEdit->text();
    int prevSpacePos = str.mid(0, lineEdit->cursorPosition()).lastIndexOf(' ');

    int curPos = lineEdit->cursorPosition();
    int nextSpacePos = str.indexOf(' ', curPos);
    if (nextSpacePos == -1) {
        nextSpacePos = str.size();
    }

    QString part1 = str.mid(0, prevSpacePos + 1);
    QString pre = str.mid(prevSpacePos + 1, curPos - prevSpacePos - 1);
    QString post = str.mid(curPos, nextSpacePos - curPos);
    QString part2 = str.mid(nextSpacePos);

    onLineEditTextChanged();
    cursorPos_ = curPos + newStr.size() - pre.size();
    return part1 + newStr + part2;
}

void Completer::onLineEditTextChanged() const
{
    qDebug() << "Completer::onLineEditTextChanged()" << cursorPos_;
    if (cursorPos_ != -1) {
        ExpressionLineEdit *lineEdit = qobject_cast<ExpressionLineEdit*>(parent());
        lineEdit->setCursorPosition(cursorPos_);
        cursorPos_ = -1;
    }
}

QStringList Completer::splitPath(const QString &path) const
{
    cursorPos_ = -1;
    ExpressionLineEdit *lineEdit = qobject_cast<ExpressionLineEdit*>(parent());
    QString text = lineEdit->text();
    QStringList stringList;
    QString str;

    int index = text.mid(0,lineEdit->cursorPosition()).lastIndexOf(' ');
    str = text.mid(index, lineEdit->cursorPosition()-index);
    str.trimmed();
    str.replace(" ", "");
    stringList << str;
    onLineEditTextChanged();
    return stringList;
}

#include <completer.h>
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ExpressionLineEdit le;
    le.show();

    return a.exec();
}

对于此代码,ExpressionLineEdit 和 Completer 可以正常工作(如预期的那样)。

但是当我尝试将 QTreeView 和 QSyledItemDelegate 设置为时,行为发生了变化。我试图重新实现QSyledItemDelegate的eventFilter函数,但它不说话。我尝试将 ExpressionLineEdit 设置为其他 QWidget 并将 QWidget 设置为 QTreeView (因为 QSyledItemDelegate 不能直接与 ExpressionLineEdit 一起使用),但它再次没有帮助。

这是带有 QTreeView 和 QSyledItemDelegate 的代码。

  #include <QTreeView>
  #include <QVBoxLayout>
  #include <QStandardItemModel>
  #include <QStyledItemDelegate>
  #include <Completer.h>
  class QEvent;
  class Delegate:public QStyledItemDelegate
  {
    public:
      Delegate(QObject* parent = 0)
        :QStyledItemDelegate(parent){}
      bool eventFilter(QObject* editor,QEvent* event){return false;}
  virtual bool  editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex& index){return false;}
      QWidget* createEditor(QWidget* parent,const QStyleOptionViewItem &option,const QModelindex &index) const
      {
        if(index.column() != 1) return 0;

        QWidget* w = new QWidget(parent);
        ExpressionLineEdit *le = new ExpressionLineEdit(w);
        QVBoxLayout* lay = new QVBoxLayout(w);
        lay->setContentsMargins(0, 0, 0, 0);
        lay->addWidget(le);
        w->setLayout(lay);
        return w;
      }

  };
  class Tree:public QTreeView
  {
    public:
      Tree(QWidget* parent = 0)
        :QTreeView(parent)
      {
        QStandardItemModel *model = new QStandardItemModel(this);
        model->setRowCount(1);
        model->setColumnCount(2);
        QStandardItem *item = new QStandardItem("Item");
        model->setItem(0,0,item);
        setModel(model);
        Delegate *d = new Delegate(this);
        setItemDelegate(d);
      }
      void keyPressEvent ( QKeyEvent * event ){}
  };

  #include <QApplication>
  #include <Completer.h>
  #include <Tree.h>
  int main(int argc, char ** argv)
   {
     QApplication app(argc,argv);
     Tree t;
     t.show();
    return app.exec();
  }

请帮助理解为什么相同的代码在这两种情况下的工作方式不同。请帮助修复 Completer 的行为。

4

0 回答 0