首页 > 代码库 > QtQuick桌面应用开发指导 7)创建应用 8)扩展

QtQuick桌面应用开发指导 7)创建应用 8)扩展

CHAPTER7 部署NotApp应用

现在我们要让程序在典型的桌面环境中可用, 可部署; 如第一章所描述, 我们在QtCreator中使用QtQuick UI项目开发NoteApp程序; 这意味着qmlscene用来加载main.qml, 随之让NoteApp运行;

首先, 让NoteApp可用的最简单方案是创建一个package(包)将所有qml文件, qmlscense和一个可以运行qmlscense加载main.qml的简单脚本bundle(捆扎)起来; 你需要参考每一个桌面平台, 了解如何创建小脚本; 例如, 在Linux平台, 你要使用bash shell脚本, 而Windows使用的是batch文件; 这个方案能很好工作, 也很直接, 但是你可能不希望把源代码都一起发布出去, 因为你的程序现在使用的是专利代码; 

程序应该以二进制格式(binary format)发布, 所有的qml都boundle在二进制文件中; 这可以帮助让安装过程更简单, 用户体验(user experience)也更愉快;

因此, 我们要为NoteApp创建一个可执行文件, 安装使用都应该相当简单; 这章中可以看到如何创建一个QtQuick程序, 把qml文件和图片都boundle到一个可执行的二进制文件中; 另外, 我们也应该探索如何对QML使用Qt Resource System; 

7.1 创建NoteApp Qt应用

目标是创建一个单个的NoteApp可执行二进制文件, 用户可以运行它来加载NoteApp;

7.1.1 创建一个QtQuick程序

首先我们要使用QtCreator创建一个QtQuick程序, 确保在wizard(向导)里面选择 Built-in element only(for all platforms); 把程序命名为 noteapp;

现在有了一个从wizard新建的项目, 注意有个 qtquick2applicationviewer项目生成; 生成的qtquick2applicationviewer项目是一个基本模板(template)程序, 用来读取QML文件; 这个程序作为一个非常通用的项目来部署QtQuick程序到设备和其他目标终端, 里面包含为这些部署目标设定的多个平台特定(platform-specific)的代码; 这里不再详细研究这些特定部分代码; 

然而, qtquick2applicationviewer还有某些古怪的地方限制了我们想要完成的目标; 这个程序设定程序员会将QML文件和可执行的二进制文件一起发布; 这样就不能使用Qt Resource System了, 但之后你会看到客服这个问题的方法;

对于noteapp下面, 这里有个源文件main.cpp; 在main.cpp中, 你会看到view对象--QtQuick2ApplicationViewer类是如何被用来调用方法: QtQuick2ApplicationViewer::setMainQmlFile()加载main.qml;

// main.cpp

1
2
3
4
5
6
7
8
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/noteapp/main.qml"));
    viewer.showExpanded();
    return app.exec();
}

注意, 有个基本的main.qml由Qt Quick Application wizard生成, 会替代原先为NoteApp创建的main.qml;

noteapp项目的文件夹结构很直接易懂;

noteapp--项目根目录

    -qml: 包含QML文件

    -qtquick2applicationviewer [qmlapplicationviewer]: 自动生成的项目, 用来加载QML文件

    -noteapp: 项目文件

    -main.cpp: 创建Qt Application的C++文件

我们要把QML文件包括fonts和images目录拷贝到新建的noteapp项目的在qmls目录里; QtCreator会识别项目文件夹和文件的变化, 把这些显示在project view里面; 如果它没有显示, 右键点击project中的QML图标选择 Add Existing Files然后添加文件;

Note 要保证把所有现存的文件包括在nodeDB.js中调用的图片都包含进来;

这时, 我们可以build(构建)和运行项目, 看看是否一切都正常; 在构建noteapp项目前, 确保项目正确的配置以及就绪; 参考 Configure Project文档; 

一旦程序成功构建, 一个可执行的二进制文件"noteapp"应该在项目根目录创建出来; 如果在系统中把Qt正确配置好了, 你可以双击文件来运行它;

7.1.2 使用Qt Resource System来存储QML文件和图片

我们创建了一个可执行文件, 加载QML文件来运行程序; 就像你在main.cpp中看到的, viewer对象通过传递相对地址来加载main.qml; 另外, 打开noteapp.pro文件来理解部署和构建设置:

1
2
3
4
5
# Add more folders to ship with the application, here
folder_01.source = qml/noteapp
folder_01.target = qml
DEPLOYMENTFOLDERS = folder_01
//...

看起来它确实想要把QML文件和可执行文件一起发布, 但这不是我们想要的;

Qt提供了一个很直观的 Resource System可以和QML无缝连接; 我们要创建一个resource文件--noteapp.qrc, 放在根(root)项目中, 这样我们可以把QML和图片文件加进去; 参考 Create a Resource File;

为了可以使用新建的resource文件--noteapp.qrc, 要在noteapp.pro和main.cpp中做最小的改动;

先把note.pro中的部署步骤注释掉:

1
2
3
4
# Add more folders to ship with the application, here
#folder_01.source = qml/noteapp
#folder_01.target = qml
#DEPLOYMENTFOLDERS = folder_01

在main.cpp中, 看到QtQuick2ApplicationViewer::setMainQmlFile()方法使用main.qml的相对路径来调用;

1
2
3
4
5
6
7
8
// qtquick2applicationviewer.cpp
//...
void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file)
{
    d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file);
    setSource(QUrl::fromLocalFile(d->mainQmlFile));
}
//...

QtQuick2ApplicationViewer类继承自QQuickView, 它用来加载和显示QML文件; QtQuick2ApplicationViewer::setMainQmlFile()方法没有为使用resource[资源文件]来优化, 它是在调用setSource()方法的时候调整了QML文件的路径[不同平台的路径格式];

克服问题的最简单方案是在main.cpp里, 对viewer对象直接调用setSource(), 但这时我们将main.qml作为resource文件的一部分来传递;

// main.cpp

1
2
3
4
5
6
7
8
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/noteapp/main.qml"));
    viewer.showExpanded();
    return app.exec();
}

QML文件的使用没有其他的地方再需要修改, 包括我们用image文件, font文件, 因为文件的路径现在是相对的, 会指向resource内部的文件系统(filesystem); 所以现在我们可以在QtCreator内构建项目, 产生一个二进制可执行文件, bundle(包含)了QML, image和font文件;

7.1.3 为程序设置图标和标题

推荐一个图像方面的改进: 为项目设置一个图标(icon); 这样可以在桌面平台上唯一地识别你的项目;

在noteapp文件夹里, 有一些PNG[Portable Network Graphics] 文件和SVG[Scalable Vector Graphics] 文件; 这些image文件可以用来为程序设置图标, 根据图标大小有64x64和80x80的, 或者是矢量化的(vectorized);

考虑到这些图标文件在不同平台上的细节, 你可以参考qtquick2applicationviewer.pri文件; 更多细节可以参考文档 Setting the Application Icon (http://qt-project.org/doc/qt-4.8/appicon.html); 

在viewer上调用setWindowIcon()方法来设置程序窗口的icon;

1
2
3
4
5
6
7
//...main.cpp
    QScopedPointer<QApplication> app(createApplication(argc, argv));
    QScopedPointer<QmlApplicationViewer> viewer(
                QmlApplicationViewer::create());
 
    viewer->setWindowIcon(QIcon("noteapp80.png"));
//...

如果程序需要默认的窗口标题(window-title), 使用setWindowTitle():

1
viewer->setWindowTitle(QString("Keep Your Notes with NoteApp!"));

现在NoteApp可以准备发布和部署到不同的桌面平台上了;


7.1.4 部署NoteApp

NoteApp是一个典型的Qt程序, 你需要决定是静态地还是动态地链接Qt; 另外, 每个桌面平台对于链接(linking)配置都有特定的要求;

可以从文档 Deploying Qt Applications (http://qt-project.org/doc/qt-4.8/deployment.html )中找到关于不同平台的部署信息;

下一步

对本教程的总结;

---7End---



CHAPTER8 课程学习和扩展阅读 

本教程展示了如何使用QtQuick创建一个应用, 以及如何在桌面环境上部署; 我们一步步地开发了NoteApp程序, 学到了QML语言的各个方面, 以及它对于开发现代流畅(fluid)UI和保持代码简洁, 应用各种开发技术的潜力;

这里学到了一些使用各种QML类型的最佳实践, 覆盖了一些有趣的题目:

- Animation和State

- 使用Javascript来强化功能

- 动态的QML对象管理

- 本地数据库存储

- 让程序准备好可以部署

现在你应该已经具备进一步开发NoteApp和增强UI的知识和信心了, 你可以尝试去发现更多在本教程没有提及的QML和Qt Quick特性;

QtQuick是一个快速发展中的技术, 可以在各种不同的软件开发产业和行业中适用, 你可以从最新的Qt Document中找到相关的帮助信息;

---8End---

---END---YCR---


QtQuick桌面应用开发指导 7)创建应用 8)扩展