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.15ApplicationWindow {TextField {id: textFieldfocus: true}InputPanel {id: keyboardy: 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_OBJECTpublic: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_OBJECTpublic: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_OBJECTpublic: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.0Rectangle {width: 800height: 600TextInput {id: textInputwidth: 200height: 30}Keyboard {target: textInputanchors.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.0ApplicationWindow {TextField {id: textField}Keyboard {target: textFieldanchors.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_OBJECTpublic: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是最稳定和功能最全的选择。