Search code examples
qtqdialogqkeyevent

How to send a key event to a qwidget in a QDialog


I am trying to create a dialog that returns a double, similar to a QInputDialog, but with numeric buttons included in the dialog. It is for an embedded system with no keyboard.

The problem is that the QDoubleSpinBox never reacts to key presses/releases. The dialog itself is receiving the key events. I tried calling event->ignore() in keyPressEvent() and keyReleaseEvent(), without success. Also tried calling QApplication::processEvents(), without success.

I am using Qt 4.8 running on Linux on an embedded ARM processor.

NumericDialog.h

#ifndef NUMERICDIALOG_H
#define NUMERICDIALOG_H

#include <QDialog>
#include <QSignalMapper>

namespace Ui {
class NumericDialog;
}

class NumericDialog : public QDialog
{
   Q_OBJECT

public:
   explicit NumericDialog(QWidget *parent = 0);
   ~NumericDialog();

   void keyPressEvent(QKeyEvent *event);
   void keyReleaseEvent(QKeyEvent *event);

   void SetMax(double max);
   void SetMin(double min);
   void SetValue(double value);
   void SetSuffix(QString suffix);
   void SetTrimEnable(bool enable);

private slots:
   void ButtonClicked(int key);

private:
   Ui::NumericDialog *ui;

   QSignalMapper _SignalMapper;
};

#endif // NUMERICDIALOG_H

NumericDialog.cpp

#include "NumericDialog.h"
#include "ui_NumericDialog.h"

#include <QKeyEvent>
#include <QDebug>


NumericDialog::NumericDialog(QWidget *parent) :
   QDialog(parent),
   ui(new Ui::NumericDialog)
{
   ui->setupUi(this);

   this->setFocusPolicy(Qt::NoFocus);
   ui->doubleSpinBox->setFocusPolicy(Qt::StrongFocus);
   ui->doubleSpinBox->setFocus();

   // Map signals, so we can use one slot for all buttons
   _SignalMapper.setMapping(ui->button0, '0');
   _SignalMapper.setMapping(ui->button1, '1');
   _SignalMapper.setMapping(ui->button2, '2');
   _SignalMapper.setMapping(ui->button3, '3');
   _SignalMapper.setMapping(ui->button4, '4');
   _SignalMapper.setMapping(ui->button5, '5');
   _SignalMapper.setMapping(ui->button6, '6');
   _SignalMapper.setMapping(ui->button7, '7');
   _SignalMapper.setMapping(ui->button8, '8');
   _SignalMapper.setMapping(ui->button9, '9');
   _SignalMapper.setMapping(ui->buttonDot, '.');

   _SignalMapper.setMapping(ui->buttonBS, Qt::Key_Backspace);
   _SignalMapper.setMapping(ui->buttonEnter, Qt::Key_Enter);
   _SignalMapper.setMapping(ui->buttonCancel, Qt::Key_Cancel);
   _SignalMapper.setMapping(ui->buttonUp, Qt::Key_Up);
   _SignalMapper.setMapping(ui->buttonDown, Qt::Key_Down);


   connect(ui->button0, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->button1, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->button2, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->button3, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->button4, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->button5, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->button6, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->button7, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->button8, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->button9, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->buttonDot, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));

   connect(ui->buttonBS, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->buttonEnter, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->buttonCancel, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->buttonUp, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));
   connect(ui->buttonDown, SIGNAL(clicked()), &_SignalMapper, SLOT(map()));

   connect(&_SignalMapper, SIGNAL(mapped(int)),this, SLOT(ButtonClicked(int)));


}

NumericDialog::~NumericDialog()
{
   delete ui;
}

void NumericDialog::keyPressEvent(QKeyEvent *event)
{
   qDebug() << "Dialog got key press" << event->text();

   QDialog::keyPressEvent(event);
}

void NumericDialog::keyReleaseEvent(QKeyEvent *event)
{
   qDebug() << "Dialog got key release" << event->text();

   QDialog::keyReleaseEvent(event);
}

void NumericDialog::SetMax(double max)
{
   ui->doubleSpinBox->setMaximum(max);
   ui->labelMax->setText(QString("%1").arg(max));
   ui->progressBar->setMaximum(max);
}

void NumericDialog::SetMin(double min)
{
   ui->doubleSpinBox->setMinimum(min);
   ui->labelMin->setText(QString("%1").arg(min));
   ui->progressBar->setMinimum(min);
}

void NumericDialog::SetValue(double value)
{
   ui->doubleSpinBox->setValue(value);
   ui->progressBar->setValue(value);
}

void NumericDialog::SetSuffix(QString suffix)
{
   ui->doubleSpinBox->setSuffix(suffix);
}

void NumericDialog::ButtonClicked(int key)
{

   switch(key)
   {
   case Qt::Key_Enter:
      break;
   case Qt::Key_Cancel:
      break;
   case Qt::Key_Up:
      break;
   case Qt::Key_Down:
      break;

   default:
      QKeyEvent keyPress(QEvent::KeyPress, key, Qt::NoModifier, QString(QChar(key)));
      qDebug() << keyPress.text();
      QApplication::sendEvent(ui->doubleSpinBox, &keyPress);

      QKeyEvent keyRelease(QEvent::KeyRelease, key, Qt::NoModifier, QString(QChar(key)));
      qDebug() << keyRelease.text();
      QApplication::sendEvent(ui->doubleSpinBox, &keyRelease);

      //QApplication::processEvents();
      break;
   }
}

When I click on the number '9' button, the console output is:

"9"
"9"
Dialog got key release "9"

When I click on the Backspace button, the console output is:

" " Dialog got key press " " " " Dialog got key release " "

There are no changes to the value in the doubleSpinBox. How do I get the key events to the doubleSpinBox?

Thanks, Mary


Solution

  • I had to set the focusPolicy of all the buttons to NoFocus (in QtDesigner). It now behaves as expected.