【问题标题】:QDateEdit calendar popupQDateEdit 日历弹出窗口
【发布时间】:2011-10-25 07:23:34
【问题描述】:

我正在尝试获取QDateEdit 以允许QCalendarWidget 在请求时显示(而不仅仅是单击向下箭头)。例如,在我班上的某个地方,我应该可以说:

ui.datepicker.showCalendar()

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

看来我需要子类QDateEdit,因为这不起作用:

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

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

关于我必须对子类做些什么以使其正常工作有什么想法吗?我在想类似的东西:

class MyDateEdit : QDateEdit
{
  Q_OBJECT

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

但是很遗憾,这似乎也无法编译或正常工作。

【问题讨论】:

  • 我很想知道您的用例是什么。在你展示它之后,用户是否仍然期望与它进行交互?为什么不单独显示一个 QCalendarWidget?
  • 用例是我想要求用户使用 qcalendarwidget 作为设置日期的唯一方法,但我不希望总是显示日历(以节省空间) -它应该只在他们点击 QDateEdit 时显示(或者如果这是一个更好的选择,它可能是一个 QLabel),然后在他们点击其他地方或选择一个日期后隐藏。
  • 哦,所以您希望 QDateEdit 不能直接编辑,并且在单击 QDateEdit 的任何部分(不仅仅是向下箭头)时显示 QCalendarWidget?
  • 理想情况下是的,但我可以使用 QDateEdit 可编辑或使用 QLabel 或其他解决方案 - 关键是 onFocus 会显示日历,而不是单击向下箭头。
  • 理想情况下,如果你想改变一个小部件的行为,你应该继承小部件并根据需要覆盖。如果有的话,这将导致更好的封装,但在这种情况下,它可能是唯一的选择。浏览源代码可能会给您所需的提示。

标签: qt qcalendarwidget


【解决方案1】:

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

【讨论】:

  • 也适用于 QDateEdit,我使用 QDateEdit *de = new QDateEdit();de->setCalendarPopup(true); 我想这就是你所需要的?
【解决方案2】:

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

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

然后使用执行“ui->calendar->show();”的“OnFocusIn”事件将事件过滤器添加到 QLineEdit见:Get a notification/event/signal when a Qt widget gets focus

【讨论】:

    【解决方案3】:

    @Rob S answer

    您对事件过滤器方法的看法是正确的,我们对 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;
    }
    

    【讨论】:

      【解决方案4】:

      我想提供类似于@Dr 的选项。 Xperience 的answer 将日历小部件封装在 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 的按钮。

      【讨论】:

        【解决方案5】:

        这是我对这个问题的 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);
        

        此或课程选择日期的日期部分,但如果您使用键盘箭头,选择会消失,但您可以看到键盘光标。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-04-13
          • 2020-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多