【问题标题】:How to make a French keyboard's dot key (numeric keypad) work as input with Qt?如何使法语键盘的点键(数字键盘)用作 Qt 的输入?
【发布时间】:2014-09-10 10:40:42
【问题描述】:

我正在设计一个 C++/Qt 应用程序。我在法语 Windows 环境中使用法语键盘。

当我尝试在 QDoubleSpinBox 控件中键入十进制数字时,按点数字键盘按钮什么也不做......我希望它插入一个小数分隔符!

这是一个非常简单的 Qt 程序来隔离问题:

ma​​in.cpp:

#include <QApplication>
#include <QVBoxLayout>
#include <QLabel>
#include <QSpinBox>
#include <QDialog>

class Dialog : public QDialog
{
public:
    Dialog()
    {
        QVBoxLayout* layout = new QVBoxLayout( this );

        layout->addWidget( new QLabel( QLocale().toString( 3.14 ), this ) );
        layout->addWidget( new QDoubleSpinBox( this ) );
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Dialog w;
    w.show();

    return a.exec();
}

我在一台法国 PC 上使用 Visual Studio 2010 和 5.2.1 编译它。

对话框打开时:

然后:

  • QLabel 显示“3,14”,这意味着法语 QLocale 已正确使用(否则,它将显示 3.14,英语默认 stype)。好的
  • QDoubleSpinBox 显示“0,00”。好的
  • 我可以使用“,”标准键盘键在微调框中键入十进制值。好的
  • 我无法使用“.”在微调框中键入十进制值标准键盘键。好的
  • 但是,当我在数字法语键盘上按点键时,什么也没有发生!这应该输入小数分隔符,无论使用什么语言环境设置!

我正在寻找一个全局解决方案(在 QApplication 级别),而不是在 QSpinBox 级别,因为我的原始项目中有很多。

【问题讨论】:

  • 纠正我,如果我错了 - 你想按'。'按钮,并期望它会打印“,”,因为您的语言环境使用“,”作为小数分隔符?
  • 没错。就像 Microsoft Excel 一样:如果我按“1”“。”和“2”从键盘,是写“1,2”在选定的单元格。

标签: c++ qt keyboard


【解决方案1】:

https://bugreports.qt.io/browse/QTBUG-41256 被修复之前,解决方案是应用程序全局事件过滤器,以便任何使用'.'在默认语言环境使用“,”作为小数点分隔符的系统上,数字键盘上的键(并且只有那里)变成了“,”。

class GlobalEventFilter : public QObject
{
public:
    explicit GlobalEventFilter(QObject *parent) : QObject(parent) {}
    bool eventFilter(QObject *obj, QEvent *ev) override {
        if (ev->type() == QEvent::KeyPress || ev->type() == QEvent::KeyRelease) {
            QKeyEvent *kev = static_cast<QKeyEvent *>(ev);
            if (kev->key() == Qt::Key_Period && (kev->modifiers() & Qt::KeypadModifier)) {
                QChar decimalPoint = QLocale().decimalPoint();
                if (decimalPoint == QLatin1Char(',')) {
                    QKeyEvent modifiedKeyEvent(kev->type(), Qt::Key_Comma, kev->modifiers(), QString(decimalPoint), kev->isAutoRepeat(), kev->count());
                    qApp->sendEvent(obj, &modifiedKeyEvent);
                    return true;
                }
            }
        }
        return false;
    }
};

在您的main() 中添加qApp-&gt;installEventFilter(new GlobalEventFilter(qApp));

我在法语 Linux 系统上进行了测试。

【讨论】:

  • 啊,我忘了检查接收器(obj)是一个 QDoubleSpinBox,所以这个事件过滤器会影响所有的小部件,甚至是 lineedits 和 textedits。如果不希望这样做,请将从 QKeyEvent modifiedKeyEvent 开始的 3 行包装成这样的 if 语句:if (qobject_cast&lt;QDoubleSpinBox *&gt;(obj) || (obj-&gt;parent() &amp;&amp; qobject_cast&lt;QDoubleSpinBox *&gt;(obj-&gt;parent())) {
  • 没错,我注意到了。但我建议QDoubleSpinBoxQLineEdit 使用相同的行为,否则可能会让用户感到困惑。
【解决方案2】:

我相信你应该使用QDoubleSpinBox,而不是QSpinBox。正如QSpinBox 的文档所述:

将 QDoubleSpinBox 用于浮点值。

正如你在QDoubleSpinBox::textFromValue看到的那样

旋转框在需要显示给定值时使用此虚函数。默认实现返回一个包含使用 QWidget::locale().toString(value, QLatin1Char('f'), decimals()) 打印的值的字符串,并将删除千位分隔符。

【讨论】:

  • 不明白你的帖子...我正在使用 QDoubleSpinBox,检查我发布的代码...。它不起作用!
  • 你的代码没有显示QDoubleSpinBox,直到你编辑它,在我回答之后!
  • 如果它仍然不起作用,我建议考虑创建一个从 QObject 派生的类,重载其 keyPressEvent 以拦截“。”键并将其作为事件过滤器安装在您想要用于此行为的小部件上。然后,您可以检测到“。”并将其替换为 QLocale::decimalPoint() - qt-project.org/doc/qt-5/qobject.html#installEventFilter
  • 不,我只编辑了错误提及QSpinBox 的第二句话。代码+截图一直使用QDoubleSpinBox,我没有编辑那些。删除您的帖子可能有意义,因为它没有回答原始问题...
  • 你说得对,我填了一个qt bug:bugreports.qt-project.org/browse/QTBUG-41256
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 2017-10-02
  • 2022-01-24
相关资源
最近更新 更多