0

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

M. Frantz
  • 31
  • 1
  • 6
  • 1
    [This answer](http://stackoverflow.com/a/18577450/1329652) has a full working example in Qt 4. It also demonstrates how to use dynamic object properties to overcome the limitations of `QSignalMapper`. It seems that you may need to use posted events instead of sent events. – Kuba hasn't forgotten Monica Mar 21 '17 at 17:49
  • Tried postEvent(), instead of sendEvent(), but the doubleSpinBox still did not respond, and the console output remainded the same. The dialog still received the key press. Note, the doubleSpinBox is inside (child of) the dialog. – M. Frantz Mar 21 '17 at 18:12
  • Does the spinbox have focus? – Kuba hasn't forgotten Monica Mar 21 '17 at 18:24
  • yes. I call ui->doubleSpinBox->setFocus() in the dialog constructor. Also, I double click it on the screen, or select all the text on the screen. – M. Frantz Mar 21 '17 at 18:54

1 Answers1

0

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

M. Frantz
  • 31
  • 1
  • 6