阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

用 Qt 给嵌入式Linux加个桌面

328次阅读
没有评论

共计 3634 个字符,预计需要花费 10 分钟才能阅读完成。

导读 今天给大家分享一下:如何用 Qt 实现一个 launcher (程序启动器)。代码很少,C++ 部分大约 100 行代码。

下面是实现过程。

1. 创建 QML 应用

在 Qt Creator 依次点击:-> File -> New File or Project-> Applications -> Qt Quick Application

用 Qt 给嵌入式 Linux 加个桌面

然后一路点击 next 直到 finish。

2. 解析配置文件

Linux 系统里安装过的应用,都会在 /usr/share/applications 目录下有相应的配置文件,用于说明如何启动该应用,如下:

# ls -1X /usr/share/applications/
apport-gtk.desktop
apturl.desktop
arduino.desktop
audacity.desktop
bcompare.desktop
...

以 bcompare.desktop 为例:

[Desktop Entry]
Name=Beyond Compare
Exec=bcompare
Icon=bcompare
...

字段含义:

Name 字段是应用的名称,

Exec 字段是应用的启动命令,

Icon 字段是应用的图标名称,

解析配置文件:

// 文件:main.cpp

QVariantList apps()
{
    QVariantList ret;
    QDirIterator it(DESKTOP_FILE_SYSTEM_DIR, ...);

    while (it.hasNext()) {const auto filename = it.next();
        QSettings desktopFile(filename, QSettings::IniFormat);
        
        // 定位到 [Desktop Entry]
        desktopFile.beginGroup(DESKTOP_ENTRY_STRING);

        // 提取 app 信息
        AppInfo app;
        app.exec = desktopFile.value("Exec").toString().remove("\"").remove(QRegExp("%."));
        app.icon = desktopFile.value("Icon").toString();
        app.name = desktopFile.value("Name").toString();

        // 保存 app 信息
        ret.append(QStringList{app.name, app.icon, app.exec});
    }
    return ret;
}

int main(int argc, char *argv[])
{[...]
    // 将解析到的 app 信息传递给 QML 前端
    engine.rootContext()->setContextProperty("apps", apps());
    [...]
}

核心就是遍历某个目录下的所有文件,解析配置文件的工作则由 QSettings 负责。

运行效果:

// 打印出所有的 app 启动信息

exec:  "xpad" 
icon:  "xpad" 
name:  "Xpad"
[...]
3. 实现整体布局

我们通过 SwipeView 来实现滑动翻页的功能,参考我之前的文章:《Qt 官方示例 | 这几个 QML 版的 HelloWorld 你学会了吗?》至于单独一页的布局,我们可以使用 Repeater 这个控件。Repeater 可以帮我们生成重复的内容,这里我们规定一页最多显示 24 个 app。

通过 SwipeView + Repeater 实现布局:

// 文件: main.qml

SwipeView {[...]
        property int selectedIndex: 0
        Repeater {
            id: pageRepeater
            model: appPages.length

            Item {property var page: appPages[index]
                Grid {
                    columns: 6
                    Repeater {
                        model: page.length

                        Image {source: "qrc:/images/qtlogo.png"}
                    }
                }
            }
        }
    }

第一个 Repeater 用于实现生成所有的页面,

第二个 Repeater 用于生成页面里的所有 APP 的图标,这里我们先用 Qt 的 logo 来代替真实的 APP 图标。

运行效果:

用 Qt 给嵌入式 Linux 加个桌面

这时候已经支持左右滑动了,但是还没填入 APP 信息。

4. 支持显示应用图标

在 main() 里,我们设置了一个名为 apps 的属性,它包含了所有 APP 的信息:

engine.rootContext()->setContextProperty("apps", apps());

我们需要在前端界面中使用 APP 的图标替换掉 Qt logo。

显示 APP 图标:

// 文件:main.qml

Grid {[...]
    Repeater {
        model: page !== undefined ? page.length : 0

        Column {
            Image {property var app: page[index]
                // APP 图标
                source: "image://icons/" + app[1]
                [...]
            }

            Label {property var app: page[index]
                id: label
                // APP 的名称
                text: app[0]
                [...]
            }
        }
    }
}

改动非常少。

运行效果:

用 Qt 给嵌入式 Linux 加个桌面

这时仅支持显示图标,但是仍不支持鼠标选中。

5. 支持选中应用

选中应用需要添加对鼠标 hover 事件的处理。当鼠标移动到某个图标上时,Qt 会捕获到鼠标 hover 事件,并传递给当前焦点所在的控件上。我们将 APP 的界面代码抽取出来,单独放在 AppEntry.qml,使其成为一个独立的控件,然后再在其中添加对鼠标 hover 事件的处理。

图标控件:AppEntry.qml

/// 文件:AppEntry.qml 

Pane {
    id: root
    property var app
    [...]

    // 当鼠标移动到该图标时,发送信号 hovered()
    signal hovered()
    MouseArea {[...]
        onHoveredChanged: {if (hovered) {root.hovered()
            }
        }
    }

    Column {
        anchors.fill: parent

        Image {source: "image://icons/" + app[1]
            [...]
        }

        Label {[...]
        }
    }
}

在 main.qml 中接受到 AppEntry 控件的 hovered 信号时,需改变其背景色以提示用户已选中图标。

// 文件:main.qml

Repeater {
    model: page.length

    AppEntry {app: page[index]
        [...]
        // selected 改变时,背景色会变化
        selected: swipeView.selectedIndex === index
        onHovered: {swipeView.select(index)
        }
        [...]
    }
}

运行效果:

用 Qt 给嵌入式 Linux 加个桌面

这是已经能显示选中状态了,但是仍无法启动应用。

6. 支持启动应用

在 Qt 里,可以使用 QProcess 来创建进程。这里我们创建一个 QProcess 的子类用于运行 APP。

QProcess 的子类:

// 文件:process.cpp
void Process::start(const QString &program, const QVariantList &arguments)
{[...]
    QProcess::startDetached(program);
}

// 文件:process.h
class Process : public QProcess
{
    Q_OBJECT

public:
    Process(QObject *parent = nullptr);

    Q_INVOKABLE void start(const QString &program, const QVariantList &arguments = {});
};

// 文件:main.cpp
int main(int argc, char *argv[])
{
    // 将 Process 的实例传递给前端
    engine.rootContext()->setContextProperty("proc", new Process(&engine));
}

前端处理点击事件:

// 文件:AppEntry.qml

signal clicked()
MouseArea {[...]
    onClicked: {root.clicked()
    }
}

当用户点击图标时,AppEntry 控件会发出 clicked() 信号。

// 文件:main.qml

AppEntry {app: page[index]
    [...]
    // 主窗口启动 APP
    onClicked: {exec(app[2])
    }
    [...]
}

function exec(program) {console.debug("Exec:" + program)
    proc.start(program)
    Qt.quit();}

最后调用到 Process::start(),启动 APP。

运行效果:

用 Qt 给嵌入式 Linux 加个桌面

怎么样,你们学会了吗?

—— The End ——

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-07-25发表,共计3634字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19348
评论数
4
阅读量
7801149
文章搜索
热门文章
开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南 大家好,我是星哥。之前介绍了腾讯云的 Code...
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板 1Panel:小白轻松构建 Web 服务与面板加固指南 哈喽,我是星哥,经常有人问我不...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

  4 盘位、4K 输出、J3455、遥控,NAS 硬件入门性价比之王 开篇 在 NAS 市场中,威...
星哥带你玩飞牛NAS-7:手把手教你免费内网穿透-Cloudflare tunnel

星哥带你玩飞牛NAS-7:手把手教你免费内网穿透-Cloudflare tunnel

星哥带你玩飞牛 NAS-7:手把手教你免费内网穿透 -Cloudflare tunnel 前言 大家好,我是星...
告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

  告别 Notion 焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁” 引言 在数字笔记工...
三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

  三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Andr...
Python自学26 – Cookie和Session

Python自学26 – Cookie和Session

Python 自学 26 – Cookie 和 Session 在学习 Web 开发时,Cooki...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

  告别 Notion 焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁” 引言 在数字笔记工...
如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的 Nano Banana Pro?附赠邪修的用法 前言 大家好,我是星哥,今天来介绍谷歌的 ...
每年0.99刀,拿下你的第一个顶级域名,详细注册使用

每年0.99刀,拿下你的第一个顶级域名,详细注册使用

每年 0.99 刀,拿下你的第一个顶级域名,详细注册使用 前言 作为长期折腾云服务、域名建站的老玩家,星哥一直...
颠覆 AI 开发效率!开源工具一站式管控 30+大模型ApiKey,秘钥付费+负载均衡全搞定

颠覆 AI 开发效率!开源工具一站式管控 30+大模型ApiKey,秘钥付费+负载均衡全搞定

  颠覆 AI 开发效率!开源工具一站式管控 30+ 大模型 ApiKey,秘钥付费 + 负载均衡全...
星哥带你玩飞牛NAS-11:咪咕视频订阅部署全攻略

星哥带你玩飞牛NAS-11:咪咕视频订阅部署全攻略

星哥带你玩飞牛 NAS-11:咪咕视频订阅部署全攻略 前言 在家庭影音系统里,NAS 不仅是存储中心,更是内容...