自定义QCompleter,直接绑定QLineEdit,可默认选中,自动根据内容行数自动缩小高度

news/2024/11/29 5:32:36/

自定义QCompleter,直接绑定QLineEdit,可默认选中,自动根据内容缩小窗口,能设置最高显示行数,自动停靠。里面的duplicatelist是本人的特殊用途,正常情况下是不需要,也就构造函数最后一个参数其实没什么用处。代码是在VS2019+Qt6.5.0下写的

 刚刚学习Qt三个月,不太熟练,代码有很多地方要优化,请大家多多指教

不说废话了,直接上代码

下面这个是头文件

#pragma once

#include <QListView>
#include <QStringListModel>
#include <QLineEdit>
#include <QCompleter>
#include <QEvent>
#include <QKeyEvent>

#include <QApplication>
class QMyCompleterListView : public QListView {
    Q_OBJECT

public:
    QMyCompleterListView(QLineEdit* ledit, QStringList startstrlist = { }, QStringList duplicate = { });
    ~QMyCompleterListView();


    //设置要过滤的字符串
    void setCompleterStringList(QStringList w) { words = w; };

    // 设置要从第几个字符开始显示弹窗,默认是第一位开始显示弹窗
    void setStartbit(unsigned int val = 1) { startbit = val ? val : 1; };
    //返回默认起始位,要从第几个字符开始显示弹窗
    int getStartbit() const { return startbit; };


    //设置是否默认选中第一项
    //************************************
    // 方法:    QMyCompleterListView::setStartHighlight
    // 权限:    public 
    // 返回类型:   void
    // 参数:     bool hightlight
    // 修饰:     
    // 功能:设置是否默认选中第一项
    //************************************
    void setStartHighlight(bool hightlight = true);

    //返回是否默认选中第一项
    //************************************
    // 方法:    QMyCompleterListView::getStartHighlight
    // 权限:    public 
    // 返回类型:   bool
    // 修饰:     const
    // 功能:返回是否默认选中第一项
    //************************************
    bool getStartHighlight() const { return ishightlight; };

    //设置模式,model = PopupCompletion,只显示相匹配的文本,UnfilteredPopupCompletion,匹配显示在前,不匹配移动最后
    //************************************
    // 方法:    QMyCompleterListView::setCompleterMode
    // 权限:    public 
    // 返回类型:   void
    // 参数:     QCompleter::CompletionMode model
    // 修饰:     
    // 功能:设置显示数据的模式,值是PopupCompletion(0)或UnfilteredPopupCompletion(1)
    // PopupCompletion:为只显示匹配字符串;UnfilteredPopupCompletion,显示所有,匹配的在前面。
    //************************************
    void setCompleterMode(QCompleter::CompletionMode  model = QCompleter::PopupCompletion);

    //************************************
    // 方法:    QMyCompleterListView::getCompleterMode
    // 权限:    public 
    // 返回类型:   QCompleter
    // 修饰:     const
    // 功能:返回显示数据的模式,值是PopupCompletion(0)或UnfilteredPopupCompletion(1)
    // PopupCompletion:为只显示匹配字符串;UnfilteredPopupCompletion,显示所有,匹配的在前面。
    //************************************
    QCompleter::CompletionMode getCompleterMode() const { return completermode; };


    //************************************
    // 方法:    QMyCompleterListView::setCaseSensitive
    // 权限:    public 
    // 返回类型:   void
    // 参数:     Qt::CaseSensitivity sensitive
    // 修饰:     
    // 功能: 设置是否区分大小写,值Qt::CaseSensitive或Qt::CaseInsensitive
    //************************************
    void setCaseSensitive(Qt::CaseSensitivity sensitive = Qt::CaseSensitive);

    //************************************
    // 方法:    QMyCompleterListView::getCaseSensitive
    // 权限:    public 
    // 返回类型:   Qt::CaseSensitivity
    // 修饰:     const
    // 功能: 返回是否区分大小写,值Qt::CaseSensitive或Qt::CaseInsensitive
    //************************************
    Qt::CaseSensitivity getCaseSensitive() const { return casesensitive; };


    //************************************
    // 方法:    QMyCompleterListView::getMaxVisibleItems
    // 权限:    public 
    // 返回类型:   int
    // 修饰:     const
    // 功能: 获取最大显示行数
    //************************************
    int getMaxVisibleItems() const { return maxvisibleitems; }

    //************************************
    // 方法:    QMyCompleterListView::setMaxVisibleItems
    // 权限:    public 
    // 返回类型:   void
    // 参数:     int val
    // 修饰:     
    // 功能:设置最大显示行数
    //************************************
    void setMaxVisibleItems(int val = 7) { maxvisibleitems = val; };

    //************************************
    // 方法:    QMyCompleterListView::getFiltermode
    // 权限:    public 
    // 返回类型:   Qt::MatchFlags
    // 修饰:     const
    // 功能:返回过滤模式,值为Qt::MatchContains,任意位置匹配;Qt::MatchStartsWith,只能文本开头匹配
    //************************************
    Qt::MatchFlags getFiltermode() const { return filtermode; }


    //************************************
    // 方法:   QMyCompleterListView::setFilterMode
    // 权限:    public 
    // 返回类型:   void
    // 参数:     Qt::MatchFlags 默认为Qt::MatchStartsWith,只能文本开头匹配
    // 修饰:     
    // 功能:设置过滤模式,值为Qt::MatchContains,任意位置匹配;Qt::MatchStartsWith,只能文本开头匹配
    //************************************
    void setFilterMode(Qt::MatchFlags fiterm = Qt::MatchStartsWith);


    QLineEdit* getLineEdit() const { return lineEdit; }

    /*    void setLineEdit(QLineEdit* val) { lineEdit = val; }*/

        //读取是否显示副本的标志值
    bool getIsduplicatelist() const { return isduplicatelist; }
    //设置是否显示副本的标志值
    void setIsduplicatelist(bool val = false);

    //设置显示副本的标志值
    void setIsduplicatelist(QStringList duplicate);
private:
    QStringList words; // 整个完成列表的单词
    QLineEdit* lineEdit;
    QStringListModel* model; // 完成列表的model
    unsigned int startbit; //此值是设置要从第几个字符开始显示弹出窗
    bool ishightlight;//弹窗是否默认第一项
    Qt::CaseSensitivity casesensitive; //是否区分大小写
    QCompleter::CompletionMode  completermode; //补全模式
    Qt::MatchFlags filtermode; //过滤模式,开始匹配或任意位置匹配
    QStringList duplicatelist; //第二个字符串数组,此数组是副本,往往是为补全字符串的说明,不做为结果
    bool isduplicatelist;//是否副本说明
    unsigned int maxvisibleitems; //显示窗行数
    int x, y;
protected:
    QSize sizeHint() const;
    bool eventFilter(QObject* watched, QEvent* event);

public slots:

    void setCompleter(const QString& text); // 动态的显示完成列表
    void completeText(const QModelIndex& index); // 点击完成列表中的项,使用此项自动完成输入的单词

};
 

cpp文件

#include "QMyCompleterListView.h"

QMyCompleterListView::QMyCompleterListView(QLineEdit* ledit, QStringList startstrlist, QStringList duplicate) : QListView(ledit) {
    lineEdit = ledit;
    model = new QStringListModel();
    if (!startstrlist.isEmpty()) {   
        setCompleterStringList(startstrlist);
    }
    if (!duplicate.isEmpty()) {
        duplicatelist = duplicate;
    }

    setWindowFlags(Qt::ToolTip);

   //设置Fixed模式,可以使listview能显示最小高度

    QSizePolicy policy = sizePolicy();
    policy.setVerticalPolicy(QSizePolicy::Fixed);
    setSizePolicy(policy);

    setEditTriggers(QAbstractItemView::NoEditTriggers);
    //setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setSelectionBehavior(QAbstractItemView::SelectRows);
    setSelectionMode(QAbstractItemView::SingleSelection);
    setFocusPolicy(Qt::NoFocus);
    setFocusProxy(lineEdit);
    lineEdit->installEventFilter(this);

    setMaxVisibleItems();
    setStartbit();
    setStartHighlight();
    setCaseSensitive();
    setCompleterMode();
    setFilterMode();
    setIsduplicatelist();

    connect(lineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setCompleter(const QString&)));
    connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(completeText(const QModelIndex&)));
}

QMyCompleterListView::~QMyCompleterListView() {

}

void QMyCompleterListView::setStartHighlight(bool hightlight /*= true*/) { 

    if (hightlight) {

        QPalette p = palette();
        //QPalette::Inactive 未活动的状态下
        p.setColor(QPalette::Inactive, QPalette::Highlight,
            p.color(QPalette::Active, QPalette::Highlight));
        p.setColor(QPalette::Inactive, QPalette::HighlightedText,
            p.color(QPalette::Active, QPalette::HighlightedText));
        setPalette(p);
        ishightlight = true;
    }
    else {
        QPalette p = palette();
        p.setColor(QPalette::Inactive, QPalette::Highlight,
            p.color(QPalette::Inactive, QPalette::Highlight));
        p.setColor(QPalette::Inactive, QPalette::HighlightedText,
            p.color(QPalette::Inactive, QPalette::HighlightedText));
        setPalette(p);
        ishightlight = false;
    }
}

void QMyCompleterListView::setCompleterMode(QCompleter::CompletionMode model /*= QCompleter::PopupCompletion*/) {
    completermode = model ? QCompleter::UnfilteredPopupCompletion : QCompleter::PopupCompletion;
}

void QMyCompleterListView::setCaseSensitive(Qt::CaseSensitivity sensitive /*= Qt::CaseSensitive*/) {
    casesensitive = sensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
}

void QMyCompleterListView::setFilterMode(Qt::MatchFlags fiterm /*= Qt::MatchStartsWith*/) {
    filtermode = fiterm == Qt::MatchContains ? Qt::MatchContains : Qt::MatchStartsWith;
}

void QMyCompleterListView::setIsduplicatelist(bool val /*= false*/) {

    if (!val || duplicatelist.isEmpty() || words.isEmpty())
        isduplicatelist = false;
    else {
        QStringList lsstr;

        for (int i = 0; i < words.size(); i++) {
            lsstr.append(words.at(i) + " " + duplicatelist.at(i));
        }
        words = lsstr;
        isduplicatelist = true;
    }

}

void QMyCompleterListView::setIsduplicatelist(QStringList duplicate) {
    if (words.isEmpty())
        isduplicatelist = false;
    else {
        duplicatelist = duplicate;
        QStringList lsstr;
        for (int i = 0; i < words.size(); i++) {
            lsstr.append(words.at(i) + " " + duplicatelist.at(i));
        }
        words = lsstr;
        isduplicatelist = true;
    }
}

QSize QMyCompleterListView::sizeHint() const {
    if (model->rowCount() == 0) return QSize(width(), 0);
    int nToShow = maxvisibleitems < model->rowCount() ? maxvisibleitems : model->rowCount();
    return QSize(sizeHintForColumn(0) + 10, nToShow * sizeHintForRow(0) + 10);
}

bool QMyCompleterListView::eventFilter(QObject* watched, QEvent* event) {
    if (watched == lineEdit && !isHidden()) {
        if (event->type() == QEvent::KeyPress) {


            if (words.isEmpty()) {
                return QWidget::eventFilter(watched, event);

            }


            int key = ((QKeyEvent*)event)->key();
            int count = model->rowCount();

            QModelIndex currentIndex = this->currentIndex();

            if (Qt::Key_Down == key) {

                // 按向下方向键时,移动光标选中下一个完成列表中的项

                int row = currentIndex.row() + 1;

                if (row >= count) {

                    row = 0;

                }

                QModelIndex index = model->index(row, 0);

                setCurrentIndex(index);

            }
            else if (Qt::Key_Up == key) {

                // 按向下方向键时,移动光标选中上一个完成列表中的项

                int row = currentIndex.row() - 1;

                if (row < 0) {

                    row = count - 1;

                }

                QModelIndex index = model->index(row, 0);

                setCurrentIndex(index);

            }
            else if (Qt::Key_Escape == key) {

                // 按下Esc键时,隐藏完成列表

                hide();

            }
            else if (Qt::Key_Enter == key || Qt::Key_Return == key) {

                // 按下回车键时,使用完成列表中选中的项,并隐藏完成列表
                if (currentIndex.isValid()) {

                    QString text = this->currentIndex().data().toString();
                    if (isduplicatelist)
                        text = text.left(text.indexOf(" ") + 1);
                    lineEdit->setText(text);
                    hide();
                }
            }
        }
        else if (event->type() == QEvent::Paint) {
                QPoint p(0, lineEdit->height());
                if (lineEdit->mapToGlobal(p).x() != x || lineEdit->mapToGlobal(p).y() != y) {
                    x = lineEdit->mapToGlobal(p).x();
                    y = lineEdit->mapToGlobal(p).y();
                    move(x, y);
                }

        }
        else if (event->type() == QEvent::FocusOut) {
            hide();
        }
    }
    return QWidget::eventFilter(watched, event);
}

void QMyCompleterListView::setCompleter(const QString& text) {

//字节小于初始位、列表为空或没获得焦点不显示QCompliter窗体。
    if (text.size() < startbit || words.isEmpty() || QApplication::focusWidget() != lineEdit) {
        hide();
        return;
    }
    if (isduplicatelist && text.indexOf(" ") == text.size() - 1) {
        QString str = text;
        str.chop(1);
        lineEdit->setText(str);
        return;
    }

    hide();
    QStringList sl;
    QStringList el;


    foreach(QString word, words) {

        if (getFiltermode() == Qt::MatchStartsWith) {
            if (word.startsWith(text, casesensitive)) {
                sl << word;
            }
            else
                el << word;
        }
        else {
            if (word.contains(text, casesensitive)) {
                sl << word;
            }
            else
                el << word;
        }

    }

    if (completermode == QCompleter::UnfilteredPopupCompletion)
        sl << el;

    model->setStringList(sl);
    setModel(model);
    if (model->rowCount() == 0) {
        return;
    }
    setMinimumWidth(lineEdit->width());
    setMaximumWidth(sizeHintForColumn(0) + 10);
    QPoint p(0, lineEdit->height());
    int x = lineEdit->mapToGlobal(p).x();
    int y = lineEdit->mapToGlobal(p).y() + 1;
    move(x, y);
    show();
    if (ishightlight && model->rowCount() > 0) {
        setCurrentIndex(model->index(0, 0));
    }

}
void QMyCompleterListView::completeText(const QModelIndex& index) {

    QString text = index.data().toString();
    if (isduplicatelist)
        text = text.left(text.indexOf(" ") + 1);
    lineEdit->setText(text);
    hide();

}

实现方法也简单

QStringList word_list;
    word_list << "11112   我僮偿" << "11112  大 春偿" << "11113  啊多发点是" << "11114  秦真正的" << "11115  暮云春树地是" << "111在云春树地是" << "1221115  暮大撒反对撒地是" << "11eee15  暮云sdfds地是" << "11ddw  暮云春树地是" << "11asfdasf5  暮云春df sfd是";
    QMyCompleterListView* mycompleter = new QMyCompleterListView(ui->LineEdit, word_list);


http://www.ppmy.cn/news/338378.html

相关文章

紧急求助~~!!!

刚刚学了Java一个学期&#xff0c;刚刚对Java稍稍了解&#xff0c;老师就让我们完成一个课程设计题目。虽然应该可以编出来&#xff0c;但我现在真的没有什么思路&#xff0c;所以&#xff0c;紧急求助高手指点一二&#xff0c;帮帮在下吧&#xff0c;一个星期的时间就得上交了…

erlang练习题

-module(three). -export([]). %% 1、将列表中的integer,float,atom转成字符串并合并成一个字个字符串&#xff1a;[1,a,4.9,“sdfds”] 结果&#xff1a;“1a4.9sdfds” one([])->[]; one([H|T])-> if is_list(H)->Hone(T); true->lists:flatten(io_lib:format(&…

Quartz 单独启动任务调度器案例举例

Quartz 配置文件&#xff0c;如果是基于maven 的项目只需要放置到src/main/resources目录下 #quartz setting File # quartz instance Name org.quartz.scheduler.instanceName MySchedulerVincent# quarts thread pool size 3 ; maximum of 3 jobs can be run simultaneous…

Spring常用注解(收藏大全)

点击上方“程序员大咖”&#xff0c;选择“置顶公众号” 关键时刻&#xff0c;第一时间送达&#xff01; 作者&#xff1a;IT_faquirhttps://blog.csdn.net/IT_faquir/article/details/78025203 程序员大咖整理发布&#xff0c;转载请联系作者获得授权 Spring部分 1.声明bean的…

Java 并发编程之任务取消(五)

停止基于线程的服务 正确的封装原则是&#xff1a;除非拥有某个线程&#xff0c;否则不能对该线程进行操控。例如中断线程或修改线程的优先级等 。那么什么 是拥有某个线程呢&#xff0c;就是创建该线程的类&#xff0c;一般来说线程池是其工作线程的所有者&#xff0c;所以要…

12eqfsdfds

public void aaa(){System.out.println("hello"); }

ces

#include<iostream> using namespace std; int main() { int s,f; cin>>s>>f; if (((s>8) && (s<16))||((s17) && (f00))) { cout<<"YES"; } else { cout<<"NO"; } }

Ubuntu下sqlite3的安装及使用

转载Ubuntu下sqlite3的安装及使用 Sqlite是一款轻型的数据库&#xff0c;实现了多数SQL-92标准&#xff0c;包括事务&#xff08;原子性&#xff0c;一致性&#xff0c;隔离性和持久性 ACID&#xff09;&#xff0c;触发器与多数复杂查询。对于一个移动手持设备的应用开发者&am…