1、效果展示

今天这篇文章主要讲解的是自定义搜索框,不仅仅支持搜索,而且可以支持搜索预览,具体请看效果图1。网上也有一些比较简单明了的自定义搜索框,比如Qt之自定义搜索框,讲的也比较详细,不过本文的侧重点不仅仅是搜索,而且包括了检索功能。有兴趣的小伙伴可以看下步骤3的思路讲解。

图1 自定义搜索框

2、功能分析

这个自定义搜索框支持输入一定的数据源,然后通过检索窗口进行搜索数据,匹配到的数据会优先展示到预览下拉框,预览窗口支持hover高亮整行。仔细阅读demo源码的同学可能就会发现其实这个搜搜框的左侧又一个按钮是可以点击的,但是目前还没有添加具体的点击功能。了解了这个控件的功能之后,如果觉得对你有用,那么就可以接着继续往下看实现流程。

3、思路讲解

问题分析:

1、数据源存储在哪儿?怎么实现检索

2、弹出式下拉框显示和隐藏控制?位置同步?

3、鼠标hover状态的颜色设置?

首先在讲解源码之前,我抛出了3个问题,有精力的同学可以先思考下这几个问题,然后在接着往下看,下边我也会逐一说明这个些问题。

源码讲解:

1、使用到的类:

StockSortFilterProxyModel:过滤数据源,该model上的数据索引直接供视图展示
StockTableView:自定义视图,用于显示预览数据
StockListWidget:自定义搜索框
StockItemDelegate:自定义委托,提供自定义绘图

上边4个类是完成自定义搜索框的自定义类,当然除了上述4个类以外,还用到了qt自带的一些类,更好的理解这些类,那么这个自定义控件的思路也就显得异常好理解。

2、头文件说明

  • 委托:负责视图绘制
 class IView;

 struct StockItemDelegatePrivate
{
int column = ;//进度条所在列,下标从0开始
QTableView * parent = nullptr;
IView * view = nullptr;
}; class StockItemDelegate : public QStyledItemDelegate
{
Q_OBJECT public:
StockItemDelegate(QTableView * parent = nullptr);
~StockItemDelegate(){}; public:
void setView(IView * view); protected:
virtual void paint(QPainter * painter
, const QStyleOptionViewItem & option
, const QModelIndex & index) const Q_DECL_OVERRIDE; virtual QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const Q_DECL_OVERRIDE; private:
QScopedPointer<StockItemDelegatePrivate> d_ptr;
};
  • 窗口布局:StockTableView是专门用来展示检索后的数据,StockListWidget是窗口布局
 class IView
{
public:
virtual void SetMouseOver(int) = ;
}; class StockTableView : public QTableView, public IView
{
Q_OBJECT
public:
StockTableView(QStandardItemModel * model, QWidget * parent = ); public:
void SetMouseOver(int); protected:
virtual void mouseMoveEvent(QMouseEvent * event) override;
virtual void leaveEvent(QEvent * event) override;
virtual void mousePressEvent(QMouseEvent * event) override; private:
int currHovered;
void disableMouseOver(); private:
QStandardItemModel * m_pSourceModel;
}; struct StockListWidgetPrivate; class StockListWidget : public QWidget, public QAbstractNativeEventFilter
{
Q_OBJECT public:
StockListWidget(QWidget * parent = nullptr);
~StockListWidget(); public slots:
void NativeParentWindowMove(); protected:
virtual void moveEvent(QMoveEvent * event) override;
virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result) override; private:
void InitializeUI(); private:
QScopedPointer<StockListWidgetPrivate> d_ptr;
};
  • 数据源:根据模式串匹配检索后的数据,并负责通知视图进行更新展示
 class StockSortFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT public:
StockSortFilterProxyModel(QObject *parent = nullptr);
~StockSortFilterProxyModel(); void SetFilterContext(const QString & pattern); protected:
bool lessThan(const QModelIndex &left
, const QModelIndex &right) const;
bool filterAcceptsRow(int source_row
, const QModelIndex & source_parent) const;
private:
size_t sortColumn = ;
};

3、窗口布局:

窗口布局:也就是这个检索框长什么样子,效果展示图1中就可以看到,在这个dmeo中,也就是StockListWidget类,该类使用了一个水平布局添加了按钮和文本输入框。当文本输入框内容发生变化时,启动检索,然后刷新视图上的数据,具体看源码

 connect(d_ptr->m_pSearchLineEdit, &QLineEdit::textChanged, this, [this](const QString & text){
if (d_ptr->m_pFilterModel)
{
d_ptr->m_pFilterModel->SetFilterContext(text);//根据检索内容刷新model
}
if (d_ptr->m_pStockPreviewWidget)
{
d_ptr->m_pStockPreviewWidget->move(d_ptr->m_pTitleWidget->mapToGlobal(QPoint(, d_ptr->m_pTitleWidget->height())));
int rowHeight = d_ptr->m_pStockPreview->rowHeight();
int rowCount = d_ptr->m_pFilterModel->rowCount();
d_ptr->m_pStockPreviewWidget->setFixedHeight(rowHeight * rowCount > DropWidgetMaxHeight ? DropWidgetMaxHeight : rowHeight * rowCount);
d_ptr->m_pStockPreviewWidget->show();//修正view高度,挪动位置并显示
}
});

4、数据存储

qt提供了一些列的model来供我们使用,有可以存放数据的,也有一些只供我们使用接口的,在这个demo中我使用的是QStandardItemModel,他可以存储我们所需要检索的源数据,然后qt还提供了一个检索model,QSortFilterProxyModel,我继承该model可以做自己想做的检索实现,然后把检索到的数据索引通知到视图,这样就完成了数据更新,具体关联代码如下:

     StockItemDelegate * itemDelegate = new StockItemDelegate(d_ptr->m_pStockPreview);
d_ptr->m_pStockPreview->setItemDelegate(itemDelegate);
itemDelegate->setView(d_ptr->m_pStockPreview);//委托关联到视图上,负责数据绘制 d_ptr->m_pStockPreviewWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::Popup); d_ptr->m_pFilterModel->setSourceModel(d_ptr->m_pListModel);//检索model检索的数据源设置
d_ptr->m_pStockPreview->setModel(d_ptr->m_pFilterModel);//视图展示的model为检索后的model

数据检索实现,我匹配的是每一列是否为需要的值,也就是如果这一行中某一列满足要求都认为该行满足要求

 bool StockSortFilterProxyModel::filterAcceptsRow(int source_row
, const QModelIndex & source_parent) const
{
QRegExp regExp = filterRegExp();
bool result = false;
for (int i = ; i < sortColumn; ++i)//循环匹配所有的列,有一列满足要求就返回true
{
QModelIndex index = sourceModel()->index(source_row, i, source_parent);
QString context = sourceModel()->data(index).toString(); if (regExp.isEmpty() == false)
{
QString regExpStr = regExp.pattern();
result = regExp.exactMatch(context);
} if (result)
{
break;
}
} return result;
}

5、视图显示

关于视图显示,主要是视图显示位置和显示时机

显示时机:编辑框内容发现变化的时候显示,编辑框失去焦点的时候隐藏,这样也就存在一个问题,当主窗口拖动时,视图位置更新怎么做?

显示位置:当主窗口位置移动时,更新视图位置,这个方法看一参考qt捕获全局windows消息

6、视图背景色

视图背景色在添加数据源的时候设置了默认背景色,在后hover的时候重新设置背景色,hover失效后再恢复默认背景色,实现行hover代码如下:

 void StockTableView::SetMouseOver(int row)
{
if (row == currHovered)
{
return;
} StockSortFilterProxyModel * sortModel = static_cast<StockSortFilterProxyModel *>(model());
if (sortModel->rowCount() <= row)
{
return;
}
for (int col = ; col < sortModel->columnCount(); col++)//循环遍历,设置指定行中每一个item的背景色
{
QModelIndex index = sortModel->index(row, col);
if (index.isValid())
{
if (QStandardItem * item = m_pSourceModel->itemFromIndex(sortModel->mapToSource(index)))
{
item->setBackground(QBrush(QColor(, , )));
}
}
} if (currHovered != -)
{
disableMouseOver();//恢复之前hover的行
}
currHovered = row;
}

4、相关文章

5、demo下载链接:

Qt之自定义检索框

如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!! 

 

很重要--转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords
  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。

Qt之自定义检索框的更多相关文章

  1. Qt之自定义搜索框

    简述 关于搜索框,大家都经常接触.例如:浏览器搜索.Windows资源管理器搜索等. 当然,这些对于Qt实现来说毫无压力,只要思路清晰,分分钟搞定. 方案一:调用QLineEdit现有接口 void ...

  2. 【Qt】Qt之自定义搜索框【转】

    简述 关于搜索框,大家都经常接触.例如:浏览器搜索.Windows资源管理器搜索等. 当然,这些对于Qt实现来说毫无压力,只要思路清晰,分分钟搞定. 简述 效果 细节分析 Coding 源码下载 效果 ...

  3. Qt之自定义搜索框——QLineEdit里增加一个Layout,还不影响正常输入文字(好像是一种比较通吃的方法)

    简述 关于搜索框,大家都经常接触.例如:浏览器搜索.Windows资源管理器搜索等. 当然,这些对于Qt实现来说毫无压力,只要思路清晰,分分钟搞定. 方案一:调用QLineEdit现有接口 void ...

  4. Qt 之 自定义提示信息框—迅雷风格(模拟QDialog类的exec()方法) good

    http://blog.csdn.net/goforwardtostep/article/details/53614830

  5. Qt之自定义QLineEdit右键菜单

    一.QLineEdit说明 QLineEdit是单行文本框,不同于QTextEdit,他只能显示一行文本,通常可以用作用户名.密码和搜索框等.它还提供了一些列的信号和槽,方便我们使用,有兴趣的小伙伴可 ...

  6. Qt之等待提示框(QPropertyAnimation)

    简述 之前分享过QLabel可以通过QMovie播放gif图片,可以实现等待提示框,今天主要使用动画QPropertyAnimation来进行实现! 数据加载的时候,往往都需要后台线程进行数据请求,而 ...

  7. Qt之自定义托盘(二)

    上一篇文章讲述了自定义Qt托盘,不过不是使用QSystemTrayIcon这个类,而是我们自己完全自定义的一个类,我们只需要处理这个类的鼠标hover.鼠标左键点击.鼠标右键点击和鼠标左键双击,就可以 ...

  8. 在ASP.NET中引用自定义提示框

    在html网页中自定义提示框 正文: 在一般的B/S架构中项目,与用户的交互信息是非常重要的.在一般的情况下,设计人员都在把用户信息呈现在html中,用div和span去弹出相关信息.对于一般的情况而 ...

  9. Qt之等待提示框(QMovie)

    简述 关于gif的使用在实际项目中我用的并不多,因为我感觉瑕疵挺多的,很多时候锯齿比较严重,当然与图存在很大的关系. 关于生成gif的方法可以提供一个网站preloaders,基本是可以满足需求的. ...

随机推荐

  1. Android Studio升级到3.4遇到的问题总结

    1.gradle需要升级. 1).project的build.gradle文件写下如下代码: buildscript { repositories { google() jcenter() } dep ...

  2. 2018-4-5-cadence skill

    skill 是 Cadence 提供的二次开发语言,可以做很多有用的二次开发. 开发参考手册:<algroskill><sklangref><sklanguser> ...

  3. NOIP2017 国庆郑州集训知识梳理汇总

    第一天 基础算法&&数学 day1难度测试 如果要用一个词来形容上午的测试,那真是体无完肤.  成绩: 题目 成绩 评价 T1 50 一般 T2 10 大失所望 T3 0 差 基础算法 ...

  4. linux去除\r(window中编辑的文本)

    vim -b file 二进制贷款文件:%s/^M//g         # 注意这里使用Ctrl+V+M输入^M 上面的方法我就不行,但是下面的可以: 如果不行可以使用 :%s/\r//

  5. webServices 使用GET请求接口方法

    webServices  若要使用GET请求接口方法在Web.config 下添加这段 <webServices>     <protocols>       <add  ...

  6. vue基于webpack说明

    1.文件build里的check-versions.js:检查node和npm版本, 此文件里的 (1)require('chalk')引入一个模块,定义输入终端样式 (2) require('sem ...

  7. Java EE 导图

  8. postgrel执行VACUUM报VACUUM cannot run inside a transaction block

    在python脚本里执行: sql_gp1 = "VACUUM dwd_access_record_inout_temp" sql_gp2 = "delete from ...

  9. windows 10 64位机器上 安装部署

    mi这个博客写的不错 https://www.cnblogs.com/dingguofeng/p/8709476.html 安装redis 可视化工具后 ,新建连接 名称随意,注意端口号是否有误默认6 ...

  10. Javascript——浅谈 Event Flow

    1.Javascript Events : Event Bubbling(事件冒泡) 如果事件从最特定的元素开始,则事件流中的一个阶段称为事件冒泡(DOM中可能最深的节点)然后向上流向最不特定的节点( ...