Qt键盘输入法的开源方案
1. 官方方案
Qt Virtual Keyboard(推荐)
GitHub: https://code.qt.io/cgit/qt/qtvirtualkeyboard.git/
cpp
// 启用方法 qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); // 或者在main.cpp中 #include <QtVirtualKeyboard> int main(int argc, char *argv[]) { qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); QApplication app(argc, argv); return app.exec(); }
QML使用:
qml
import QtQuick 2.15 import QtQuick.VirtualKeyboard 2.15 ApplicationWindow { TextField { id: textField focus: true } InputPanel { id: keyboard y: parent.height - keyboard.height } }
QWidget使用:
1. 基础配置和头文件
项目文件 (.pro)
pro
QT += core gui widgets virtualkeyboard # 启用虚拟键盘模块 DEFINES += QT_VIRTUALKEYBOARD_DEFAULT_STYLE=\"default\" CONFIG += c++17
主函数配置 (main.cpp)
cpp
#include <QApplication> #include <QWidget> #include <QLineEdit> #include <QTextEdit> #include <QVBoxLayout> #include <QtVirtualKeyboard> int main(int argc, char *argv[]) { // 必须设置环境变量 qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); QApplication app(argc, argv); // 创建主窗口 QWidget window; QVBoxLayout *layout = new QVBoxLayout(&window); // 创建输入控件 QLineEdit *lineEdit = new QLineEdit(); lineEdit->setPlaceholderText("点击这里显示虚拟键盘"); QTextEdit *textEdit = new QTextEdit(); textEdit->setPlaceholderText("多行文本编辑框"); layout->addWidget(lineEdit); layout->addWidget(textEdit); window.resize(400, 300); window.show(); return app.exec(); }
2. 自定义虚拟键盘管理器
VirtualKeyboardManager.h
cpp
#ifndef VIRTUALKEYBOARDMANAGER_H #define VIRTUALKEYBOARDMANAGER_H #include <QObject> #include <QWidget> #include <QInputMethod> #include <QEvent> #include <QApplication> class VirtualKeyboardManager : public QObject { Q_OBJECT public: static VirtualKeyboardManager& instance(); void showKeyboard(); void hideKeyboard(); bool isVisible() const; void setKeyboardParent(QWidget *parent); void setInputFocusWidget(QWidget *widget); protected: bool eventFilter(QObject *obj, QEvent *event) override; private: VirtualKeyboardManager(QObject *parent = nullptr); ~VirtualKeyboardManager() = default; QInputMethod *m_inputMethod; QWidget *m_focusWidget; QWidget *m_keyboardParent; }; #endif // VIRTUALKEYBOARDMANAGER_H
VirtualKeyboardManager.cpp
cpp
#include "VirtualKeyboardManager.h" #include <QDebug> VirtualKeyboardManager::VirtualKeyboardManager(QObject *parent) : QObject(parent), m_inputMethod(nullptr), m_focusWidget(nullptr), m_keyboardParent(nullptr) { m_inputMethod = QGuiApplication::inputMethod(); // 安装事件过滤器到应用程序 qApp->installEventFilter(this); } VirtualKeyboardManager& VirtualKeyboardManager::instance() { static VirtualKeyboardManager instance; return instance; } void VirtualKeyboardManager::showKeyboard() { if (m_inputMethod) { m_inputMethod->show(); qDebug() << "Virtual keyboard shown"; } } void VirtualKeyboardManager::hideKeyboard() { if (m_inputMethod) { m_inputMethod->hide(); qDebug() << "Virtual keyboard hidden"; } } bool VirtualKeyboardManager::isVisible() const { return m_inputMethod ? m_inputMethod->isVisible() : false; } void VirtualKeyboardManager::setKeyboardParent(QWidget *parent) { m_keyboardParent = parent; } void VirtualKeyboardManager::setInputFocusWidget(QWidget *widget) { m_focusWidget = widget; if (widget) { widget->setFocus(); showKeyboard(); } } bool VirtualKeyboardManager::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::FocusIn) { if (QWidget *widget = qobject_cast<QWidget*>(obj)) { if (widget->inherits("QLineEdit") || widget->inherits("QTextEdit") || widget->inherits("QPlainTextEdit") || widget->inherits("QComboBox")) { m_focusWidget = widget; showKeyboard(); qDebug() << "Focus gained by:" << widget->metaObject()->className(); } } } else if (event->type() == QEvent::FocusOut) { // 可选:失去焦点时隐藏键盘 // hideKeyboard(); } else if (event->type() == QEvent::Close) { hideKeyboard(); } return QObject::eventFilter(obj, event); }
3. 自定义输入控件
VirtualInputWidget.h
cpp
#ifndef VIRTUALINPUTWIDGET_H #define VIRTUALINPUTWIDGET_H #include <QLineEdit> #include <QFocusEvent> class VirtualInputWidget : public QLineEdit { Q_OBJECT public: explicit VirtualInputWidget(QWidget *parent = nullptr); protected: void focusInEvent(QFocusEvent *event) override; void mousePressEvent(QMouseEvent *event) override; signals: void inputActivated(); }; #endif // VIRTUALINPUTWIDGET_H
VirtualInputWidget.cpp
cpp
#include "VirtualInputWidget.h" #include "VirtualKeyboardManager.h" VirtualInputWidget::VirtualInputWidget(QWidget *parent) : QLineEdit(parent) { } void VirtualInputWidget::focusInEvent(QFocusEvent *event) { QLineEdit::focusInEvent(event); emit inputActivated(); // 通知键盘管理器显示键盘 VirtualKeyboardManager::instance().setInputFocusWidget(this); } void VirtualInputWidget::mousePressEvent(QMouseEvent *event) { QLineEdit::mousePressEvent(event); emit inputActivated(); VirtualKeyboardManager::instance().setInputFocusWidget(this); }
4. 增强的键盘控制器
EnhancedKeyboardController.h
cpp
#ifndef ENHANCEDKEYBOARDCONTROLLER_H #define ENHANCEDKEYBOARDCONTROLLER_H #include <QObject> #include <QWidget> #include <QInputMethod> #include <QTimer> class EnhancedKeyboardController : public QObject { Q_OBJECT public: explicit EnhancedKeyboardController(QWidget *parent = nullptr); ~EnhancedKeyboardController(); void enableAutoShow(bool enable = true); void setKeyboardTheme(const QString &theme); void setKeyboardLanguage(const QString &language); void showKeyboard(); void hideKeyboard(); void toggleKeyboard(); public slots: void onApplicationStateChanged(Qt::ApplicationState state); private slots: void checkFocus(); private: QInputMethod *m_inputMethod; QTimer *m_focusCheckTimer; bool m_autoShowEnabled; QWidget *m_lastFocusedWidget; }; #endif // ENHANCEDKEYBOARDCONTROLLER_H
EnhancedKeyboardController.cpp
cpp
#include "EnhancedKeyboardController.h" #include <QGuiApplication> #include <QDebug> #include <QWidget> EnhancedKeyboardController::EnhancedKeyboardController(QWidget *parent) : QObject(parent), m_inputMethod(nullptr), m_autoShowEnabled(true), m_lastFocusedWidget(nullptr) { m_inputMethod = QGuiApplication::inputMethod(); // 创建焦点检查定时器 m_focusCheckTimer = new QTimer(this); m_focusCheckTimer->setInterval(100); connect(m_focusCheckTimer, &QTimer::timeout, this, &EnhancedKeyboardController::checkFocus); m_focusCheckTimer->start(); // 监听应用状态变化 connect(qApp, &QApplication::applicationStateChanged, this, &EnhancedKeyboardController::onApplicationStateChanged); } EnhancedKeyboardController::~EnhancedKeyboardController() { m_focusCheckTimer->stop(); } void EnhancedKeyboardController::enableAutoShow(bool enable) { m_autoShowEnabled = enable; } void EnhancedKeyboardController::setKeyboardTheme(const QString &theme) { qputenv("QT_QUICK_CONTROLS_STYLE", theme.toUtf8()); } void EnhancedKeyboardController::setKeyboardLanguage(const QString &language) { // 设置键盘语言环境 qputenv("QT_VIRTUALKEYBOARD_DEFAULT_LANG", language.toUtf8()); } void EnhancedKeyboardController::showKeyboard() { if (m_inputMethod && !m_inputMethod->isVisible()) { m_inputMethod->show(); qDebug() << "Keyboard shown programmatically"; } } void EnhancedKeyboardController::hideKeyboard() { if (m_inputMethod && m_inputMethod->isVisible()) { m_inputMethod->hide(); qDebug() << "Keyboard hidden programmatically"; } } void EnhancedKeyboardController::toggleKeyboard() { if (m_inputMethod->isVisible()) { hideKeyboard(); } else { showKeyboard(); } } void EnhancedKeyboardController::onApplicationStateChanged(Qt::ApplicationState state) { if (state != Qt::ApplicationActive) { hideKeyboard(); } } void EnhancedKeyboardController::checkFocus() { if (!m_autoShowEnabled) return; QWidget *focusedWidget = QApplication::focusWidget(); if (focusedWidget && focusedWidget != m_lastFocusedWidget) { m_lastFocusedWidget = focusedWidget; // 检查是否是文本输入控件 if (focusedWidget->inherits("QLineEdit") || focusedWidget->inherits("QTextEdit") || focusedWidget->inherits("QPlainTextEdit") || focusedWidget->inherits("QComboBox")) { showKeyboard(); } else { hideKeyboard(); } } }
2. 第三方开源输入法框架
Maliit 框架
GitHub: https://github.com/maliit/framework
bash
# Ubuntu安装 sudo apt install maliit-framework-server maliit-inputmethod-context # 在Qt中使用 qputenv("QT_IM_MODULE", QByteArray("maliit"));
Fcitx5 框架
GitHub: https://github.com/fcitx/fcitx5
cpp
// 支持Qt的输入法框架 qputenv("QT_IM_MODULE", QByteArray("fcitx"));
IBus 框架
GitHub: https://github.com/ibus/ibus
cpp
qputenv("QT_IM_MODULE", QByteArray("ibus"));
3. 专门为Qt设计的开源虚拟键盘
QVirtualKeyboard
GitHub: https://github.com/kanryu/quickvirtualkeyboard
qml
import QtQuick 2.0 import QuickVirtualKeyboard 1.0 Rectangle { width: 800 height: 600 TextInput { id: textInput width: 200 height: 30 } Keyboard { target: textInput anchors.bottom: parent.bottom } }
QtOnScreenKeyboard
GitHub: https://github.com/mbasaglia/QtOnScreenKeyboard
cpp
#include "keyboardwidget.h" // 在需要的地方显示键盘 KeyboardWidget *keyboard = new KeyboardWidget(this); keyboard->setTargetWidget(yourTextEdit); keyboard->show();
QmlKeyboard
GitHub: https://github.com/kanryu/qmlkeyboard
qml
import QtQuick 2.0 import QmlKeyboard 1.0 ApplicationWindow { TextField { id: textField } Keyboard { target: textField anchors.bottom: parent.bottom } }
4. 嵌入式设备专用方案
T9拼音输入法 for Qt
GitHub: https://github.com/supertable/t9qt
cpp
#include "t9inputmethod.h" T9InputMethod *t9 = new T9InputMethod(this); t9->setInputField(yourLineEdit); t9->show();
Qt5ChineseInputMethod
GitHub: https://github.com/CodeZry/Qt5ChineseInputMethod
支持拼音、五笔等中文输入法。
5. 自定义实现的完整示例
简单虚拟键盘实现
keyboardwidget.h:
cpp
#ifndef KEYBOARDWIDGET_H #define KEYBOARDWIDGET_H #include <QWidget> #include <QPushButton> #include <QGridLayout> #include <QLineEdit> class KeyboardWidget : public QWidget { Q_OBJECT public: explicit KeyboardWidget(QWidget *parent = nullptr); void setTargetWidget(QWidget *target); private slots: void onKeyClicked(); void onBackspaceClicked(); void onEnterClicked(); void onSpaceClicked(); private: void setupUI(); QWidget *targetWidget; QGridLayout *mainLayout; }; #endif
keyboardwidget.cpp:
cpp
#include "keyboardwidget.h" #include <QApplication> KeyboardWidget::KeyboardWidget(QWidget *parent) : QWidget(parent), targetWidget(nullptr) { setupUI(); setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); } void KeyboardWidget::setupUI() { mainLayout = new QGridLayout(this); // 第一行:数字 QStringList row1 = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}; for (int i = 0; i < row1.size(); ++i) { QPushButton *btn = new QPushButton(row1[i]); connect(btn, &QPushButton::clicked, this, &KeyboardWidget::onKeyClicked); mainLayout->addWidget(btn, 0, i); } // 第二行:字母 QStringList row2 = {"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"}; for (int i = 0; i < row2.size(); ++i) { QPushButton *btn = new QPushButton(row2[i]); connect(btn, &QPushButton::clicked, this, &KeyboardWidget::onKeyClicked); mainLayout->addWidget(btn, 1, i); } // 功能键 QPushButton *backspaceBtn = new QPushButton("←"); QPushButton *spaceBtn = new QPushButton("Space"); QPushButton *enterBtn = new QPushButton("Enter"); connect(backspaceBtn, &QPushButton::clicked, this, &KeyboardWidget::onBackspaceClicked); connect(spaceBtn, &QPushButton::clicked, this, &KeyboardWidget::onSpaceClicked); connect(enterBtn, &QPushButton::clicked, this, &KeyboardWidget::onEnterClicked); mainLayout->addWidget(backspaceBtn, 2, 0, 1, 2); mainLayout->addWidget(spaceBtn, 2, 2, 1, 6); mainLayout->addWidget(enterBtn, 2, 8, 1, 2); } void KeyboardWidget::setTargetWidget(QWidget *target) { targetWidget = target; } void KeyboardWidget::onKeyClicked() { if (!targetWidget) return; QPushButton *btn = qobject_cast<QPushButton*>(sender()); if (btn) { QString text = btn->text(); if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(targetWidget)) { lineEdit->insert(text); } } } void KeyboardWidget::onBackspaceClicked() { if (!targetWidget) return; if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(targetWidget)) { lineEdit->backspace(); } } void KeyboardWidget::onSpaceClicked() { if (targetWidget && qobject_cast<QLineEdit*>(targetWidget)) { qobject_cast<QLineEdit*>(targetWidget)->insert(" "); } } void KeyboardWidget::onEnterClicked() { hide(); // 输入完成隐藏键盘 }
6. 使用建议
环境配置
bash
# 检查可用的输入法模块 ls /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/ # 设置环境变量 export QT_IM_MODULE=qtvirtualkeyboard
项目配置(.pro文件)
pro
# 如果使用Qt Virtual Keyboard QT += virtualkeyboard # 或者手动链接 LIBS += -lqtvirtualkeyboard
平台特定说明
- Linux: 支持最好,多种框架可选
- Windows: 推荐使用Qt Virtual Keyboard
- 嵌入式Linux: 考虑性能,选择轻量级方案
- Android/iOS: 通常使用系统自带键盘
根据你的具体需求(中文输入、嵌入式设备、桌面应用等)选择合适的方案。对于大多数情况,Qt Virtual Keyboard是最稳定和功能最全的选择。