今天和大家分享一下:如何用Qt实现一个launcher(程序启动器)。运行效果:github链接:https://github.com/alamminsal...代码很少,C++部分大概100行代码。下面是实现过程。1.创建QML应用程序在QtCreator中点击:->文件->新建文件或项目->应用程序->QtQuick应用程序点击下一步直到完成。2、分析配置文件Linux系统中安装的应用程序在/usr/share/applications目录下会有一个对应的配置文件来说明如何启动应用程序,如下:#ls-1X/usr/share/applications/apport-gtk.desktopapturl.desktoparduino.desktopaudacity.desktopbcompare.desktop...以bcompare.desktop为例:[DesktopEntry]Name=BeyondCompareExec=bcompareIcon=bcompare...字段含义:Name字段为应用程序的名称,Exec字段是应用程序的启动命令,Icon字段是应用程序的图标名称,解析配置文件://file:main.cppQVariantListapps(){QVariantListret;QDirIteratorit(DESKTOP_FILE_SYSTEM_DIR,...);while(it.hasNext()){constauto文件名=it.next();QSettings桌面文件(文件名,QSettings::IniFormat);//定位到[桌面条目]desktopFile.beginGroup(DESKTOP_ENTRY_STRING);//提取app信息AppInfoapp;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});}returnret;}intmain(intargc,char*argv[]){[...]//将解析后的app信息传递给QML前端引擎。rootContext()->setContextProperty("apps",apps());[...]}核心是遍历一个目录下的所有文件,QSettings负责解析配置文件。作用://打印出所有应用程序启动信息exec:"xpad"icon:"xpad"name:"Xpad"[...]3.实现整体布局我们使用SwipeView来实现滑动页面的功能,参考我之前的文章:《Qt 官方示例 | 这几个 QML 版的 HelloWorld 你学会了吗?》至于单页的布局,我们可以使用Repeater控件。Repeater可以帮助我们生成重复的内容。这里我们规定一个页面最多可以显示24个应用。通过swipeView+中继器实现://文件:main.qmlswipeView{[...]属性intintintoflecteater:0repeater{id:pagerepeater模型:apppages.lengthemptages.lengthitem{propertyvarpage{apppages:apppages[index]grid{index]grid{columns:6grid{columRepeater{Model:Page.LengthImage{Source:"QRC:/IMAGES/qtlogo.png"}}}}第一个repeater用于实现所有页面,第二个repeater用于生成页面的所有页面.APP图标,这里我们先用Qt的logo来代替真正的APP图标。运行效果:此时支持左右滑动,但是还没有填写APP信息。4.支持显示应用程序图标在main()中,我们设置了一个名为apps的属性,里面包含了所有APP的信息:engine.rootContext()->setContextProperty("apps",apps());我们需要将前端界面中的Qtlogo换成APP图标。显示应用程序图标://文件:main.qmlgrid{[...]Repeater{Model:Page!==未定义?Page.length:0COLUMN{Image{PropertyVarApp:Pagex]//Appicon:"Image://icons/"+app[1][...]}label{PropertyVarApp:Page[Index]id:label//应用程序的名称TEXT:app[0][...]}}}}}}变化很小。运行效果:此时只支持图标,仍然不支持鼠标选择。5.支持选定的应用程序。选中的应用需要添加鼠标悬停事件的处理。当鼠标移到某个图标上时,Qt会捕获鼠标悬停事件并将其传递给当前焦点所在的控件。我们把APP的接口代码抽取出来单独放在AppEntry.qml中,让它成为一个独立的控件,然后在里面添加鼠标悬停事件处理。图标控件:AppEntry.qml///文件:AppEntry.qmlPane{id:根属性varapp[...]//发送信号hovered()signalhovered()MouseArea{[...]OnHoveredChanged:{if(hovered){root.hovered()}}column{anchors.fill:paintimage{source:"image://icons/""+app[1]}label{当悬停时AppEntry控件的信号在main.qml中被接收,它的背景颜色需要改变以提醒用户图标已经被选择。//File:Main.qmlRepeter{Model:Page.LengthAPENTRY{App:Page[Index][...]//SELECTED变化,背景色会变化select:swipeView.selectEx===iNDexNHovered:{Swipvixselect(index)}[...]}}运行效果:这样已经可以显示了6.支持启动应用程序在Qt中,可以使用QProcess来创建进程,这里我们创建一个QProcess的子类来运行APP。QProcess的子类://文件:process.cppvoidProcess::start(constQString&program,constQVariantList&arguments){[...]QProcess::startDetached(program);}//文件:process.hclassProcess:publicQProcess{Q_OBJECTpublic:Process(QObject*parent=nullptr);Q_INVOKABLEvoidstart(constQString&program,constQVariantList&arguments={});};//file:main.cppintmain(intargc,char*argv[]){//将Process实例传给前端引擎.rootContext()->setContextProperty("proc",newProcess(&engine));}前端处理点击事件://file:AppEntry.qmlsignalclicked()MouseArea{[...]onClicked:{root.clicked()}}当用户点击图标时,AppEntry控件发出clicked()信号。//File:main.qmlAppEntry{app:page[index][...]//主窗口启动APPonClicked:{exec(app[2])}[...]}functionexec(program){console.debug("Exec:"+program)proc.start(program)Qt.quit();}最后调用Process::start()启动APP。运行效果:怎么样?你学会了吗?——完结——推荐阅读:专辑|Linux驱动开发专辑|Linux系统编程专辑|后台回复【加群】,我拉你进群。
