[Qt]显示地图-3 切换地图和图片

——pro————————–
QT += core gui location positioning
QT += quick widgets quickwidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
imagewidget.cpp \
main.cpp \
mainwindow.cpp

HEADERS += \
imagewidget.h \
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

DISTFILES += \
map.qml

RESOURCES += \
src.qrc

———————mainwindow.h————————-
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:

bool isQmlView =false;

MainWindow(QWidget *parent = nullptr);
~MainWindow();

// 更新坐标的接口
void updateCoordinates(double latA, double lonA, double latB, double lonB);
private slots:
void on_zoomInButton_clicked();
void on_zoomOutButton_clicked();
void on_p2m_clicked();
private:
Ui::MainWindow *ui;
private :
void zoomOut();
void zoomIn();
};

#endif // MAINWINDOW_H

———————main.cpp—————————-
#include “mainwindow.h”
#include
#include
#include “imagewidget.h”

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

// 更新坐标到新位置
// w.updateCoordinates(34.0522, -118.2437, 36.7783, -119.4179); // A: Los Angeles, B: Fresno

qDebug()<<"11"; return a.exec(); } ---------------------mainwindow.cpp------------------------------------- #include "mainwindow.h" #include "ui_mainwindow.h" #include "imagewidget.h" #include
#include
#include
#include
#include
#include

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);

// 获取 QQuickWidget
QQuickWidget *quickWidget = ui->quickWidget;

// 设置 QML 文件路径
quickWidget->setSource(QUrl(QStringLiteral(“qrc:/map.qml”)));
quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);

// 获取 QML 上下文
QQmlContext *context = quickWidget->rootContext();

// 默认坐标
QVariant coordinateA = QVariant::fromValue(QGeoCoordinate(37.7749, -122.4194)); // San Francisco
QVariant coordinateB = QVariant::fromValue(QGeoCoordinate(37.8044, -122.2711)); // Oakland

// 传递默认坐标到 QML
context->setContextProperty(“coordinateA”, coordinateA);
context->setContextProperty(“coordinateB”, coordinateB);

// 连接按钮到槽函数
connect(ui->zoomInButton, &QPushButton::clicked, this, &MainWindow::on_zoomInButton_clicked);
connect(ui->zoomOutButton, &QPushButton::clicked, this, &MainWindow::on_zoomOutButton_clicked);

}

void MainWindow::updateCoordinates(double latA, double lonA, double latB, double lonB)
{
QQuickWidget *quickWidget = ui->quickWidget;
QQuickItem *rootObject = quickWidget->rootObject(); // 修改为 QQuickItem*

if (rootObject) {
// 更新 QML 的属性
rootObject->setProperty(“coordinateA”, QVariant::fromValue(QGeoCoordinate(latA, lonA)));
rootObject->setProperty(“coordinateB”, QVariant::fromValue(QGeoCoordinate(latB, lonB)));
} else {
qWarning() << "Root object is null!"; } } // 放大地图 void MainWindow::zoomIn() { } // 缩小地图 void MainWindow::zoomOut() { } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_zoomInButton_clicked() { QQuickWidget *quickWidget = ui->quickWidget;
QQuickItem *rootObject = quickWidget->rootObject();

if (rootObject) {
double currentZoom = rootObject->property(“zoomLevelVal”).toDouble();
double newZoom = currentZoom + 1.0; // 增加 zoomLevel
rootObject->setProperty(“zoomLevelVal”, newZoom);
}
}

void MainWindow::on_zoomOutButton_clicked()
{

QQuickWidget *quickWidget = ui->quickWidget;
QQuickItem *rootObject = quickWidget->rootObject();

if (rootObject) {
double currentZoom = rootObject->property(“zoomLevelVal”).toDouble();
double newZoom = currentZoom – 1.0; // 减少 zoomLevel
rootObject->setProperty(“zoomLevelVal”, newZoom);
qDebug()<update();
}
}

void MainWindow::on_p2m_clicked()
{
isQmlView = !isQmlView;

if (isQmlView) {
ui->quickWidget->show();
ui->label->hide();
} else {
ui->quickWidget->hide();
ui->label->show();
//imageWidget->repaint();
}
}

———————-map.qml——————————
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtLocation 5.15
import QtPositioning 5.15

Item {
width: 800
height: 600

Plugin {
id: mapPlugin
name: “osm” // 使用 OpenStreetMap 插件
}

// 坐标属性,可通过 C++ 更新
property var coordinateA: QtPositioning.coordinate(37.7749, -122.4194)
property var coordinateB: QtPositioning.coordinate(37.8044, -122.2711)
property real zoomLevelVal: 10

Map {
anchors.fill: parent
plugin: mapPlugin
center: coordinateA // 默认以 A 为中心
zoomLevel: zoomLevelVal // 使用绑定的 zoomLevel 属性

// 显示从 A 到 B 的路径
MapPolyline {
line.width: 1
line.color: “red”
path: [coordinateA, coordinateB]
}
}
}

[Qt]显示地图-2 将地图嵌入主窗口,可放大缩小

———————pro—————————–
QT += core gui location positioning
QT += quick widgets quickwidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#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

DISTFILES += \
map.qml

RESOURCES += \
src.qrc

————————mainwindow.h—————————-

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

// 更新坐标的接口
void updateCoordinates(double latA, double lonA, double latB, double lonB);

private slots:
void on_zoomInButton_clicked();

void on_zoomOutButton_clicked();

private:
Ui::MainWindow *ui;
private :
void zoomOut();
void zoomIn();
};

#endif // MAINWINDOW_H

——————————–main.cpp———————————

#include “mainwindow.h”
#include
#include

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

// 更新坐标到新位置
// w.updateCoordinates(34.0522, -118.2437, 36.7783, -119.4179); // A: Los Angeles, B: Fresno

qDebug()<<"11"; return a.exec(); } ---------------------------mainwindow.cpp--------------------------------------- #include "mainwindow.h" #include "ui_mainwindow.h" #include
#include
#include
#include
#include

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);

// 获取 QQuickWidget
QQuickWidget *quickWidget = ui->quickWidget;

// 设置 QML 文件路径
quickWidget->setSource(QUrl(QStringLiteral(“qrc:/map.qml”)));
quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);

// 获取 QML 上下文
QQmlContext *context = quickWidget->rootContext();

// 默认坐标
QVariant coordinateA = QVariant::fromValue(QGeoCoordinate(37.7749, -122.4194)); // San Francisco
QVariant coordinateB = QVariant::fromValue(QGeoCoordinate(37.8044, -122.2711)); // Oakland

// 传递默认坐标到 QML
context->setContextProperty(“coordinateA”, coordinateA);
context->setContextProperty(“coordinateB”, coordinateB);

// 连接按钮到槽函数
connect(ui->zoomInButton, &QPushButton::clicked, this, &MainWindow::on_zoomInButton_clicked);
connect(ui->zoomOutButton, &QPushButton::clicked, this, &MainWindow::on_zoomOutButton_clicked);
}

void MainWindow::updateCoordinates(double latA, double lonA, double latB, double lonB)
{
QQuickWidget *quickWidget = ui->quickWidget;
QQuickItem *rootObject = quickWidget->rootObject(); // 修改为 QQuickItem*

if (rootObject) {
// 更新 QML 的属性
rootObject->setProperty(“coordinateA”, QVariant::fromValue(QGeoCoordinate(latA, lonA)));
rootObject->setProperty(“coordinateB”, QVariant::fromValue(QGeoCoordinate(latB, lonB)));
} else {
qWarning() << "Root object is null!"; } } // 放大地图 void MainWindow::zoomIn() { } // 缩小地图 void MainWindow::zoomOut() { } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_zoomInButton_clicked() { qDebug()<<"2"; QQuickWidget *quickWidget = ui->quickWidget;
QQuickItem *rootObject = quickWidget->rootObject();

if (rootObject) {
double currentZoom = rootObject->property(“zoomLevelVal”).toDouble();
double newZoom = currentZoom + 1.0; // 增加 zoomLevel
rootObject->setProperty(“zoomLevelVal”, newZoom);
}
}

void MainWindow::on_zoomOutButton_clicked()
{

QQuickWidget *quickWidget = ui->quickWidget;
QQuickItem *rootObject = quickWidget->rootObject();

if (rootObject) {
double currentZoom = rootObject->property(“zoomLevelVal”).toDouble();
double newZoom = currentZoom – 1.0; // 减少 zoomLevel
rootObject->setProperty(“zoomLevelVal”, newZoom);
qDebug()<update();
}
}

———————————main.qml———————————-
#include “mainwindow.h”
#include “ui_mainwindow.h”
#include
#include
#include
#include
#include

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);

// 获取 QQuickWidget
QQuickWidget *quickWidget = ui->quickWidget;

// 设置 QML 文件路径
quickWidget->setSource(QUrl(QStringLiteral(“qrc:/map.qml”)));
quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);

// 获取 QML 上下文
QQmlContext *context = quickWidget->rootContext();

// 默认坐标
QVariant coordinateA = QVariant::fromValue(QGeoCoordinate(37.7749, -122.4194)); // San Francisco
QVariant coordinateB = QVariant::fromValue(QGeoCoordinate(37.8044, -122.2711)); // Oakland

// 传递默认坐标到 QML
context->setContextProperty(“coordinateA”, coordinateA);
context->setContextProperty(“coordinateB”, coordinateB);

// 连接按钮到槽函数
connect(ui->zoomInButton, &QPushButton::clicked, this, &MainWindow::on_zoomInButton_clicked);
connect(ui->zoomOutButton, &QPushButton::clicked, this, &MainWindow::on_zoomOutButton_clicked);
}

void MainWindow::updateCoordinates(double latA, double lonA, double latB, double lonB)
{
QQuickWidget *quickWidget = ui->quickWidget;
QQuickItem *rootObject = quickWidget->rootObject(); // 修改为 QQuickItem*

if (rootObject) {
// 更新 QML 的属性
rootObject->setProperty(“coordinateA”, QVariant::fromValue(QGeoCoordinate(latA, lonA)));
rootObject->setProperty(“coordinateB”, QVariant::fromValue(QGeoCoordinate(latB, lonB)));
} else {
qWarning() << "Root object is null!"; } } // 放大地图 void MainWindow::zoomIn() { } // 缩小地图 void MainWindow::zoomOut() { } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_zoomInButton_clicked() { qDebug()<<"2"; QQuickWidget *quickWidget = ui->quickWidget;
QQuickItem *rootObject = quickWidget->rootObject();

if (rootObject) {
double currentZoom = rootObject->property(“zoomLevelVal”).toDouble();
double newZoom = currentZoom + 1.0; // 增加 zoomLevel
rootObject->setProperty(“zoomLevelVal”, newZoom);
}
}

void MainWindow::on_zoomOutButton_clicked()
{

QQuickWidget *quickWidget = ui->quickWidget;
QQuickItem *rootObject = quickWidget->rootObject();

if (rootObject) {
double currentZoom = rootObject->property(“zoomLevelVal”).toDouble();
double newZoom = currentZoom – 1.0; // 减少 zoomLevel
rootObject->setProperty(“zoomLevelVal”, newZoom);
qDebug()<update();
}
}

[Qt]显示地图-1

—————–pro————————-
QT += core gui location positioning
QT += quick widgets quickwidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
CoordinateUpdater.cpp \
main.cpp \
mainwindow.cpp

HEADERS += \
CoordinateUpdater.h \
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

DISTFILES += \
main.qml

RESOURCES += \
res.qrc
————-CoordinateUpdater.h—————————-
#ifndef COORDINATEUPDATER_H
#define COORDINATEUPDATER_H

#include
#include

class CoordinateUpdater : public QObject {
Q_OBJECT
Q_PROPERTY(QGeoCoordinate coordinateA READ coordinateA WRITE setCoordinateA NOTIFY coordinateAChanged)
Q_PROPERTY(QGeoCoordinate coordinateB READ coordinateB WRITE setCoordinateB NOTIFY coordinateBChanged)

public:
explicit CoordinateUpdater(QObject *parent = nullptr);

QGeoCoordinate coordinateA() const;
QGeoCoordinate coordinateB() const;

void setCoordinateA(const QGeoCoordinate &coord);
void setCoordinateB(const QGeoCoordinate &coord);

signals:
void coordinateAChanged();
void coordinateBChanged();

private:
QGeoCoordinate m_coordinateA;
QGeoCoordinate m_coordinateB;
};

#endif // COORDINATEUPDATER_H

———————————-mainwindow.h—————————–

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

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;
};

#endif // MAINWINDOW_H

————————————CoordinateUpdater.cpp—————————-
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

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;
};

#endif // MAINWINDOW_H
——————————————main.cpp————————————–
#include
#include
#include
#include
#include
#include
#include “CoordinateUpdater.h”

int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);

// 创建 C++ 坐标更新器
CoordinateUpdater coordinateUpdater;
coordinateUpdater.setCoordinateA(QGeoCoordinate(37.7749, -122.4194)); // 初始值 (旧金山)
coordinateUpdater.setCoordinateB(QGeoCoordinate(37.8044, -122.2711)); // 初始值 (奥克兰)

QQmlApplicationEngine engine;

// 将 C++ 对象暴露给 QML
engine.rootContext()->setContextProperty(“coordinateUpdater”, &coordinateUpdater);

// 加载 QML 文件
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);

// 模拟外部更新坐标
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&coordinateUpdater]() {
double newLatA = (qrand() % 180) – 90.0; // 随机纬度
double newLonA = (qrand() % 360) – 180.0; // 随机经度
double newLatB = (qrand() % 180) – 90.0;
double newLonB = (qrand() % 360) – 180.0;

coordinateUpdater.setCoordinateA(QGeoCoordinate(newLatA, newLonA));
coordinateUpdater.setCoordinateB(QGeoCoordinate(newLatB, newLonB));
});
timer.start(2000); // 每 2 秒更新坐标

return app.exec();
}

//#include “main.moc”

—————————–mainwindow.cpp———————————–

#include “mainwindow.h”
#include “ui_mainwindow.h”

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}

MainWindow::~MainWindow()
{
delete ui;
}

——————————–main.qml————————————
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtLocation 5.15
import QtPositioning 5.15

ApplicationWindow {
visible: true
width: 640
height: 480

// QML 中的动态坐标绑定到 C++ 的属性
property var coordinateA: coordinateUpdater.coordinateA
property var coordinateB: coordinateUpdater.coordinateB

// 定义地图
Map {
anchors.fill: parent
plugin: Plugin {
name: “osm” // 使用 OpenStreetMap 插件
}
center: coordinateA // 设置地图中心为 A 坐标
zoomLevel: 12

// 绘制指向 B 坐标的箭头
MapQuickItem {
coordinate: coordinateA // A 坐标点
sourceItem: Image {
width: 30
height: 30
source: “qrc:/monkey.png” // 替换为您的箭头图片
rotation: Math.atan2(coordinateB.latitude – coordinateA.latitude,
coordinateB.longitude – coordinateA.longitude) * 180 / Math.PI
}
}

MapQuickItem {
coordinate: coordinateA // A 坐标点
sourceItem: Image {
width: 30
height: 30
source: “qrc:/monkey.png” // 替换为您的箭头图片
rotation: Math.atan2(-coordinateB.latitude + coordinateA.latitude,
-coordinateB.longitude + coordinateA.longitude) * 180 / Math.PI
}
}
}
/*
// 坐标更新时打印调试信息
Connections {
target: coordinateUpdater
onCoordinateAChanged: console.log(“Updated A:”, coordinateUpdater.coordinateA)
onCoordinateBChanged: console.log(“Updated B:”, coordinateUpdater.coordinateB)
}
*/
}

[Qt]QtLocation移植

在使用香橙派时用到了qtlocation模块,但是开发板没有响应的库,需要自己移植
1.使用命令 *** 查看版本
开发板使用5.15.3版本Qt,需要下载相同版本 https://qt-mirror.dannhauer.de/archive/qt/5.15/
2.下载后解压到主机 ~/tools/下 tar -xvf ***
3.修改头文件,否则报错
src/corelib/global/qglobal.h 里添加limits头文件
# include 一定要加在ifdef __cplusplus和endif之间才行
4.修改conf文件
/home/yue/tools/qt-everywhere-src-5.15.3/qtbase/mkspecs/linux-aarch64-gnu-g++/qmake.conf文件 填入自己的交叉编译链
# modifications to g++.conf
QMAKE_CC = /home/yue/sdk/orangepi-build/toolchains/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc
QMAKE_CXX = /home/yue/sdk/orangepi-build/toolchains/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-g++
QMAKE_LINK = /home/yue/sdk/orangepi-build/toolchains/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-g++
QMAKE_LINK_SHLIB = /home/yue/sdk/orangepi-build/toolchains/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-g++

# modifications to linux.conf
QMAKE_AR = /home/yue/sdk/orangepi-build/toolchains/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-ar cqs
QMAKE_OBJCOPY = /home/yue/sdk/orangepi-build/toolchains/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-objcopy
QMAKE_NM = /home/yue/sdk/orangepi-build/toolchains/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-nm -P
QMAKE_STRIP = /home/yue/sdk/orangepi-build/toolchains/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-strip

5.在qt目录下新建autoconfig.sh文件,并添加可执行属性 sudo chmod +x autoconfig.sh

./configure \
-prefix /opt/qt-5.15.3 \
-release \
-feature-library \
-opensource \
-xplatform linux-aarch64-gnu-g++ \
-make libs \
-optimized-qmake \
-no-opengl \
-pch \
-shared \
-qt-libjpeg \
-qt-zlib \
-qt-libpng

6.先清理下
sudo make distclean -j5
7.执行配置文件
sudo ./autoconfig.sh
8.编译
sudo gmake -j5
9.安装
sudo gmake install -j5

10.将库文件拷贝到开发板, 这里使用了部分正点原子的库,如果自己生成需要修改buildroot

cd /opt/atk-dlrk356x-toolchain/aarch64-buildroot-linux-gnu/sysroot/usr/lib/
scp \
libprotobuf.so.16 \
libopencv_gapi.so.405 \
libjpeg.so.62 \
libmali_hook.so.1 \
libopencv_highgui.so.405 \
libopencv_ml.so.405 \
libopencv_objdetect.so.405 \
libopencv_photo.so.405 \
libopencv_stitching.so.405 \
libopencv_video.so.405 \
libopencv_calib3d.so.405 \
libopencv_features2d.so.405 \
libopencv_dnn.so.405 \
libopencv_flann.so.405 \
libopencv_videoio.so.405 \
libopencv_imgcodecs.so.405 \
libopencv_freetype.so.405 \
libopencv_imgproc.so.405 \
libopencv_core.so.405 \
libQt5MultimediaWidgets.so.5 \
libQt5Multimedia.so.5 \
libQt5SerialPort.so.5 \
libopencv_video.so.405 \
libopencv_calib3d.so.405 \
libopencv_imgproc.so.405 \
libopencv_core.so.405 \
libQt5Test.so.5 \
libopencv_imgproc.so.405 \
libopencv_core.so.405 \
libopencv_core.so.405 \
libopencv_dnn.so.405 \
libopencv_calib3d.so.405 \
libopencv_imgproc.so.405 \
libopencv_core.so.405 \
libopencv_imgproc.so.405 \
libopencv_core.so.405 root@192.168.0.107:/usr/lib/aarch64-linux-gnu

cd /opt/qt-5.15.3/lib
sudo scp libQt5Location.so* libQt5Positioning* libQt5QuickTemplates2.so.5 libQt5QuickControls2.so.5 libQt5Concurrent.so.5 root@192.168.0.101:/usr/lib/aarch64-linux-gnu

cd /opt/qt-5.15.3/qml
sudo scp -r QtLocation root@192.168.0.107:/usr/lib/aarch64-linux-gnu/qt5/qml
sudo scp -r QtPositioning root@192.168.0.107:/usr/lib/aarch64-linux-gnu/qt5/qml
sudo scp -r QtQuick root@192.168.0.107:/usr/lib/aarch64-linux-gnu/qt5/qml

cd /opt/qt-5.15.3/plugins
scp -r ./geoservices root@192.168.0.107:/usr/lib/aarch64-linux-gnu/qt5/plugins/

[Qt]串口通信 ,不使用movetothread

—————————.pro—————————-
QT += core gui serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#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

——————————-main.cpp—————————–
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #include
#include

class SerialReceiver : public QObject {
Q_OBJECT

public:
SerialReceiver(QTextEdit *textEdit) : m_serialPort(new QSerialPort), m_textEdit(textEdit) {
// 设置串口设备 ttyUSB0
m_serialPort->setPortName(“/dev/ttyUSB0”);
m_serialPort->setBaudRate(QSerialPort::Baud115200);
m_serialPort->setDataBits(QSerialPort::Data8);
m_serialPort->setParity(QSerialPort::NoParity);
m_serialPort->setStopBits(QSerialPort::OneStop);
m_serialPort->setFlowControl(QSerialPort::NoFlowControl);

connect(m_serialPort, &QSerialPort::readyRead, this, &SerialReceiver::readData);

if (m_serialPort->open(QIODevice::ReadWrite)) {
qDebug() << "Serial port opened."; } else { qDebug() << "Failed to open serial port."; } // 启动定时器,每隔 1 秒发送一次数据 m_timer = new QTimer(this); connect(m_timer, &QTimer::timeout, this, &SerialReceiver::sendData); m_timer->start(1000); // 1 秒间隔
}

public slots:
void readData() {
QByteArray data = m_serialPort->readAll();
// 将接收的数据展示到文本框中
m_textEdit->append(data);
}

void sendData() {
QByteArray dataToSend = “Hello, this is a periodic message!\n”;
qDebug() << "Sending data:" << dataToSend; m_serialPort->write(dataToSend);
}

private:
QSerialPort *m_serialPort;
QTextEdit *m_textEdit;
QTimer *m_timer; // 定时器
};

// 线程函数
void setThreadToCPU3() {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(3, &cpuset); // 将线程绑定到CPU3
pthread_t currentThread = pthread_self();
int result = pthread_setaffinity_np(currentThread, sizeof(cpu_set_t), &cpuset);
if (result != 0) {
qDebug() << "Error setting CPU affinity for thread:" << strerror(result); } else { qDebug() << "Thread is now running on CPU3."; } } class SerialThread : public QThread { public: SerialThread(QTextEdit *textEdit) : m_textEdit(textEdit) {} protected: void run() override { setThreadToCPU3(); // 设置线程在CPU3上运行 SerialReceiver receiver(m_textEdit); // 创建串口接收器 exec(); // 开始事件循环 } private: QTextEdit *m_textEdit; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; QVBoxLayout layout; QLabel label("Serial Data:"); QTextEdit textEdit; textEdit.setReadOnly(true); layout.addWidget(&label); layout.addWidget(&textEdit); window.setLayout(&layout); // 创建一个线程来接收串口数据 SerialThread serialThread(&textEdit); serialThread.start(); window.show(); // 在程序退出前确保线程安全结束 QObject::connect(&app, &QApplication::aboutToQuit, [&serialThread]() { serialThread.quit(); // 结束线程事件循环 serialThread.wait(); // 等待线程完全结束 }); return app.exec(); } #include "main.moc" ----------------------------mainwindow.cpp-------------------------- #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this);
}

MainWindow::~MainWindow()
{
delete ui;
}

————————–mainwindow.h——————————
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

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;
};
#endif // MAINWINDOW_H

[Qt]显示摄像头-4 使用线程

————————.pro——————————-
QT += core gui
QT += core gui widgets # 确保 widgets 模块被包含

CONFIG += link_pkgconfig
PKGCONFIG += opencv4

QT += multimedia multimediawidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
CameraWorker.cpp \
main.cpp \
mainwindow.cpp

HEADERS += \
CameraWorker.h \
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

——————————–CameraWorker.h—————————
#ifndef CAMERAWORKER_H
#define CAMERAWORKER_H

#include
#include
#include
#include
#include

class CameraWorker : public QObject {
Q_OBJECT

public:
CameraWorker(QObject *parent = nullptr);
~CameraWorker();
void startCamera(int deviceIndex);
void stopCamera();

signals:
void frameCaptured(const QImage &image);

private:
cv::VideoCapture capture;
QMutex mutex;
bool isRunning;
void process();
};

#endif // CAMERAWORKER_H

————————-CameraWorker.cpp———————————
#include “CameraWorker.h”
#include // 包含 QDebug 以使用 qDebug()
#include

CameraWorker::CameraWorker(QObject *parent) : QObject(parent), isRunning(false) {}

CameraWorker::~CameraWorker() {
stopCamera();
}

void CameraWorker::startCamera(int deviceIndex) {
if (capture.isOpened()) return;

capture.open(deviceIndex);
if (!capture.isOpened()) {
qDebug() << "无法打开摄像头"; // 这里可以正常使用 qDebug() return; } capture.set(cv::CAP_PROP_FRAME_WIDTH, 640); // 设置宽度 capture.set(cv::CAP_PROP_FRAME_HEIGHT, 480); // 设置高度 capture.set(cv::CAP_PROP_FPS, 15); // 设置帧率 capture.set(cv::CAP_PROP_EXPOSURE, -4); // 设置曝光(根据需要调整) capture.set(cv::CAP_PROP_GAIN, 0); // 设置增益(根据需要调整) QThread::msleep(100); // 暂停以让设置生效 isRunning = true; QThread *thread = QThread::create([this]() { process(); }); connect(thread, &QThread::finished, this, &CameraWorker::deleteLater); thread->start();
}

void CameraWorker::stopCamera() {
QMutexLocker locker(&mutex);
isRunning = false;
capture.release();
}

void CameraWorker::process() {
while (true) {
{
QMutexLocker locker(&mutex);
if (!isRunning) break;
}

cv::Mat frame;
capture >> frame;
if (frame.empty()) continue;

cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
QImage image(frame.data, frame.cols, frame.rows, frame.step[0], QImage::Format_RGB888);
emit frameCaptured(image);
QThread::msleep(33); // 限制帧率
}
}

———————-mainwindow.h—————————————–
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include
#include “CameraWorker.h” // 添加这一行以包含 CameraWorker
#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots:
void updateCameraFrame(const QImage &image);

private:
Ui::MainWindow *ui;
CameraWorker *cameraWorker; // 确保这个声明是正确的
QThread *cameraThread;
};

#endif // MAINWINDOW_H

——————————mainwindow.cpp————————-
#include “mainwindow.h”
#include “ui_mainwindow.h”

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow), cameraWorker(new CameraWorker) {
ui->setupUi(this);

// 创建线程
cameraThread = new QThread;
cameraWorker->moveToThread(cameraThread);

connect(cameraThread, &QThread::started, [this]() {
cameraWorker->startCamera(0); // 打开默认摄像头
});
connect(cameraThread, &QThread::finished, cameraWorker, &CameraWorker::deleteLater);
connect(cameraWorker, &CameraWorker::frameCaptured, this, &MainWindow::updateCameraFrame);

cameraThread->start();
}

MainWindow::~MainWindow() {
cameraThread->quit();
cameraThread->wait();
delete ui;
}

void MainWindow::updateCameraFrame(const QImage &image) {
ui->cameraLabel->setPixmap(QPixmap::fromImage(image)); // 假设你在 UI 中有一个 QLabel 名为 cameraLabel
}

————————–main.cpp——————————
#include “mainwindow.h”
#include

int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

————————-.ui————————————-
添加名为 cameraLabel 的 QLabel 的控件

[Qt]显示USB摄像头3

————————.pro————————————-
QT += core gui
QT += core gui widgets # 确保 widgets 模块被包含

CONFIG += link_pkgconfig
PKGCONFIG += opencv4

QT += multimedia multimediawidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
CameraWidget.cpp \
main.cpp \
mainwindow.cpp

HEADERS += \
CameraWidget.h \
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

———————-CameraWidget.h—————————-
#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H

#include
#include
#include
#include

class CameraWidget : public QWidget {
Q_OBJECT

public:
explicit CameraWidget(QWidget *parent = nullptr);
~CameraWidget();

private slots:
void updateFrame();

private:
QLabel *label; // 用于显示摄像头画面
cv::VideoCapture capture; // OpenCV 摄像头捕获对象
};

#endif // CAMERAWIDGET_H

—————CameraWidget.cpp—————————————-
#include “CameraWidget.h”
#include
#include
#include
#include

CameraWidget::CameraWidget(QWidget *parent) : QWidget(parent) {
QVBoxLayout *layout = new QVBoxLayout(this);
label = new QLabel(this);
layout->addWidget(label);
setLayout(layout);

// 打开摄像头
if (!capture.open(0)) { // 0 为默认摄像头
label->setText(“无法打开摄像头”);
return;
}

// 设置摄像头分辨率和其他属性
capture.set(cv::CAP_PROP_FRAME_WIDTH, 640); // 设置宽度
capture.set(cv::CAP_PROP_FRAME_HEIGHT, 480); // 设置高度
capture.set(cv::CAP_PROP_FPS, 15); // 设置帧率
capture.set(cv::CAP_PROP_EXPOSURE, -4); // 设置曝光(根据需要调整)
capture.set(cv::CAP_PROP_GAIN, 0); // 设置增益(根据需要调整)
QThread::msleep(100); // 暂停以让设置生效

// 设置定时器定时更新摄像头画面
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &CameraWidget::updateFrame);
timer->start(33); // 每 33 毫秒更新一次(约 30 FPS)
}

CameraWidget::~CameraWidget() {
capture.release(); // 释放摄像头资源
}

void CameraWidget::updateFrame() {
cv::Mat frame;
capture >> frame; // 从摄像头获取一帧图像
if (frame.empty()) return;

// 转换为 RGB 格式并显示
cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
QImage image(frame.data, frame.cols, frame.rows, frame.step[0], QImage::Format_RGB888);
label->setPixmap(QPixmap::fromImage(image));
}

—————————-mainwindow.h—————————–
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include “CameraWidget.h”

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;
CameraWidget *cameraWidget; // 摄像头小部件
};

#endif // MAINWINDOW_H

—————————-mainwindow.cpp—————————
#include “mainwindow.h”
#include “ui_mainwindow.h”
#include

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);

// 创建并设置摄像头小部件
cameraWidget = new CameraWidget(this);

// 将摄像头小部件添加到布局
QWidget *cameraContainer = ui->cameraContainer; // 确保在 .ui 文件中设置了 cameraContainer
QVBoxLayout *layout = new QVBoxLayout(cameraContainer);
layout->addWidget(cameraWidget);
}

MainWindow::~MainWindow() {
delete ui;
}

———————-main.cpp—————————————-
#include
#include “mainwindow.h”

int main(int argc, char *argv[]) {
QApplication app(argc, argv); // 创建 QApplication 对象

MainWindow mainWindow; // 创建主窗口对象
mainWindow.show(); // 显示主窗口

return app.exec(); // 进入应用程序主事件循环
}

————————-ui————————————
新建个名字为 cameraContainer 的QWidget控件

[Qt]使用opencv显示摄像头

——————.pro——————————
QT += core gui
QT += core gui widgets # 确保 widgets 模块被包含

CONFIG += link_pkgconfig
PKGCONFIG += opencv4

QT += multimedia multimediawidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
CameraWidget.cpp \
main.cpp \
mainwindow.cpp

HEADERS += \
CameraWidget.h \
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
————————————-CameraWidget.h————————
#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H

#include
#include
#include
#include
#include

class CameraWidget : public QWidget {
Q_OBJECT

public:
explicit CameraWidget(QWidget *parent = nullptr);

private slots:
void updateFrame();

private:
QLabel *label;
cv::VideoCapture capture;
};

#endif // CAMERAWIDGET_H
—————————————–CameraWidget.cpp—————–
#include “CameraWidget.h”
#include
#include
#include
#include
#include
#include

CameraWidget::CameraWidget(QWidget *parent) : QWidget(parent) {
// 创建布局和标签
QVBoxLayout *layout = new QVBoxLayout(this);
label = new QLabel(this);
layout->addWidget(label);
setLayout(layout);

// 打开摄像头
if (!capture.open(0)) {
label->setText(“无法打开摄像头”);
return;
}

// 设置摄像头分辨率和其他属性
capture.set(cv::CAP_PROP_FRAME_WIDTH, 640); // 设置宽度
capture.set(cv::CAP_PROP_FRAME_HEIGHT, 480); // 设置高度
capture.set(cv::CAP_PROP_FPS, 15); // 设置帧率
capture.set(cv::CAP_PROP_EXPOSURE, -4); // 设置曝光(根据需要调整)
capture.set(cv::CAP_PROP_GAIN, 0); // 设置增益(根据需要调整)
QThread::msleep(100); // 暂停以让设置生效

// 检查实际分辨率
int width = capture.get(cv::CAP_PROP_FRAME_WIDTH);
int height = capture.get(cv::CAP_PROP_FRAME_HEIGHT);
qDebug() << "当前分辨率:" << width << "x" << height; // 设置定时器定时更新摄像头画面 QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &CameraWidget::updateFrame); timer->start(20); // 每 5 毫秒更新一次
}

void CameraWidget::updateFrame() {
if (!capture.isOpened()) {
qDebug() << "摄像头未打开"; return; } cv::Mat frame; capture >> frame; // 从摄像头获取一帧图像
if (frame.empty()) {
qDebug() << "获取的帧为空"; return; } // 转换为 RGB 格式并显示 cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); QImage image(frame.data, frame.cols, frame.rows, frame.step[0], QImage::Format_RGB888); label->setPixmap(QPixmap::fromImage(image));
}

—————————mainwindow.h———————————
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

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;
};
#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);

}

MainWindow::~MainWindow()
{
delete ui;
}

—————————-main.cpp————————————–
#include
#include “CameraWidget.h”

int main(int argc, char *argv[]) {
QApplication app(argc, argv);
CameraWidget cameraWidget;
cameraWidget.setWindowTitle(“USB 摄像头画面”);
cameraWidget.resize(640, 480);
cameraWidget.show();
return app.exec();
}

[Qt]使用opencv读取摄像头并显示

—————————-.pro—————————-
QT += core gui
QT += core gui widgets # 确保 widgets 模块被包含

CONFIG += link_pkgconfig
PKGCONFIG += opencv4

QT += multimedia multimediawidgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
CameraWidget.cpp \
main.cpp \
mainwindow.cpp

HEADERS += \
CameraWidget.h \
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

——————-CameraWidget.h————————
#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H

#include
#include
#include
#include
#include

class CameraWidget : public QWidget {
Q_OBJECT

public:
explicit CameraWidget(QWidget *parent = nullptr);

private slots:
void updateFrame();

private:
QLabel *label;
cv::VideoCapture capture;
};

#endif // CAMERAWIDGET_H
————————————CameraWidget.cpp————————
#include “CameraWidget.h”

CameraWidget::CameraWidget(QWidget *parent) : QWidget(parent) {
// 创建布局和标签
QVBoxLayout *layout = new QVBoxLayout(this);
label = new QLabel(this);
layout->addWidget(label);
setLayout(layout);

// 打开摄像头
capture.open(0); // 0 表示默认摄像头
if (!capture.isOpened()) {
label->setText(“无法打开摄像头”);
return;
}

// 设置定时器定时更新摄像头画面
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &CameraWidget::updateFrame);
timer->start(10); // 每 30 毫秒更新一次
}

void CameraWidget::updateFrame() {
cv::Mat frame;
capture >> frame; // 从摄像头获取一帧图像
if (frame.empty()) return;

// 转换为 RGB 格式并显示
cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
QImage image(frame.data, frame.cols, frame.rows, frame.step[0], QImage::Format_RGB888);
label->setPixmap(QPixmap::fromImage(image));
}
———————-mainwindow.h——————————
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

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;
};
#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);

}

MainWindow::~MainWindow()
{
delete ui;
}

————————–main.cpp—————————————
#include
#include “CameraWidget.h”

int main(int argc, char *argv[]) {
QApplication app(argc, argv);
CameraWidget cameraWidget;
cameraWidget.setWindowTitle(“USB 摄像头画面”);
cameraWidget.resize(640, 480);
cameraWidget.show();
return app.exec();
}

[Qt]点击输入框弹出键盘

———————-*.pro———————————
QT += core gui
QT += virtualkeyboard

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#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

—————————–mainwindow.h——————————-
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

protected:
bool eventFilter(QObject *obj, QEvent *event) override; // 事件过滤器

private:
Ui::MainWindow *ui;

private slots:
void showKeyboard(); // 点击输入框时显示键盘
};

#endif // MAINWINDOW_H

—————————–mainwindow.cpp——————————–
#include “mainwindow.h”
#include “ui_mainwindow.h”
#include
#include
#include

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);

// 安装事件过滤器
ui->lineEdit->installEventFilter(this);
this->setFocus(); // 将焦点设置到主窗口
}

MainWindow::~MainWindow()
{
delete ui;
}

// 实现事件过滤器
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->lineEdit && event->type() == QEvent::FocusIn) {
showKeyboard(); // 点击输入框时显示键盘
}
return QMainWindow::eventFilter(obj, event);
}

void MainWindow::showKeyboard()
{
QGuiApplication::inputMethod()->show(); // 显示虚拟键盘
}

—————————–main.cpp—————————————
#include
#include
#include “mainwindow.h”

int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
qputenv(“QT_IM_MODULE”, QByteArray(“qtvirtualkeyboard”));
qputenv(“QT_VIRTUALKEYBOARD_LANGUAGE”, QByteArray(“fr_FR”)); // 法语
qputenv(“QT_VIRTUALKEYBOARD_LANGUAGE”, QByteArray(“de_DE”)); // 德语

QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

————————*.ui—————————————————-
添加 lineEdit