首页 > 其他分享 >自定义的Qt搜索框控件

自定义的Qt搜索框控件

时间:2022-11-23 20:36:27浏览次数:41  
标签:控件 MSearchBar Qt 自定义 lwList void magnifier event painter

该控件模仿的是比较常见的应用程序中的搜索框。实现了输入文本后按回车搜索(也可以点击搜索按钮开始搜索),和记住最近的几个搜索记录的功能。使用者通过响应inputCompleted信号获取输入文本进行操作。使用该控件是相当的简单。只要把下面的代码复制到你的项目中,在设计师软件里加一个QWidget,然后提升为该类即可。该控件在VS2015和Qt5.9上测试通过。下面是效果图:

上代码,头文件:

class MSearchBar : public QWidget
{
    Q_OBJECT

public:
    MSearchBar(QWidget* parent = 0);
    QSize sizeHint() const override;

signals:
    void inputCompleted(const QString& str);

private slots:
    void leTextReturnPressed();

private:
    void addHistory(const QString& str);
    bool eventFilter(QObject *watched, QEvent *event) override;
    void paintEvent(QPaintEvent*) override;
    void resizeEvent(QResizeEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void enterEvent(QEvent *event) override;
    void leaveEvent(QEvent *event) override;
    void showPopup();

    enum Status
    {
        NONE,
        HOVERED,
        PRESSED,
    };

private:
    class MDiyListWidget;
    bool focused;
    bool oddClick;
    Status state;
    QPoint pressPt;
    QRect magnifier;
    QStringList history;
    QLineEdit* leText;
    MDiyListWidget* lwList;
};

class QListWidget;

class MSearchBar::MDiyListWidget : public QWidget
{
    Q_OBJECT

public:
    MDiyListWidget(QWidget* parent = 0);
    void setItems(const QStringList& strs);

signals:
    void textChanged(const QString&);

private slots:
    void lwListItemSelectionChanged();

private:
    QListWidget* lwList;
};

CPP文件:

MSearchBar::MSearchBar(QWidget* parent) :
    QWidget(parent), focused(false), state(NONE)
{
    oddClick = false;
    setMouseTracking(true);

    QHBoxLayout* lay = new QHBoxLayout(this);
    leText = new QLineEdit(this);
    leText->setStyleSheet(u8"QLineEdit { border:none; }");
    leText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    leText->installEventFilter(this);
    lay->addWidget(leText);
    setLayout(lay);
    connect(leText, &QLineEdit::returnPressed, this, &MSearchBar::leTextReturnPressed);
    lwList = new MDiyListWidget(this);
    connect(lwList, &MDiyListWidget::textChanged, leText, &QLineEdit::setText);
}

void MSearchBar::leTextReturnPressed()
{
    QString str = leText->text();
    emit inputCompleted(str);
    addHistory(str);
}

void MSearchBar::addHistory(const QString& str)
{
    if (!str.isEmpty() && !history.contains(str))
    {
        history.append(str);
    }
    if (history.size() > 10)
    {
        history.pop_front();
    }
}

void MSearchBar::resizeEvent(QResizeEvent *event)
{
    QSize sz = event->size();
    layout()->setContentsMargins(1, 1, sz.height() - 1, 1);
    magnifier.setX(sz.width() - sz.height() + 1);
    magnifier.setY(1);
    magnifier.setWidth(sz.height() - 2);
    magnifier.setHeight(sz.height() - 2);
}

void MSearchBar::paintEvent(QPaintEvent*)
{
    QStyleOption opt;
    opt.init(this);
    QPainter painter(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
    QPalette pale = palette();
    painter.setBrush(Qt::NoBrush);
    /* 绘制边框 */
    if (focused)
    {
        painter.setPen(QPen(pale.highlight(), 1));
        painter.drawRect(0, 0, width() - 1, height() - 1);
    }
    else
    {
        painter.setPen(QPen(pale.mid(), 1));
        painter.drawRect(0, 0, width() - 1, height() - 1);
    }
    /* 绘制放大镜 */
    const QPointF ciCenter(0.4, 0.4);
    const qreal ciRadius = 0.2;
    const QPointF liStart(0.6, 0.6);
    const QPointF liEnd(0.83, 0.83);
    painter.setRenderHint(QPainter::Antialiasing);
    switch (state)
    {
    case MSearchBar::NONE:
        painter.translate(magnifier.x(), magnifier.y());
        painter.setPen(QPen(pale.mid(), 2));
        break;
    case MSearchBar::HOVERED:
        painter.fillRect(magnifier, pale.highlight());
        painter.translate(magnifier.x(), magnifier.y());
        painter.setPen(QPen(pale.light(), 2));
        break;
    case MSearchBar::PRESSED:
        painter.fillRect(magnifier, pale.highlight());
        painter.translate(magnifier.x() + 1, magnifier.y() + 1);
        painter.setPen(QPen(pale.light(), 2));
        break;
    default: // never goto this.
        break;
    }
    int msz = magnifier.width();
    painter.drawEllipse(ciCenter * msz, ciRadius * msz, ciRadius * msz);
    painter.drawLine(msz * liStart, msz * liEnd);
}

bool MSearchBar::eventFilter(QObject *watched, QEvent *event)
{
    if (event->type() == QEvent::FocusIn)
    {
        focused = true;
        update();
    }
    else if (event->type() == QEvent::FocusOut)
    {
        focused = false;
        update();
    }
    else if (event->type() == QEvent::MouseMove && state == HOVERED)
    {
        state = NONE;
        update();
    }
    else if (event->type() == QEvent::MouseButtonRelease)
    {
        QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(event);
        if (mouseEvent->button() == Qt::LeftButton)
        {
            oddClick = !oddClick;
            if (!history.empty() && oddClick)
            {
                showPopup();
            }
        }
    }
    return false;
}

void MSearchBar::showPopup()
{
    lwList->setItems(history);
    QPoint scrPos = mapToGlobal(QPoint(0, height()));
    lwList->move(scrPos);
    lwList->setFixedWidth(width());
    lwList->show();
}

void MSearchBar::mouseMoveEvent(QMouseEvent *event)
{
    bool isHover = magnifier.contains(event->pos());
    if (isHover && state != HOVERED)
    {
        state = HOVERED;
        update();
    }
    else if (!isHover && state != NONE)
    {
        state = NONE;
        update();
    }
}

void MSearchBar::mousePressEvent(QMouseEvent *event)
{
    QPoint p = event->pos();
    if (magnifier.contains(p))
    {
        pressPt = p;
        state = PRESSED;
        update();
    }
}

void MSearchBar::mouseReleaseEvent(QMouseEvent *event)
{
    if (pressPt == event->pos())
    {
        state = HOVERED;
        QString str = leText->text();
        emit inputCompleted(str);
        addHistory(str);
        update();
    }
}

void MSearchBar::enterEvent(QEvent *event)
{
    // nothing.
}

void MSearchBar::leaveEvent(QEvent *event)
{
    state = NONE;
    update();
}

QSize MSearchBar::sizeHint() const
{
    return QSize(160, 24);
}

/////////////////////////////////////////////////////////////////////////////////////////

MSearchBar::MDiyListWidget::MDiyListWidget(QWidget* parent) :
    QWidget(parent)
{
    setWindowFlag(Qt::Popup);

    QHBoxLayout* lay = new QHBoxLayout(this);
    lay->setContentsMargins(0, 0, 0, 0);
    lwList = new QListWidget(this);
    lay->addWidget(lwList);
    setLayout(lay);
    connect(lwList, &QListWidget::itemSelectionChanged, this, &MDiyListWidget::lwListItemSelectionChanged);
}

void MSearchBar::MDiyListWidget::setItems(const QStringList& strs)
{
    lwList->clear();
    lwList->addItems(strs);
}

void MSearchBar::MDiyListWidget::lwListItemSelectionChanged()
{
    QList<QListWidgetItem*> selects = lwList->selectedItems();
    if (!selects.empty())
    {
        emit textChanged(selects.first()->text());
        close();
    }
}

 

标签:控件,MSearchBar,Qt,自定义,lwList,void,magnifier,event,painter
From: https://www.cnblogs.com/mengxiangdu/p/16919688.html

相关文章

  • Vue笔记 - 自定义事件与事件总线
    自定义事件与事件总线目录自定义事件与事件总线1.事件1.1基本使用1.2事件修饰符1.3键盘事件2.自定义事件3.全局事件总线1.事件1.1基本使用使用v-on:xxx或......
  • QT图片查看器封装-鼠标中心缩放、移动、截图、框选、切换播放
    Qt图片查看器目录1      简介...12      功能实现...22.1     图片以鼠标为中心放大缩小功能...22.2     图片移动功能...42.3   ......
  • 手动创建线程池+自定义拒绝策略
    try{ThreadFactorytycThreadFactory=newThreadFactoryBuilder().setNamePrefix("tyc-call-inf").build();//拒绝策略,超过线程数+......
  • 自定义异常类以及使用方式
    publicclassAmountOfMoneyMissMatchExceptionextendsRuntimeException{publicAmountOfMoneyMissMatchException(){super();}publicAmoun......
  • Qt5 CMake项目简单模板
    cmake_minimum_required(VERSION3.5)project(testVERSION0.1LANGUAGESCXX)set(CMAKE_INCLUDE_CURRENT_DIRON)set(CMAKE_CXX_STANDARD11)set(CMAKE_CXX_STAN......
  • wpf 后台添加控件
    音乐播放列表,鼠标右键点击列表时,出现添加到歌单,做成每次右键点击时,后台新增选项了(也可以前台绑定数据源每次增删改后更新数据源)TextBlocktext=newTextBlock();text.......
  • wpf 后台修改控件颜色(颜色Brush类型新建)
    16进制、rgb格式、提供的颜色示例:xxx.Foreground=newSolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"));xxx.Background=newSolidColorBrus......
  • 自定义授权过滤器分配权限
    1.在用户登录时候获取用户的角色信息  2.创建一个类,继承Attribute,和IAuthorizationFilter ......
  • 使用 Dockerfile 自定义 Nginx 镜像
    一般来说,自定义Nginx只需要把静态文件放到镜像里就可以了,不需要重写CMD与ENTRYPOINT。但是,如果的确需要在Nginx启动前执行一些操作,就需要重写CMD了,如果写成下边就样......
  • Winform控件绑定数据
    目录简介绑定基类功能扩展简单控件绑定列表控件绑定绑定BindingList集合绑定DataTable表格绑定BindingSource源表格控件绑定绑定DataTable绑定BindingListUI线程全局类简......