【Qt編程】自動補全功能,qt編程補全
最近寫了一個查單詞的類似有道詞典的軟體,裡面就有一個自動補全功能(即當你輸入一個字母時,就會出現幾個候選項)。這個自動補全功能十分常見,百度搜尋關鍵詞時就會出現。不過它們這些補全功能都是與你輸入的進行首字匹配,有時也會不方便。例如,如果我輸入一個“好”,如果是首字匹配的話會出現:
如果是句中匹配的話,則是這種情況:
你可以根據自己的要求進行選擇哪一種模式。 Qt中內建QCompleter類來實現上面的自動補全功能,讀者可以在Qt內建的demo中很容易的學會該類的使用。
下面我要講的是自己構造一個比QCompleter更強大的類。有人會說,為什麼有現成的不用,要自己寫一個類呢?因為,我用QCompleter類的時候發現,它只有句首匹配模式(可能是我沒仔細看文檔,不知道可以改變模式),其次,當我的詞庫非常大的時候,有的時候就不會出現下拉自動補全列表,具體原因也不清楚。所以自己寫了一個類,來實現QCompleter類所沒有功能。廢話不多說,直接見代碼(代碼註解比較詳細,就不仔細講解了,widget.ui檔案也不給出了,就是一個空的介面):1、widget.h
#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include<QMouseEvent>namespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); void mousePressEvent(QMouseEvent *event);private: Ui::Widget *ui;signals: void movesignal();};#endif // WIDGET_H
2.completelineedit.h
#ifndef COMPLETELINEEDIT_H#define COMPLETELINEEDIT_H#include <QLineEdit>#include <QStringList>#include<QFile>#include<QTextCodec>#include<QDebug>class QListView;class QStringListModel;class QModelIndex;class CompleteLineEdit : public QLineEdit { Q_OBJECTpublic: CompleteLineEdit(QStringList words, QWidget *parent = 0);public slots: void setCompleter(const QString &text); // 動態顯示自動完成清單 void completeText(const QModelIndex &index); // 點擊自動完成清單中的項,使用此項自動完成輸入的單詞protected: virtual void keyPressEvent(QKeyEvent *e); virtual void focusOutEvent(QFocusEvent *e);private slots: void replyMoveSignal();private: QStringList words; // 整個自動完成清單的單詞 QListView *listView; // 自動完成清單 QStringListModel *model; // 自動完成清單的model};#endif // COMPLETELINEEDIT_H
3.widget.cpp
#include "widget.h"#include "ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this);}Widget::~Widget(){ delete ui;}void Widget::mousePressEvent(QMouseEvent *event){ emit movesignal();}
4.completelineedit.cpp
#include "CompleteLineEdit.h"#include <QKeyEvent>#include <QListView>#include <QStringListModel>#include <QDebug>CompleteLineEdit::CompleteLineEdit(QStringList words, QWidget *parent) : QLineEdit(parent), words(words){ listView = new QListView(this);//用於顯示下拉式清單 model = new QStringListModel(this); listView->setWindowFlags(Qt::ToolTip);//設定下拉式清單的樣式 connect(this, SIGNAL(textChanged(const QString &)), this, SLOT(setCompleter(const QString &))); connect(listView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(completeText(const QModelIndex &)));}void CompleteLineEdit::focusOutEvent(QFocusEvent *e){ // listView->hide();//當輸入行不是焦點時,隱藏自動補全的下拉式清單}void CompleteLineEdit::replyMoveSignal(){ listView->hide();//當輸入行不是焦點時,隱藏自動補全的下拉式清單}void CompleteLineEdit::keyPressEvent(QKeyEvent *e){ if (!listView->isHidden()) { int key = e->key(); int count = listView->model()->rowCount(); QModelIndex currentIndex = listView->currentIndex(); if (Qt::Key_Down == key) { // 按向下方向鍵時 int row = currentIndex.row() + 1; if (row >= count) { row = 0; } QModelIndex index = listView->model()->index(row, 0); listView->setCurrentIndex(index); } else if (Qt::Key_Up == key) { // 按向下方向鍵時 int row = currentIndex.row() - 1; if (row < 0) { row = count - 1; } QModelIndex index = listView->model()->index(row, 0); listView->setCurrentIndex(index); } else if (Qt::Key_Escape == key) { // 按下Esc鍵時隱藏自動完成清單 listView->hide(); } else if (Qt::Key_Enter == key || Qt::Key_Return == key) { // 按下斷行符號鍵時,使用自動完成清單中選中的項,並隱藏自動完成清單 if (currentIndex.isValid()) { QString text = listView->currentIndex().data().toString(); setText(text); } listView->hide(); } else { // 其他情況,隱藏自動完成清單,並使用QLineEdit的鍵盤按下事件 listView->hide(); QLineEdit::keyPressEvent(e); } } else { QLineEdit::keyPressEvent(e); }}void CompleteLineEdit::setCompleter(const QString &text){ if (text.isEmpty())//沒有輸入內容的情況 { listView->hide(); return; } if ((text.length() > 1) && (!listView->isHidden())) { return; } // 如果完整的自動完成清單中的某個單詞包含輸入的文本,則加入要顯示的自動完成清單串中 QStringList sl; foreach(QString word, words) { //填充模式一 if (word.contains(text))//只要包含該輸入內容就顯示,這裡也可以設定大小寫不敏感 { sl << word; } //填充模式二// if(word.indexOf(text,0,Qt::CaseInsensitive)==0)//必需與句首內容相同// sl<<word; } model->setStringList(sl); listView->setModel(model); if (model->rowCount() == 0) { return; } // 設定列表的顯示位置及大小 listView->setMinimumWidth(width()); listView->setMaximumWidth(width()); QPoint p(0, height()); int x = mapToGlobal(p).x(); int y = mapToGlobal(p).y() + 1; listView->move(x, y); listView->show();}void CompleteLineEdit::completeText(const QModelIndex &index){ QString text = index.data().toString(); setText(text); listView->hide();}
5.main.cpp
#include <QApplication>#include "CompleteLineEdit.h"#include"widget.h"int main(int argc, char *argv[]) { QApplication a(argc, argv); QStringList sl; QFile *inFile=new QFile ("input.txt");//這個是你自己的詞庫 if(!inFile->open(QIODevice::ReadOnly|QIODevice::Text)) { qDebug()<<"cannot read!"; } while(!inFile->atEnd()) { QByteArray line = inFile->readLine(); QTextCodec* gbk_codec = QTextCodec::codecForName("GBK"); QString gbk_string = gbk_codec->toUnicode(line); if (!line.isEmpty()) sl << gbk_string.trimmed();//將檔案中的詞彙輸入到sl中 } inFile->close();//關閉檔案 sl<< "你好" << "好的" << "好嗎" << "你的" << "真好啊" << "天真" << "你好嗎"; Widget *w= new Widget(); CompleteLineEdit * edit= new CompleteLineEdit(sl,w); w->show(); // QObject::connect(w,SIGNAL(movesignal()),edit,SLOT(replyMoveSignal())); return a.exec();}
最後放兩張查單詞軟體用到的自動補全功能的:
Qt Creator 代碼自動補全怎設定
嗯嗯 明白了
QT中有的檔案沒有自動補全,比如QString、QFile,但加標頭檔QtGui後,就可以自動補全了,為何?
你的版本可能有問題吧,我試了下,只要包含了QString的標頭檔也會有QString的自動補全。這隻是編輯器的一個功能,會去標頭檔裡搜尋相應的函數並列出來。但常用的函數必須要熟記的。你可以換個QCreator試試。