提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
前言
一、Buildroot构建QT环境
1.1 构建环境
1.2 检查qtvirtualkeyboard库
二、测试过程
2.1 直接调用qtvirtualkeyboard
1.测试代码
2.测试效果
2.2 运行QML示例
1.测试代码
2.测试效果
2.3 Qwidget 嵌套Qml
1.测试代码
2.测试效果
2.4 第三方Qwidget库移植
1.第三方库地址QVirtualKeyboard: Qt5虚拟键盘支持中英文,仿qt官方的virtualkeyboard模块,但使用QWidget实现。 - Gitee.com
2.移植第三方库
3.测试代码
4.测试效果
参考博客
总结
前言
需要在嵌入式linux开发板上使用qt进行ui界面开发,因为使用的是触摸屏,所以需要使用虚拟键盘来进行输入。且因为是新手且只熟悉c语言,所以使用的qt架构为widgt,本来是以为将Qt Designer的代码直接移植到板子上就行,但不知道为什么在板子上一直无法弹出 qtvirtualkeyboard 键盘,因此最终还是选择暂时移植第三方库来完成键盘输入功能。本文主要对这一过程进行记录,也希望熟悉qt开发的大神不吝指教。
提示:以下是本篇文章正文内容,下面案例可供参考
一、Buildroot构建QT环境
1.1 构建环境
开发板使用buildroot来构建系统,因此使用qt的话直接在buildroot选择qt支持即可,同时这里也加入了对qtvirtualkeyboard 的支持。
先在Target packages ->Graphic libraries and applications (graphic/text)->mesa3d 中开启openGL支持,然后在QT5中选择qtvirtualkeyboard支持。
make编译、烧录后即可在板子上使用qt。
1.2 检查qtvirtualkeyboard库
在板子的usr/lib目录下有生成的一些qt库,在 /usr/lib/qt/plugins/platforminputcontexts/ 目录下可以·看到生成的 libqtvirtualkeyboardplugin.so库,证明键盘库是存在的。
二、测试过程
2.1 直接调用qtvirtualkeyboard
在板子上的环境按如上方式构建完成后,首选方法当然是直接对官方qtvirtualkeyboard进行调用,因为这是在Qt Designer测试成功过的代码。然而在实际测试中,点击QLineEdit无法弹出键盘。
1.测试代码
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QMainWindow>
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLineEdit>
#include <QVBoxLayout>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QLineEdit *lineEdit;
QVBoxLayout *layout;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
centralWidget->setFixedSize(600,480);
lineEdit = new QLineEdit(centralWidget);
lineEdit->setGeometry(30,100,600,100);
lineEdit->setFocusPolicy(Qt::StrongFocus); // 确保可以接收焦点
}
MainWindow::~MainWindow()
{
delete ui;
}
2.测试效果
点击文本框不能弹出·键盘。
2.2 运行QML示例
在2.1的方式失败后,由于不清楚失败原因是什么,因此在网上搜索相关的解决方式,也按照一些方式进行了尝试,包括检查qtvirtualkeyboard库是否生成,相关库在板子上的路径,在板子上设置环境变量等,然而这些方式都未能起效。又因为看到qtvirtualkeyboard主要适配于qml构架,因此便尝试直接使用qml示例代码能否在板子上弹出键盘,而最终的结果也是成功的,使用qml示例可以正常使用键盘。
在buildroot启用quick:
1.测试代码
.pro文件:
QT += quick virtualkeyboard
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
main.qml:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.VirtualKeyboard 2.4
import QtQuick.Controls 2.12 // 这里的x应该替换为你使用的Qt版本对应的版本号
Window {
id: window
visible: true
width: 720
height: 680
title: "Hello World"
flags: Qt.Window | Qt.FramelessWindowHint
Column {
spacing: 10
anchors.centerIn: parent
TextField {
id:textUser
placeholderText: qsTr("User name")
}
}
InputPanel {
id: inputPanel
z: 99
x: 0
y: window.height
width: window.width
Component.onCompleted: {
VirtualKeyboardSettings.activeLocales = ["en_GB","zh_CN"]
VirtualKeyboardSettings.locale = "en_GB"
}
states: State {
name: "visible"
when: inputPanel.active
PropertyChanges {
target: inputPanel
y: window.height - inputPanel.height
}
}
transitions: Transition {
from: ""
to: "visible"
reversible: true
ParallelAnimation {
NumberAnimation {
properties: "y"
duration: 250
easing.type: Easing.InOutQuad
}
}
}
}
TextField {
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
}
}
2.测试效果
点击文本框可弹出键盘进行烧录。
2.3 Qwidget 嵌套Qml
基于2.1与2.2的测试结果,qwidget无法调出键盘,qml成功弹出键盘说明问题应该不是出在buildroot构建的qt环境上,可能在嵌入式上qwidget 本身无法支持qtvirtualkeyboard,因此之后尝试的方法就是在qwidget内嵌入qml,看能否实现基于qwidget调用·qtvirtualkeyboard。
1.测试代码
.pro文件:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
QT += quick virtualkeyboard
QT += quickwidgets
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
qml.qrc
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QDialog>
#include <QQuickWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QDialog *qmlDialog;
QQuickWidget *qmlWidget;
QPushButton* btn;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QQuickWidget *qmlWidget = new QQuickWidget(this);
// qmlWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
qmlWidget->setSource(QUrl("qrc:/main.qml"));
qmlWidget->show();
this->setCentralWidget(qmlWidget);
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
main.qml:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.VirtualKeyboard 2.4
import QtQuick.Controls 2.12 // 这里的x应该替换为你使用的Qt版本对应的版本号
Item {
id: root
Item {
id: appContainer
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: inputPanel.top
}
InputPanel {
id: inputPanel
y: Qt.inputMethod.visible ? parent.height - inputPanel.height : parent.height
anchors.left: parent.left
anchors.right: parent.right
}
// TextField {
// id:appcontainer
// focus: true
// onPressed: {
// vkb.visible = true; //当选择输入框的时候才显示键盘
// }
// }
}
2.测试效果
不知道是否是哪里的嵌入qml有问题,可以看到屏幕最顶部有键盘的图案出现,但实际效果显示也和预期不符,最终也只能放弃此方案。
2.4 第三方Qwidget库移植
在上述方案验证之后,剩下的选择就只有把qt架构整体改为quick或者找个能在qwidget运行的键盘,最终选择了网上开源的第三方库。
1.第三方库地址QVirtualKeyboard: Qt5虚拟键盘支持中英文,仿qt官方的virtualkeyboard模块,但使用QWidget实现。 - Gitee.com
2.移植第三方库
参考库作者的使用说明及其它博客完成移植
git clone 下载库到本地
git clone https://gitee.com/yynestt/QVirtualKeyboard.git
先进入pinyin文件夹执行qmake生成Makefile文件,再执行make生成拼音库,返回上层文件夹执行相同操作,最终生成需要的libQt5SoftKeyboard.so库
cd QVirtualKeyboard/pinyin/
/home/amiliya/linux/buildroot/buildroot/output/host/bin/qmake //qmake路径
make
cd ..
/home/amiliya/linux/buildroot/buildroot/output/host/bin/qmake //qmake路径
make
最终生成的文件
将生成的libQt5SoftKeyboard.so库文件拷贝到板子的/usr/lib/qt/plugins/platforminputcontexts/ 目录下
cp bin/plugins/platforminputcontexts/libQt5SoftKeyboard.so ../linux/buildroot/buildroo
t/output/target/usr/lib/qt/plugins/platforminputcontexts/
这里我复制到buildroot的output文件下,然后通过buildroot打包到板子上。
3.测试代码
将2.1的测试代码中的库引用进行替换·:
// qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
qputenv("QT_IM_MODULE",QByteArray("Qt5Input"));
4.测试效果
可以弹出键盘,样式也和qtvirtualkeyboard差不多,后期也可以根据需要调整一下键盘大小,因此暂时便先使用此方案。
参考博客
在ARM板上实现qt虚拟键盘 Qwidget实现 官方虚拟键盘、第三方虚拟键盘qtvirtualkeyboard //Qwidget最简单但效果不是最好_qt 虚拟键盘-CSDN博客
总结
记录下在嵌入式linux开发板上调用qt虚拟键盘的调试过程。