QDateEdit всплывающее окно календаря
Я пытаюсь получить QDateEdit
чтобы позволить QCalendarWidget
показывать при запросе (а не просто при нажатии на стрелку вниз). Например, где-то в моем классе я мог бы сказать:
ui.datepicker.showCalendar()
и это должно загрузить календарь, который появляется прямо ниже выбора даты.
Похоже, мне нужно подкласс QDateEdit
, поскольку это не работает:
QDateEdit *de = new QDateEdit();
de->calendarWidget()->show();
Я также пытался посылать команды клавиатуры, как предписано, когда вы просматриваете исходный код QDateTimeEdit.cpp для Qt, но, кажется, мои сочетания клавиш отключены или что-то в этом роде.
Любые идеи о том, что я должен сделать для подкласса, чтобы заставить это работать? Я думал о чем-то вроде:
class MyDateEdit : QDateEdit
{
Q_OBJECT
protected:
void mouseEvent(QEvent *event) {
this.calendarWidget().show();
}
};
Но, увы, похоже, что он не компилируется или работает неправильно.
3 ответа
Я смог понять это самостоятельно - все еще не уверен, как заставить QDateEdit работать должным образом, но я использовал QLineEdit, и он соответствовал моим потребностям. Просто подключите QCalendarWidget "onClick(QDate)" к слоту, который вы создаете, который делает:
setText(date.toString("M/d/yyyy"));
ui->calendar->hide();
Затем добавьте фильтр событий в QLineEdit, используя событие "OnFocusIn", которое выполняет "ui->calendar->show();" Смотрите: Получить уведомление / событие / сигнал, когда виджет Qt получает фокус
Включить "setCalendarPopup ( bool enable)" в QDateTimeEdit позволяет всплывающий календарь
@Rob S ответ
Вы были правы с подходом фильтра событий, мы сделали бы то же самое с QDateEdit.
Я пишу код, который расширяет ваш подход с QDateEdit:
В mainwindow.h я создал указатель QCalendar (используя QtCreator)
Ниже приведен код mainwindow.cpp (я выдаю полный код, чтобы новички, такие как я, могли получить от него выгоду)
Убедитесь, что для свойства buttonSymbol и calendarpopup установлено значение false, чтобы оно работало правильно
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCalendarWidget>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->dateEdit->setDate(QDate::currentDate());
widget=new QCalendarWidget(); //widget is QCalendar pointer
ui->verticalLayout->addWidget(widget);
widget->setWindowFlags(Qt::Popup); // we need widget to popup
ui->dateEdit->installEventFilter(this);
connect(widget,SIGNAL(clicked(QDate)),ui->dateEdit,SLOT(setDate(QDate)));
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::InputMethodQuery)
{
if (object == ui->dateEdit)
{
if(widget->isVisible()==false && ui->dateEdit->calendarWidget()->isVisible()==false) // this done to avoid conflict
{
qWarning(QString().number(event->type()).toStdString().c_str());
qWarning(object->objectName().toLatin1().data());
widget->move(ui->dateEdit->mapToGlobal(QPoint(0,ui->dateEdit->height())));
widget->show();
}
}
}
return false;
}
ИЛИ:: В качестве альтернативы мы можем использовать QCalendarWidget, предоставляемый dateEdit, хотя это не очень эффективно, так как включение его в Popup будет портить его внутреннее. Дайте ему шанс, если хотите
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCompleter>
#include <QCalendarWidget>
#include <QMouseEvent>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->dateEdit->setDate(QDate::currentDate());
widget = ui->dateEdit->calendarWidget();
widget->setWindowFlags(Qt::Popup);
ui->dateEdit->installEventFilter(this);
//connecting widget with dateedit
ui->dateEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
ui->dateEdit->setCalendarPopup(true);
connect(widget,SIGNAL(clicked(QDate)),ui->dateEdit,SLOT(setDate(QDate)));
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (object == ui->dateEdit)
{
if (event->type() == QEvent::FocusIn || event->type() == QEvent::MouseButtonPress)
{
// WE NEED MOUSE EVENT TO AVOID INTERFERNCE WITH CALENDAR POPUP BUTTON SITUATED AT CORNER OF dateEdit WIDGET
if(widget->isVisible()==false && ( ((QMouseEvent* )event)->x()< (ui->dateEdit->width()-10)))
{
widget->move(ui->dateEdit->mapToGlobal(QPoint(0,ui->dateEdit->height())));
widget->show();
}
}
}
return false;
}
Хочу предложить вариант, аналогичный @Dr. Ответ Xperience, который инкапсулирует виджет календаря в подклассе QDateEdit:
#include <QDateEdit>
#include <QCalendarWidget>
class DateEdit : public QDateEdit {
Q_OBJECT
public:
explicit DateEdit(QWidget *parent = nullptr);
protected:
virtual void focusInEvent(QFocusEvent *event) override;
private:
QCalendarWidget *calendar = new QCalendarWidget(this);
};
DateEdit::DateEdit(QWidget *parent) : QDateEdit (parent) {
setButtonSymbols(QAbstractSpinBox::NoButtons);
setCalendarPopup(false);
setDate(QDate::currentDate());
calendar->setWindowFlags(Qt::Popup);
connect(calendar, &QCalendarWidget::clicked, this, [&](const QDate &date) {
setDate(date);
calendar->hide();
});
}
void DateEdit::focusInEvent(QFocusEvent *event) {
if (!calendar->isVisible()) {
calendar->setSelectedDate(date());
calendar->move(mapToGlobal(QPoint(0, height())));
calendar->show();
}
return QDateEdit::focusInEvent(event);
}
Предупреждение: если вы разместите этот виджет с помощью QtDesigner, он переопределит свойства buttonSymbols и calendarPopup, поэтому вы должны установить его вручную, чтобы скрыть кнопки QDateEdit.
Вот мой хакерский подход к проблеме. После долгой борьбы за что-то чистое, я прочитал исходный кодQDateEditor
(что на самом деле просто упрощенное QDateTimeEditor
) и, похоже, это не чистое решение. Ниже приведен код дляtoggle()
скорее, чем show()
, но до сих пор:
// Enable the calendar popup
date_editor->setCalendarPopup(true);
// Show the calendar popup by default
// There seems to be no proper interface to achieve that
// Fake a mouse click on the right-hand-side button
QPointF point = date_editor->rect().bottomRight() - QPointF{5, 5};
QCoreApplication::postEvent(
date_editor,
new QMouseEvent(QEvent::MouseButtonPress, point, Qt::LeftButton,
Qt::LeftButton, Qt::NoModifier));
Используя что-то вроде этого, вы можете продолжать полагаться на функции проверки редактора.
Кстати, еще одна неприятная вещь о встроенном редакторе, который делает QLineEdit
Заманчиво то, что (по крайней мере, в моем случае) курсор клавиатуры по умолчанию не отображается. Это очень сбивает с толку. Чтобы решить эту проблему, я сделал:
// Select a section so that the cursor is be visible
date_editor->setSelectedSection(QDateTimeEdit::DaySection);
Это или, конечно, выбирает дневную часть даты, но если вы используете стрелки на клавиатуре, выделение исчезнет, но вы можете увидеть курсор на клавиатуре.