可自己复用自己改造的ListWidget使用demo
使用的话可以和给外部QLineEdit搭配,接受sigSelectRecord即可
其他类似的均可由这个基础demo改造
头文件.h
//搜索记录工具
class GLEXPORT SearchRecordWidget : public QWidget{
Q_OBJECT
public:
SearchRecordWidget(QWidget* wid = nullptr);
~SearchRecordWidget();
//添加一项
void addItem(QString);
//清空所有item
void clearAllItem();
//获取listwidget行数
int recordCount(){return m_list_widget->count();};
protected:
void mouseMoveEvent(QMouseEvent* event) override;
signals:
//选中某个字符串
void sigSelectItem(QString);
void sigSelectRecord(QString);
private:
void InitUi();
//根据listWidget适配高度
void adjustHeight();
//清除所有item的悬浮状态
void clearAllItemHoverState();
protected:
bool eventFilter(QObject*, QEvent*) override;
void paintEvent(QPaintEvent*) override;
private slots:
private:
QLabel* m_lab_title{nullptr};
QPushButton* m_btn_clear{nullptr};
QListWidget* m_list_widget{nullptr};
//窗体固定宽度
int m_fix_w{173};
//list每项的行高
int m_list_item_h{24};
//除listwidegt以上的高度
int m_top_height {32};
};
class QHBoxLayout;
class SearchRecordItemWidget : public QWidget {
Q_OBJECT
public:
SearchRecordItemWidget(QString, QWidget* parent = nullptr);
~SearchRecordItemWidget();
//设置悬浮状态
void setHoverState(bool);
QString getRecordText(){return m_text;};
private:
void InitUi();
protected:
virtual void enterEvent(QEvent* event);
virtual void leaveEvent(QEvent* event);
virtual void mouseReleaseEvent(QMouseEvent* event);
signals:
void sigDeleteItem();
void sigSelectRecord(QString);
private:
QWidget* m_wid_main {nullptr};
QLabel* m_lab_text{nullptr};
QString m_text{""};
QPushButton* m_btn_clear{nullptr};
//水平布局,放入类全局便于控制按钮的加入
QHBoxLayout*m_hor_layout{nullptr};
};
实现文件.cpp
SearchRecordWidget::SearchRecordWidget(QWidget* wid) : QWidget(wid){
InitUi();
}
SearchRecordWidget::~SearchRecordWidget() {}
void SearchRecordWidget::addItem(QString str) {
int count = m_list_widget->count();
//大于8个删除最后一行
if (count >= 8) {
m_list_widget->takeItem(count - 1);
}
//插入Item
QListWidgetItem* item = new QListWidgetItem(NULL);
m_list_widget->insertItem(0, item);
//生成ItemWidget
SearchRecordItemWidget* formatWidget =
new SearchRecordItemWidget(str, this);
formatWidget->setFocusPolicy(Qt::NoFocus);
//给Item设置和ItemWidget一样的大小
QSize formatSize = QSize(m_list_widget->width(), m_list_item_h);
item->setSizeHint(formatSize);
m_list_widget->setItemWidget(item, formatWidget);
connect(formatWidget, &SearchRecordItemWidget::sigDeleteItem, this,
[this]() {
QObject* obj = sender();
if (obj) {
int need_row = -1;
//找到第几行,删除即可
int count = m_list_widget->count();
for (int i = 0; i < count; i++) {
auto cur_item = this->m_list_widget->item(i);
QWidget* cur_wid = m_list_widget->itemWidget(cur_item);
if (cur_wid == obj) {
need_row = i;
break;
}
}
if (need_row != -1) {
m_list_widget->takeItem(need_row);
if (m_list_widget->count() == 0) {
//没有行了,关闭本窗体
close();
} else {
//还有行,适配高度
adjustHeight();
}
}
}
});
connect(formatWidget, &SearchRecordItemWidget::sigSelectRecord, this,
[this](QString str) {
emit sigSelectRecord(str);
close();
});
//大小适配
adjustHeight();
}
void SearchRecordWidget::clearAllItem() {
m_list_widget->clear();
adjustHeight();
hide();
}
void SearchRecordWidget::mouseMoveEvent(QMouseEvent* event) {
}
void SearchRecordWidget::InitUi() {
//设置弹窗属性
//无边框+顶层
this->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint |
Qt::WindowStaysOnTopHint);
#ifdef __APPLE__
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
#endif
//大小
this->setFixedSize(m_fix_w, m_top_height);
//this->setFocusPolicy(Qt::NoFocus);
QFont font_10;
font_10.setPixelSize(10);
//最近搜索文字
m_lab_title = new QLabel(this);
m_lab_title->setFixedSize(QSize(40, 14));
m_lab_title->move(14, 9);
m_lab_title->setText(QString::fromUtf8("最近搜索"));
m_lab_title->setFont(font_10);
//清空按钮
m_btn_clear = new QPushButton(this);
m_btn_clear->setFixedSize(25, 15);
m_btn_clear->move(140, 9);
m_btn_clear->setText(QString::fromUtf8("清空"));
m_btn_clear->setFont(font_10);
connect(m_btn_clear, &QPushButton::clicked, [this](bool) {
clearAllItem();
});
//记录列表
m_list_widget = new QListWidget(this);
m_list_widget->move(6, m_top_height);
m_list_widget->setFixedSize(m_fix_w-6-6, 0);
m_list_widget->clear();
m_list_widget->setFocusPolicy(Qt::NoFocus);
m_list_widget->setSpacing(0);
m_list_widget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_list_widget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_list_widget->setMouseTracking(true);
m_list_widget->installEventFilter(this);
this->setMouseTracking(true);
installEventFilter(this);
}
void SearchRecordWidget::paintEvent(QPaintEvent*) {
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
void SearchRecordWidget::adjustHeight() {
int count = m_list_widget->count();
//每项高24
int add_height = count * m_list_item_h;
m_list_widget->setFixedHeight(add_height);
this->setFixedHeight(m_top_height + add_height+5);
}
void SearchRecordWidget::clearAllItemHoverState() {
int count = m_list_widget->count();
for (int i = 0; i < count; i++) {
auto cur_item = this->m_list_widget->item(i);
QWidget* cur_wid = m_list_widget->itemWidget(cur_item);
SearchRecordItemWidget* cur_item_wid = (SearchRecordItemWidget*)cur_wid;
cur_item_wid->setHoverState(false);
}
}
bool SearchRecordWidget::eventFilter(QObject* obj, QEvent* event) {
if (obj == this) {
if (event->type() == QEvent::WindowDeactivate) {
hide();
} else if (event->type() == QEvent::Leave) {
hide();
}
}
if (obj == this->m_list_widget) {
if (event->type() == QEvent::MouseMove) {
//auto item = this->m_list_widget->itemAt(
// this->m_list_widget->viewport()->mapFromGlobal(this->cursor().pos()));
//QWidget* need_wid = m_list_widget->itemWidget(item);
//SearchRecordItemWidget* item_wid = (SearchRecordItemWidget*)need_wid;
//if (item_wid != nullptr) {
// //遍历所有项,除item_wid外所有项都变成不可选择项
// int count = m_list_widget->count();
// for (int i = 0; i < count; i++) {
// auto cur_item = this->m_list_widget->item(i);
// QWidget* cur_wid = m_list_widget->itemWidget(cur_item);
// SearchRecordItemWidget* cur_item_wid =
// (SearchRecordItemWidget*)cur_wid;
// if (cur_item_wid == item_wid) {
// cur_item_wid->setHoverState(true);
// } else {
// cur_item_wid->setHoverState(false);
// }
// }
//}
} else if (event->type() == QEvent::Leave) {
clearAllItemHoverState();
}
}
return false;
}
SearchRecordItemWidget::SearchRecordItemWidget(QString str, QWidget* parent)
: QWidget(parent) {
m_text = str;
InitUi();
setHoverState(false);
}
SearchRecordItemWidget::~SearchRecordItemWidget() {}
void SearchRecordItemWidget::setHoverState(bool is_hover) {
if (is_hover) {
//选择状态
m_btn_clear->show();
m_hor_layout->addWidget(m_btn_clear);
QString style = "border-radius:5px;background-color:";
style+=BFSKIN()->getColor(BFSkinSetting::KUEBtnNormalCancelColor);
style += ";";
m_wid_main->setStyleSheet(style);
} else {
//普通状态
m_hor_layout->removeWidget(m_btn_clear);
m_btn_clear->hide();
m_wid_main->setStyleSheet("background-color:rgba(0,0,0,0);");
}
}
void SearchRecordItemWidget::InitUi() {
//main——widget
QGridLayout* grid_layout = new QGridLayout(this);
grid_layout->setContentsMargins(0,0,0,0);
this->setLayout(grid_layout);
//主窗体
m_wid_main = new QWidget(this);
grid_layout->addWidget(m_wid_main);
//水平layout
m_hor_layout = new QHBoxLayout(m_wid_main);
m_hor_layout->setContentsMargins(8, 0, 6, 0);
m_hor_layout->setSpacing(10);
m_wid_main->setLayout(m_hor_layout);
//项文字
m_lab_text = new QLabel(this);
m_lab_text->setText(m_text);
m_lab_text->setAlignment(Qt::AlignVCenter);
m_hor_layout->addWidget(m_lab_text);
//m_lab_text->setStyleSheet("background-color:rgba(255,0,0,100);");
//清除按钮
m_btn_clear = new QPushButton(this);
m_btn_clear->setFixedSize(12,12);
m_hor_layout->addWidget(m_btn_clear);
connect(m_btn_clear, &QPushButton::clicked, this,
[this](bool) { emit sigDeleteItem(); });
}
void SearchRecordItemWidget::enterEvent(QEvent* event) {
setHoverState(true);
}
void SearchRecordItemWidget::leaveEvent(QEvent* event) {
setHoverState(false);
}
void SearchRecordItemWidget::mouseReleaseEvent(QMouseEvent* event) {
emit sigSelectRecord(m_text);
}