#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QCalendarWidget>
#include <QHBoxLayout>
#include <QSpinBox>
#include <QPushButton>
#include <QLabel>
#include <QDate>
#include <QMessageBox>
#include <QMouseEvent>
#include <QPainter>
#include <QTableView>
#include <QTimer>
#include <QEvent>
enum class CaldrStat{
Init,Click
};
class CPCustomCalendar : public QCalendarWidget {
Q_OBJECT
public:
CPCustomCalendar(QWidget *parent = nullptr)
: QCalendarWidget(parent)
, m_startDate(QDate())
, m_endDate(QDate())
{
setGridVisible(true);
setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
connect(this, &QCalendarWidget::clicked,this,&CPCustomCalendar::handleDateSelection);
}
protected:
void paintCell(QPainter *painter, const QRect &rect, const QDate date) const override {
QCalendarWidget::paintCell(painter, rect, date);
if (!m_startDate.isValid() || !m_endDate.isValid()) return;
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::TextAntialiasing);//文字抗锯齿
auto radius = rect.height() >> 1;
if (date == m_startDate || date == m_endDate) {
painter->setBrush(QColor(0x0155FF));
painter->setPen(Qt::NoPen);
painter->drawRoundedRect(rect, radius, radius);
QRect _rect= date == m_endDate ? rect.adjusted(0, 0, -radius, 0)
: rect.adjusted(radius, 0, 0, 0);
painter->drawRect(_rect);
painter->setPen(Qt::white);
painter->drawText(rect, Qt::AlignCenter, QString::number(date.day()));
}
else if (date > m_startDate && date < m_endDate) {
painter->fillRect(rect, QColor(0xE4F0FF));
painter->setPen(QColor(0x435C86));
painter->drawText(rect, Qt::AlignCenter, QString::number(date.day()));
}
}
private slots:
void handleDateSelection() {
isClicked = !isClicked;
if (isClicked) {
m_startDate = selectedDate();
m_endDate = QDate();
setFocus();
} else{
m_endDate = selectedDate();
clearFocus();
if (m_endDate < m_startDate)
std::swap(m_startDate, m_endDate);
emit rangeChanged(m_startDate, m_endDate);
}
updateCells();
}
signals:
void rangeChanged(const QDate &start, const QDate &end);
private:
QDate m_startDate;
QDate m_endDate;
QTableView *tableView = nullptr;
bool isClicked{false};
CaldrStat stat{CaldrStat::Init};
};
class DateRangePicker : public QWidget {
Q_OBJECT
public:
DateRangePicker(QWidget *parent = nullptr) : QWidget(parent) {
selectedDaysLabel = new QLabel("已选0天", this);
calendar = new CPCustomCalendar(this);
calendar->setMinimumDate(QDate(2023, 1, 1));
calendar->setMaximumDate(QDate(2025, 12, 31));
connect(calendar, &CPCustomCalendar::rangeChanged, this, &DateRangePicker::updateDayCount);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(calendar);
mainLayout->addWidget(selectedDaysLabel);
}
private slots:
void updateDayCount(const QDate &start, const QDate &end) {
if (start.isValid() && end.isValid()) {
int days = start.daysTo(end) + 1;
selectedDaysLabel->setText(QString("已选%1天").arg(days));
} else {
selectedDaysLabel->setText("已选0天");
}
}
private:
CPCustomCalendar *calendar;
QLabel *selectedDaysLabel;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
DateRangePicker picker;
picker.setWindowTitle("日期时间选择控件");
picker.resize(400, 350);
picker.show();
return app.exec();
}
#include "main.moc"