知识网经验知识百科全书!
登录

如何在Visual「如何在visio中写公式」

140次浏览 | 2022-10-04 00:20:11 更新
来源 :一只小猪
最佳经验
本文由作者推荐

在上文中(如何用Visual Studio创建一个嵌入式应用?Qt框架有妙招!(一)),我们展示了如何在Visual Studio中针对Windows和嵌入式Linux创建多..Qt Quick应用程序项目。现在,我们将演示如何在嵌入式设备上运行该应用程序。然后,我们将继续开发该项目,实现预定的完整嵌入式应用程序。最后,我们将使用VS调试器对应用的C ++和QML代码进行远程调试。

在嵌入式设备上运行

我们已经演示了如何交叉编译在Visual Studio中创建的“hello world” Qt Quick应用程序。现在,我们将看到如何在树莓派上运行该应用程序。由于我们将以全屏模式运行,因此必须首先在应用程序窗口中添加一些内容。

main.qmlWindow {visible: truetitle: qsTr("Hello World")Text {id: clockfont.pointSize: 72Timer {interval: 1000; running: true; repeat: trueonTriggered: clock.text = (new Date).toLocaleTimeString(Qt.locale("de_DE"), "hh:mm:ss");}}}

Qt Quick "Hello World"

和以前一样,选择Linux项目配置,然后按F7键开始交叉编译。

Visual Studio构建输出

1u0026gt;------ Build started: Project: QuickMirror, Configuration: Debug_RPi x64 ------1u0026gt;rcc qml.qrc1u0026gt;Invoking u0026#39;mkdir -p $(dirname qml.qrc); mkdir -p $(dirname /mnt/c/Users/user/Source/Repos/QuickMirror/main.qml); mkdir -p $(dirname /mnt/c/Users/user/Source/Repos/QuickMirror/obj/x64/Debug_RPi/rcc/qrc_qml.cpp); (/home/user/raspi/qt5/bin/rcc /mnt/c/Users/user/Source/Repos/QuickMirror/qml.qrc --name qml -o /mnt/c/Users/user/Source/Repos/QuickMirror/obj/x64/Debug_RPi/rcc/qrc_qml.cpp)u0026#39;, working directory: u0026#39;/mnt/c/Users/user/Source/Repos/QuickMirroru0026#39;1u0026gt;Starting remote build1u0026gt;Compiling sources:1u0026gt;qrc_qml.cpp1u0026gt;Linking objects1u0026gt;QuickMirror.vcxproj -u0026gt; C:UsersuserSourceReposQuickMirrorbinx64Debug_RPiQuickMirror.out========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

VS中交叉编译Qt项目

现在我们把应用程序的二进制文件上传到树莓派。构建输出窗口显示了生成的二进制文件的位置(倒数第二行)。

Windows命令提示

C:Usersuseru0026gt; scp C:UsersuserSourceReposQuickMirrorbinx64Debug_RPiQuickMirror.out pi@192.168.1.98:/home/pi/pi@192.168.1.98u0026#39;s password:QuickMirror.out 100% 465KB 1.6MB/s 00:00C:Usersuseru0026gt;

将应用程序二进制文件上传到目标设备

要在为了在每次构建结束时自动复制应用程序文件,可以在“ WSL Post-Build Event”属性页中设置如下命令(注意: 这将以明文形式保存设备密码)

Project Properties u0026gt; WSL Post-Build Event u0026gt; Command Line

curl --insecure --user pi:u0026lt;passwordu0026gt; -T /mnt/$(TargetPath.Replace(u0026#39;u0026#39;,u0026#39;/u0026#39;).Replace(u0026#39;:u0026#39;,u0026#39;u0026#39;).ToLower()) scp://u0026lt;device-addru0026gt;/home/pi/$(TargetFileName)

在每次构建结束时将二进制文件复制到设备端

在启动Qt Quick应用程序之前,我们需要设置一些必需的环境变量:

  • LD_LIBRARY_PATH: Qt二进制文件安装的路径。
  • QT_QPA_PLATFORM:QPA..插件。
  • QT_QPA_PLATFORM_PLUGIN_PATH:QPA..插件安装的路径。
  • QT_QPA_EGLFS_PHYSICAL_WIDTH、QT_QPA_EGLFS_PHYSICAL_HEIGHT:物理屏幕的宽度和高度,以毫米为单位。
  • QML2_IMPORT_PATH:安装的QML模块的路径。

树莓派命令外壳

pi@raspberry-pi:~$ export LD_LIBRARY_PATH="/usr/local/qt5pi/lib"pi@raspberry-pi:~$ export QT_QPA_PLATFORM="eglfs"pi@raspberry-pi:~$ export QT_QPA_PLATFORM_PLUGIN_PATH="/usr/local/qt5pi/plugins/platforms"pi@raspberry-pi:~$ export QT_QPA_EGLFS_PHYSICAL_WIDTH="326"pi@raspberry-pi:~$ export QT_QPA_EGLFS_PHYSICAL_HEIGHT="520"pi@raspberry-pi:~$ export QML2_IMPORT_PATH="/usr/local/qt5pi/qml"pi@raspberry-pi:~$ ./QuickMirror.out

树莓派显示器

如何在Visual「如何在visio中写公式」

在树莓派上运行“ Hello World”应用程序

应用程序开发过程

应用程序的要求包括显示以下信息:

  • 当前时间
  • 当前日期
  • 重要公共纪念日
  • 天气预报
  • 下一班公共交通工具
  • 新闻

我们将把每个功能项封装为独立的QML类型。为此,我们必须首先将QML模块定义(qmldir)文件添加到项目中:

  • 选择"Project u0026gt; Add New Item.. u0026gt; Qt u0026gt; QML Module Definition"。
  • 在位置字段中,设置包含QML文件的文件夹路径。
如何在Visual「如何在visio中写公式」

向项目添加新的QML模块定义

按下“Add”后,qmldir 文件将在项目树中变为可用。我们将使用此文件来映射每种QML类型到其对应的源文件。

如何在Visual「如何在visio中写公式」

将QML类型映射到源文件

将新的QML源文件添加到项目中:

  • 选择“Project u0026gt; Add New Item... u0026gt; Qt u0026gt; QML File"”。
  • 将位置设置为qmldir同级目录。
  • 设置QML文件名。
  • 按“Add”。
如何在Visual「如何在visio中写公式」

向项目添加新的QML文件

我们将首先添加用于显示当前时间、当前日期和重要公共纪念日的QML类型。该Clock类型将显示当前时间,每秒刷新一次。

Text {font.family: FontFamily_Clockfont.styleName: FontStyle_Clockfont.pointSize: 144color: "white"renderType: Text.NativeRenderingantialiasing: falsefunction refresh() {text = (new Date).toLocaleTimeString(Qt.locale("de_DE"), "hh:mm");}Component.onCompleted : refresh();Timer {interval: 1000; running: true; repeat: true onTriggered: parent.refresh();}}

Clock QML类型的定义

该Calendar类型将显示当前日期,并在不同城市名之间循环。

Text {renderType: Text.NativeRenderingid: calendarcolor: "white"font.family: FontFamily_Boldfont.styleName: FontStyle_Boldfont.pointSize: 72property var locales: ["en_US", "de_DE", "pt_PT"]property var localeIdx: 0function capitalize(s) {return s.replace(/(^|-)./g, function(c) { return c.toUpperCase(); });}function setNextLocale() {localeIdx = (localeIdx + 1) % locales.length;}function getCurrentText() {var date = new Date;var locale = Qt.locale(locales[localeIdx]);var calendarText = capitalize(date.toLocaleDateString(locale, "dddd, dd"));var monthShort = date.toLocaleDateString(locale, "MMM");var monthLong = date.toLocaleDateString(locale, "MMMM");if (monthLong.length u0026lt;= 5) {calendarText += capitalize(monthLong);} else {calendarText += capitalize(monthShort);if (!monthShort.endsWith("."))calendarText += ".";}calendarText += date.toLocaleDateString(locale, " yyyy");return calendarText;}Component.onCompleted: {text = getCurrentText();}Timer {interval: 15000; running: true; repeat: trueonTriggered: {setNextLocale();text = getCurrentText();}}Behavior on text {SequentialAnimation {NumberAnimation { target: calendar; property: "opacity"; to: 0.0; duration: 1000 }PropertyAction { target: calendar; property: "text" }NumberAnimation { target: calendar; property: "opacity"; to: 1.0; duration: 500 }}}}

Calendar QML类型的定义

除了日期/时间,我们的应用程序还将依靠Web API来检索信息。我们将在一个单独的进程中运行curl以连接到Web API。进程创建由名为Process的C ++类处理。然后,QML类型ApiCall将通过一个Process对象传送必要的参数运行curl并收集其输出。

Item {property var url: ""property var path: []property var query: []signal response(var response)signal error(var error)Process {id: curlproperty var path: Q_OS_WIN ? "C:WindowsSystem32curl.exe" : "/usr/bin/curl"property var request: ""command: path + " -s "" + request + """}function sendRequest() {curl.request = url;if (path.length u0026gt; 0)curl.request += "/" + path.join("/");if (query.length u0026gt; 0)curl.request += "?" + query.join("u0026");curl.start();}Connections {target: curlonExit /*(int exitCode, QByteArray processOutput)*/ : {if (exitCode != 0) {console.log("ApiCall: exit " + exitCode);console.log("==== ApiCall: request: " + curl.request);return error("exit " + exitCode);}try {return response(JSON.parse(processOutput));} catch (err) {console.log("ApiCall: error: " + err.toString());console.log("==== ApiCall: request: " + curl.request);console.log("==== ApiCall: response: " + processOutput);return error(err);}}}}

ApiCall QML类型的定义

创建Process的C ++类

  • 选择"Project u0026gt; Add Qt Class u0026gt; Qt Class"
  • 将类名设置为Process
  • 按“Add”
如何在Visual「如何在visio中写公式」

向项目添加新的Qt C ++类

Process.h

public:Q_INVOKABLE void start();void setCommand(const QStringu0026 cmd);QString command() const;signals:void commandChanged();void exit(int exitCode, QByteArray processOutput);protected:void onFinished(int exitCode, QProcess::ExitStatus status);void onErrorOccurred(QProcess::ProcessError error);private:QString m_command;};Process.cppProcess(QObject* parent) : QProcess(parent){connect(this, QOverloadu0026lt;int, QProcess::ExitStatusu0026gt;::of(u0026QProcess::finished),this, u0026Process::onFinished);connect(this, u0026QProcess::errorOccurred,this, u0026Process::onErrorOccurred);}Process::~Process(){}void Process::setCommand(const QStringu0026 cmd){if (cmd != m_command) {m_command = cmd;emit commandChanged();}}QString Process::command() const{return m_command;}void Process::start(){if (state() == ProcessState::NotRunning)QProcess::start(m_command);elseqInfo() u0026lt;u0026lt; "==== QProcess: ERROR already running:" u0026lt;u0026lt; m_command;}void Process::onFinished(int exitCode, QProcess::ExitStatus status){emit exit((status == ExitStatus::NormalExit) ? exitCode : -1, readAll());}void Process::onErrorOccurred(QProcess::ProcessError error){qInfo() u0026lt;u0026lt; "==== QProcess: ERROR " u0026lt;u0026lt; error;}main.cppint main(int argc, char* argv[]){qmlRegisterTypeu0026lt;Processu0026gt;("Process", 1, 0, "Process");...

Process类的定义

OnThisDay QML类型将使用ApiCall的实例来获取重要公共纪念日列表,并每隔几秒钟循环一次。

QuickMirror.OnThisDay.qml

Item {id: onThisDayclip: trueproperty int viewportHeightproperty var events: []property var births: []property var deaths: []property int idxEventType: -1ApiCall {id: onThisDayApiproperty int month: 0property int day: 0property string eventType: ""url: "https://byabbe.se"; path: ["on-this-day", month, day, eventType + ".json" ]onResponse: {if ("events" in response) {events = shuffle(response.events);eventType = "births";sendRequest();} else if ("births" in response) {births = shuffle(response.births);for (var i in births)births[i].year = "*" + births[i].year;eventType = "deaths";sendRequest();} else if ("deaths" in response) {deaths = shuffle(response.deaths);for (var i in deaths)deaths[i].year = "u0026lt;supu0026gt;†u0026lt;/supu0026gt;" + deaths[i].year;next();}}}function init() {events = [];births = [];deaths = [];idxEventType = -1;var today = new Date;onThisDayApi.month = today.getMonth() + 1;onThisDayApi.day = today.getDate();onThisDayApi.eventType = "events";onThisDayApi.sendRequest();}function next() {if (events.length + births.length + deaths.length == 0)return;var today = new Date;if (onThisDayApi.month != today.getMonth() + 1 || onThisDayApi.day != today.getDate())return init();onThisDayText.color = "white";idxEventType = (idxEventType + 1) % 3;var event;switch (idxEventType) {case 0:if (events.length == 0)return next();event = events.shift();events = shuffle(events);events.push(event);break;case 1:if (births.length == 0)return next();event = births.shift();births = shuffle(births);births.push(event);break;case 2:if (deaths.length == 0)return next();event = deaths.shift();deaths = shuffle(deaths);deaths.push(event);break;}onThisDayText.text = event.year + " – " + event.description;showText.start();}Component.onCompleted: {init();}Timer {id: timerRetryinterval: 10000; running: true; repeat: trueonTriggered: {if (events.length + births.length + deaths.length == 0)init();}}SequentialAnimation {id: showTextPropertyAction { target: onThisDayText; property: "y"; value: 25 }NumberAnimation { target: onThisDayText; property: "opacity"; to: 1.0; duration: 500 }PauseAnimation { duration: 3000 }NumberAnimation {target: onThisDayTextproperty: "y"to: Math.min(-(25 + onThisDayText.contentHeight) + viewportHeight, 25)duration: Math.max(0, (Math.abs(to - from) * 1000) / 25)}PauseAnimation { duration: 3000 }NumberAnimation { target: onThisDayText; property: "opacity"; to: 0.0; duration: 1000 }onFinished: {onThisDay.next();}}Text {renderType: Text.NativeRenderingid: onThisDayTextwrapMode: Text.WordWrapfont.family: FontFamily_Normalfont.styleName: FontStyle_Normalfont.pointSize: 40textFormat: Text.RichTextcolor: "white"y: 25anchors.left: parent.leftwidth: parent.widthheight: contentHeightopacity: 0}Rectangle {id: topanchors.top: parent.topanchors.left: parent.leftwidth: parent.widthheight: 10gradient: Gradient {orientation: Gradient.VerticalGradientStop { position: 0.0; color: "black" }GradientStop { position: 0.5; color: "transparent" }}}Rectangle {id: bottomFadeanchors.top: parent.topanchors.topMargin: viewportHeightanchors.left: parent.leftwidth: parent.widthheight: 0.1 * viewportHeightgradient: Gradient {orientation: Gradient.VerticalGradientStop { position: 0.0; color: "transparent" }GradientStop { position: 0.5; color: "black" }}}Rectangle {anchors.top: bottomFade.bottomanchors.bottom: parent.bottomanchors.left: parent.leftwidth: parent.widthcolor: "black"}}

现在,我们已经定义了一些应用程序的QML类型,我们将在主QML文件上组织它们。

main.qml

import "QuickMirrorTypes"Window {visible: truetitle: qsTr("Quick Mirror")Flickable {anchors.fill: parentcontentWidth: mirror.widthcontentHeight: mirror.heightRectangle {id: mirrorwidth: 1080height: 1920color: "black"Clock {id: clockanchors.top: mirror.topanchors.left: mirror.left}Calendar {id: calendaranchors.top: clock.bottomanchors.topMargin: -20anchors.left: mirror.left}Rectangle {anchors.top: calendar.bottomanchors.topMargin: -5anchors.left: mirror.leftwidth: 800height: 2color: "white"}OnThisDay {id: onThisDayanchors.top: calendar.bottomanchors.left: mirror.leftanchors.leftMargin: 10anchors.bottom: mirror.bottomwidth: 780viewportHeight: 260}}}}

最后,所有QML文件和qmldir文件必须添加到应用程序的资源文件中:

  • 双击项目树中的QRC文件
  • 在“Qt Resource Editor”窗口中,按“Add u0026gt; Add Files”
  • 选择所有QML文件和qmldir文件
  • 在Qt Resource Editor中按“Save”
如何在Visual「如何在visio中写公式」

QML文件和qmldir已添加到资源文件

构建和部署后,我们将能启动应用程序并查看显示的信息。

如何在Visual「如何在visio中写公式」

在树莓派上运行的应用程序

在Visual Studio中进行调试

VS支持通过gdb调试运行在WSL上的应用程序。要在树莓派上运行过程中调试,我们将使用gdbserver启动应用程序,然后配置gdb连接到设备并启动远程调试会话。

如何在Visual「如何在visio中写公式」

使用gdb 和gdbserver从Visual Studio进行远程调试

为此, WSL中安装的gdb组件必须支持目标设备体系架构。一个简单的方法是安装gdb-multiarch。为了确保VS使用正确的调试器,我们将创建一个符号链接,把gdb映射到gdb-multiarch。我们将创建从gdbgdb-multiarch的符号链接。

如何在Visual「如何在visio中写公式」

在Visual Studio中设置远程调试会话,必须向gdb传递两个附加命令。在“GDB Debugger”属性页面中进行配置。

Project Properties u0026gt; Debugging u0026gt; Additional Debugger Commands

target extended-remote 192.168.1.98:2345
set remote exec-file /home/pi/QuickMirror.out

如何在Visual「如何在visio中写公式」

在开始远程调试会话之前,我们必须设置所需的环境变量并在设备上启动gdbserver

Raspberry Pi Command Shell

pi@raspberry-pi:~$ export LD_LIBRARY_PATH="/usr/local/qt5pi/lib"pi@raspberry-pi:~$ export QT_QPA_PLATFORM="eglfs"pi@raspberry-pi:~$ export QT_QPA_PLATFORM_PLUGIN_PATH="/usr/local/qt5pi/plugins/platforms"pi@raspberry-pi:~$ export QT_QPA_EGLFS_PHYSICAL_WIDTH="326"pi@raspberry-pi:~$ export QT_QPA_EGLFS_PHYSICAL_HEIGHT="520"pi@raspberry-pi:~$ export QML2_IMPORT_PATH="/usr/local/qt5pi/qml"pi@raspberry-pi:~$ gdbserver --once --multi :2345Listening on port 2345

按F5将启动远程调试会话。

如何在Visual「如何在visio中写公式」

远程QML调试

在嵌入式设备上运行应用程序时,也可以调试QML代码。

  • 在Qt设置中启用QML调试:Project Properties u0026gt; Qt Project Settings
如何在Visual「如何在visio中写公式」

  • 设置应用程序启动参数,启动QML调试会话
  • 设置启动QML调试会话的程序参数

Project Properties u0026gt; Debugging u0026gt; Program Arguments

-qmljsdebugger=port:8989,host:192.168.1.98,block

如何在Visual「如何在visio中写公式」

总结

我们展示了如何使用Qt VS Tools扩展在Visual Studio中创建基于Qt Quick技术的多..嵌入式应用程序。包括:

  • 从头开始创建Qt Quick项目
  • 用QML编写应用程序代码
  • 交叉编译应用程序
  • 在嵌入式设备上部署和运行
  • 在Visual Studio中对C ++和QML代码进行远程调试

该项目,包括所有源代码,可在https://github.com/micosta/quickmirror获得。

如何在Visual「如何在visio中写公式」

运行在嵌入式设备上的应用程序

本文转载自Qt中国

本文到此结束,希望对大家有所帮助。

标签:
收到0个赞
迅捷斥候天赋(迅捷斥候技能)

迅捷斥候天赋(迅捷斥候技能)

大家好,一只小美来为大家解答迅捷斥候
小米3s价格(小米3s多少钱一部)

小米3s价格(小米3s多少钱一部)

大家好,小乐来为大家解答小米3s价格以
网页图片看不到(网页有的图片显示不出来)

网页图片看不到(网页有的图片显示不出来)

关于网页图片看不到,这个很多人还不知
七龙珠电光火石3怎么放大招(七龙珠电光火石三出招表)

七龙珠电光火石3怎么放大招(七龙珠电光火石三出招表)

大家好,小乐来为大家解答七龙珠电光火
诺基亚c102i可以主动存储(诺基亚的内存卡槽在哪)

诺基亚c102i可以主动存储(诺基亚的内存卡槽在哪)

大家好,来来为大家解答诺基亚c102i可以
日服英雄联盟配音(lol日服配音表2020)

日服英雄联盟配音(lol日服配音表2020)

大家好,一只小美来为大家解答日服英雄
small函数(small函数是什么意思)

small函数(small函数是什么意思)

夏团来为大家解答small函数以下的问题,
华为g700评测(华为g700u00参数)

华为g700评测(华为g700u00参数)

关于华为g700评测,这个很多人还不知道,
主公莫慌礼包(主公莫慌官网网易)

主公莫慌礼包(主公莫慌官网网易)

夏团来为大家解答主公莫慌礼包以下的问
关于我们 | 版权声明 | 免责声明 | 联系我们
免责声明:知识网所有文字、图片、视频、音频等资料均来自互联网,不代表本站赞同其观点,内容仅代表作者本人意见,若因此产生任何纠纷作者本人负责,本站亦不为其版权负责! 如有问题,请联系我们
CopyRight©1999-2024 www.44jj.com All Right Reserved 豫ICP备16009659号