实现自定义QDateEdit可删除日期值

1.实现可删除QDeteEdit

在Qt框架中,QDateEdit是一个用于编辑日期的控件,如果想要删除QDateEdit不是特别好做,如果直接获取QDateEdit中的QLineEdti并设置显示删除按钮(代码如下所示),删除按钮会一直显示,效果并不好,所以继承QDateEdit重新定义样式是比较方便。

QLineEdit *lineEdit = pDateEdit->findChild<QLineEdit*>();
lineEdit->setClearButtonEnabled(true);

1.1 源码

头文件:

class customDateEdit :public QDateEdit
{
	Q_OBJECT
public:
	explicit customDateEdit();
	~customDateEdit();

public slots:
	void slot_clearDate();

protected:
	bool eventFilter(QObject *obj, QEvent *event) override;
	void focusOutEvent(QFocusEvent *event) override;
private:
	void init();
	void updateClearBtnPosition(QLineEdit *lineEdit);// 更新清除按钮的位置

private:
	QToolButton *m_pBtnClear = nullptr;
	QLineEdit *m_pLineEdit = nullptr;
};

源文件:


customDateEdit::customDateEdit()
{
	init();
}

customDateEdit::~customDateEdit()
{
}

void customDateEdit::slot_clearDate()
{
	this->setSpecialValueText(" ");
	m_pLineEdit->clear();
}

bool customDateEdit::eventFilter(QObject * obj, QEvent * event)
{
	if (obj == this->findChild<QLineEdit*>()) {
		if (event->type() == QEvent::Resize) {
			QLineEdit *lineEdit = qobject_cast<QLineEdit*>(obj);
			if (lineEdit) {
				updateClearBtnPosition(lineEdit);
			}
		}
		else if (event->type() == QEvent::MouseMove) {
			QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
			QLineEdit *lineEdit = qobject_cast<QLineEdit*>(obj);
			if (lineEdit) {
				// 计算清除按钮的位置
				int clearButtonWidth = m_pBtnClear->sizeHint().width();
				int clearButtonX = lineEdit->width() - clearButtonWidth;
				if (mouseEvent->pos().x() >= clearButtonX) {
					//如果文本框中有内容再显示
					if (lineEdit->text().size() > 0)
					{
						// 显示清除按钮
						m_pBtnClear->show();
					}
				}
				else {
					// 隐藏清除按钮
					m_pBtnClear->hide();
				}
			}
		}
		else if (event->type() == QEvent::Leave) {
			QLineEdit *lineEdit = qobject_cast<QLineEdit*>(obj);
			if (lineEdit) {
				// 隐藏清除按钮
				m_pBtnClear->hide();
			}
		}
	}
	return QDateEdit::eventFilter(obj, event);
}

void customDateEdit::focusOutEvent(QFocusEvent * event)
{
    //以免失去焦点自动setDate
	QDateEdit::focusOutEvent(event);
}

void customDateEdit::init()
{
	// 获取QLineEdit控件
	m_pLineEdit = findChild<QLineEdit*>();
	if (m_pLineEdit)
	{
		//创建自定义删除按钮
		m_pBtnClear = new QToolButton(m_pLineEdit);
		QIcon clearIcon = QApplication::style()->standardIcon(QStyle::SP_LineEditClearButton);
		m_pBtnClear->setIcon(clearIcon);
		m_pBtnClear->setCursor(Qt::ArrowCursor);
		m_pBtnClear->setStyleSheet("QToolButton { border: none; padding: 0px; }");
		m_pBtnClear->hide();
		
		// 连接清除按钮的点击信号到槽函数
		connect(m_pBtnClear, &QToolButton::clicked, this, &CDateEditWithDel::slot_clearDate);

		// 安装事件过滤器
		m_pLineEdit->installEventFilter(this);

		// 更新清除按钮的位置
		updateClearBtnPosition(m_pLineEdit);

		m_pLineEdit->setPlaceholderText(QString::fromLocal8Bit("选择日期"));// 设置提示文本

		//初始化默认清空
		slot_clearDate();
	}
	setFocusPolicy(Qt::NoFocus);//默认失去焦点,防止光标一直跳动

}

void customDateEdit::updateClearBtnPosition(QLineEdit * lineEdit)
{
	int nClearButtonWidth = m_pBtnClear->sizeHint().width();
	m_pBtnClear->setGeometry(lineEdit->width() - nClearButtonWidth, 0, nClearButtonWidth, lineEdit->height());
}

1.2 效果

1.3 存在问题

可使发现一个问题,初始化的时候不能默认设置空值,这会导致每次都需要手动删除,体验很不好。

2 解决初始化时不能默认空值

2.1 解决方法

自定义控件,实现效果。

2.2 源码

头文件:

#ifndef MYDATEEDIT_H
#define MYDATEEDIT_H

#include <QWidget>
#include <QLineEdit>
#include <QToolButton>
#include <QCalendarWidget>
#include <QEvent>
#include <QMouseEvent>
#include <QApplication>
#include <QPoint>
#include <QRect>
#include <QStyle>
#include <QDesktopWidget>

class MyDateEdit : public QLineEdit
{
    Q_OBJECT

public:
    explicit MyDateEdit(QWidget *parent = nullptr);
    ~MyDateEdit();

    QDate date();//获取日期
    QDateTime dateTime();//获取时间

public slots:
    void slot_clickedCalendarBtn();//点击下拉按钮
    void slot_clickedCalendarWgt(const QDate &date);
    void slot_clearDate();

private:
    void init();
    void initConnect();
    void updateClearBtnPosition();//更新清除按钮的位置

protected:
    bool eventFilter(QObject *obj, QEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;

private:
    QToolButton *m_pCalendarBtn = nullptr;//下拉按钮
    QCalendarWidget *m_pCalendarWgt = nullptr;//日历控件
    QToolButton *m_pBtnClear = nullptr;//清除按钮

};

#endif // MYDATEEDIT_H

源文件:

#include "mydateedit.h"

MyDateEdit::MyDateEdit(QWidget *parent) :
    QLineEdit(parent)
{
    init();
    initConnect();
}

MyDateEdit::~MyDateEdit()
{
}

void MyDateEdit::init()
{
    m_pCalendarBtn = new QToolButton(this);
    //设置下拉按钮样式
    m_pCalendarBtn->setStyleSheet("QToolButton { border: none; padding: 0px; }");
    m_pCalendarBtn->setIcon(QIcon(":/downgray.png"));
    m_pCalendarBtn->setCursor(Qt::PointingHandCursor);

    m_pCalendarWgt = new QCalendarWidget(this);
    m_pCalendarWgt->setWindowFlags(Qt::Popup);
    m_pCalendarWgt->installEventFilter(this);

    m_pBtnClear = new QToolButton(this);
    QIcon clearIcon = QApplication::style()->standardIcon(QStyle::SP_LineEditClearButton);
    m_pBtnClear->setIcon(clearIcon);
    m_pBtnClear->setCursor(Qt::ArrowCursor);
    m_pBtnClear->setStyleSheet("QToolButton { border: none; padding: 0px; }");
    m_pBtnClear->hide();
    m_pBtnClear->setCursor(Qt::PointingHandCursor);

    // 安装事件过滤器
    installEventFilter(this);
    // 设置提示文本
    setPlaceholderText(QString::fromLocal8Bit("选择日期"));
    // 更新清除按钮的位置
    updateClearBtnPosition();
    //默认失去焦点
    setFocusPolicy(Qt::NoFocus);
}

void MyDateEdit::initConnect()
{
    connect(m_pCalendarBtn, &QToolButton::clicked, this, &MyDateEdit::slot_clickedCalendarBtn);
    connect(m_pCalendarWgt, &QCalendarWidget::clicked, this, &MyDateEdit::slot_clickedCalendarWgt);
    // 连接清除按钮的点击信号到槽函数
    connect(m_pBtnClear, &QToolButton::clicked, this, &MyDateEdit::slot_clearDate);
}

void MyDateEdit::updateClearBtnPosition()
{
    int nClearBtnWidth = m_pBtnClear->sizeHint().width();
    int nCalendarBtnWidth = m_pCalendarBtn->sizeHint().width();
    m_pBtnClear->move(this->width() - nCalendarBtnWidth - nClearBtnWidth, 0);
}

bool MyDateEdit::eventFilter(QObject * obj, QEvent * event)
{
    if (obj == this)
    {
        if (event->type() == QEvent::MouseMove && !text().isEmpty())
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            // 计算清除按钮的位置
            int clearButtonWidth = m_pBtnClear->sizeHint().width();
            int clearButtonX = this->width() - clearButtonWidth - m_pCalendarBtn->sizeHint().width();
            // 显示清除按钮
            m_pBtnClear->show();
            updateClearBtnPosition();
        }
        else if (event->type() == QEvent::Leave)
        {
            // 隐藏清除按钮
            m_pBtnClear->hide();
        }
    }

    if (obj == m_pCalendarWgt && event->type() == QEvent::Hide)
    {
        m_pCalendarBtn->setDown(false);
    }
    return QLineEdit::eventFilter(obj, event);
}

void MyDateEdit::resizeEvent(QResizeEvent * event)
{
    QLineEdit::resizeEvent(event);
    QSize buttonSize = m_pCalendarBtn->sizeHint();
    m_pCalendarBtn->setGeometry(rect().right() - buttonSize.width() - 2, (rect().bottom() + 2 - buttonSize.height()) / 2, buttonSize.width(), buttonSize.height());
}

void MyDateEdit::slot_clickedCalendarBtn()
{
    QPoint buttonPos = m_pCalendarBtn->mapToGlobal(QPoint(0, m_pCalendarBtn->height()));
    QRect availableGeometry =QApplication::desktop()->availableGeometry(this);
    QSize calendarSize = m_pCalendarWgt->sizeHint();

    if (buttonPos.x() + calendarSize.width() > availableGeometry.right())
    {
        buttonPos.setX(availableGeometry.right() - calendarSize.width());
    }
    if (buttonPos.y() + calendarSize.height() > availableGeometry.bottom())
    {
        buttonPos.setY(buttonPos.y() - m_pCalendarBtn->height() - calendarSize.height());
    }

    m_pCalendarWgt->setGeometry(QRect(buttonPos, calendarSize));
    m_pCalendarWgt->show();
}


void MyDateEdit::slot_clickedCalendarWgt(const QDate &date)
{
    setText(date.toString("yyyy/MM/dd"));
    m_pCalendarWgt->hide();
}

void MyDateEdit::slot_clearDate()
{
    this->clear();
}

QDate MyDateEdit::date()
{
    return QDate(QDate::fromString(text(), "yyyy/MM/dd"));
}

QDateTime MyDateEdit::dateTime()
{
    return QDateTime(QDateTime::fromString(text(), "yyyy/MM/dd"));
}

2.3 效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值