3

我试图让一个QDateEdit允许QCalendarWidget在请求时显示(而不是仅仅单击向下箭头)。例如,在我班上的某个地方,我应该能够说:

ui.datepicker.showCalendar()

它应该加载出现在日期选择器正下方的日历。

看起来我需要 sub-class QDateEdit,因为这不起作用:

QDateEdit *de = new QDateEdit();
de->calendarWidget()->show();

当您浏览 Qt 的 QDateTimeEdit.cpp 源时,我也尝试按照指示发送键盘命令,但似乎我的键盘快捷键被禁用或其他东西。

关于我必须对子类做些什么才能使它起作用的任何想法?我在想类似的东西:

class MyDateEdit : QDateEdit
{
  Q_OBJECT

protected:
  void mouseEvent(QEvent *event) {
    this.calendarWidget().show();
  }
};

但唉,这似乎也无法编译或正常工作。

4

5 回答 5

12

在 QDateTimeEdit 中启用“setCalendarPopup (bool enable)”允许弹出日历

于 2013-07-31T07:11:27.207 回答
2

我能够自己弄清楚 - 仍然不知道如何让 QDateEdit 正常工作,但我使用了 QLineEdit 并且它适合我的需要。只需将 QCalendarWidget 的“onClick(QDate)”连接到您创建的插槽即可:

setText(date.toString("M/d/yyyy"));
ui->calendar->hide();

然后使用执行“ui->calendar->show();”的“OnFocusIn”事件将事件过滤器添加到 QLineEdit 请参阅:当 Qt 小部件获得焦点时获取通知/事件/信号

于 2011-08-18T16:00:56.600 回答
0

@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;
}

OR :: 或者,我们可以使用 dateEdit 提供的 QCalendarWidget,尽管它效率不高,因为将其转换为 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;
}
于 2015-09-02T22:09:43.063 回答
0

我想提供类似于@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 的按钮。

于 2019-07-28T16:14:51.293 回答
0

这是我对这个问题的 hacky 方法。在为获得干净的东西而奋斗了一段时间之后,我阅读了源代码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);

This or course 选择日期的日期部分,但如果您使用键盘箭头,则选择消失,但您可以看到键盘光标。

于 2019-08-27T17:12:20.640 回答