移动应用软件开发技术
第四讲:Meego应用开发基础
《移动应用软件开发技术》课程建设小组北京大学二零一一年
* 致谢:感谢 Intel对本课程项目的支持
课程内容• Qt 介绍• Qt 安装• 基于 QT 的 Hello World 示例程序• Qt 中主要类的介绍• Qt 的信号槽机制• Qt 中主要控件介绍
Qt介绍• Qt 是跨平台的应用程序和 UI 框架,包括– 跨平台类库– 集成开发环境– 跨平台 IDE
• 一次性开发可在不同桌面和嵌入式操作系统部署
Qt特征一• 面向对象– Qt 具有模块设计和注重软件构件或元素的可重用性的特点
• 构件支持– Qt 提供信号 signal 和槽 slot 的概念,支持对象之间在彼此不知道对方的情况下合作,使得 Qt 适合构件编程
• 友好的联机帮助– Qt 提供了大量的联机参考文件
Qt特征二• 便利性– Qt 是跨平台的 GUI 工具包,对编程者隐藏了处理不同窗口系统时的潜在问题
• 国际化– Qt 为本地化应用提供了完全的支持,所有用户界面文本都可以基于消息翻译表被翻译成各国语言
Qt特征三• 丰富的 API 函数– Qt 为开发者提供了大量的函数
• 可用户化外观– Qt 支持主题,基于 Qt 的应用程序能够在
Windows 外观, Motif 外观以及其他一些用户外观主题之间切换
• 完整的组件工具– Qt 编程的基本模块叫做组件, Qt 含有用来创建专业外观用户界面需要的所有组建
Qt介绍• Who uses Qt ?– Write code once to target multiple platforms– Create amazing user experience– Do more with less and faster– Blend web and native code in a single
application
Qt SDK
• Qt SDK
Qt中主要的类介绍1. QObject
QObject 类是所有能够处理signal , slot 和事件的 Qt 对象的基类,原型如下 :
QObject::QObject(Qobject *parent=0,const char *name=0)
在上面的函数中,如果 parent 为 0 则构造一个无父的对象;如果对象是一个组件,则它会成为顶层窗口。
Qt中主要的类介绍2. QApplication
• QApplication 类负责 GUI 应用程序的控制流和主要的设置,它包括主事件循环体,负责处理和调度所有来自窗口系统和其他资源的事件
• 处理应用程序的开始,结束以及会话管理
• QApplication 是 QObject 类的子类
Qt中主要的类介绍3. Qwidget• QWidget 是所有用户接口对象的基类,继承了
QObject 类的属性• 组件是用户界面的单元组成部分,接收鼠标, 键盘和从其它窗口系统来的事件
• QWidget 类有很多成员函数,但一般不直接使用,而通过子类继承来使用其函数功能
• QWidget 是 QObject 类的子类
信号和槽• 信号和槽机制是 Qt 的一个主要特征,是
Qt 与其它工具包最不相同的部分。• 在图形用户界面编程中,经常会出现窗口的一个部件发生的变化会被通知给另一个部件。
• Qt 采用信号和槽实现对象部件之间的通信
信号和槽的声明一在 Qt 程序设计中,包含 signals 和 slot 的类都要加上Q_OBJECT 的定义。下面给出一个在类中定义 signal 和 slot的例子
class Student:public Qobject {
Q_OBJECT
public:
Student() {myMark = 0;}
int getMark() const {return myMark;}
public slots:
void setMark(int newMark);
signals:
void markChanged(int newMark);
private:
int myMark;
}
信号和槽的声明二 Signal 的发出一般在事件的处理函数中,利用 emit 发出 signal ,下面的例子中在事件处理结束后发出 signal
void Student::setMark(int newMark) {
if(newMark != myMark) {
myMark = newMark;
emit markChanged(myMark);
}
}
信号和槽的连接一在 signal 和 slot 声明以后,需要使用 connect()函数将它们连接起来。 Connect() 函数属于QObject 类的成员函数,能够连接 signal 和slot ,也能够连 signal 和 signal 。函数原型如下
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *slot)
其中第一个和第三个参数指出 signal 和 slot 属于的对象或组件
信号和槽的连接二使用 connect() 函数进行连接的时候,还需要用到 SIGNAL() 和 SLOT()两个宏,使用方法如下:QLabel *label = new QLabel;
QScrollBar *scroll = new QScrollBar;
QObject::connect(scroll, SIGNAL(valueChanged(int)), label, SLOT(setNum(int)));
信号和槽的连接方式一• 同一个信号连接到多个槽
connect(slider, SIGNAL(valueChanged(int)), spinBox, SLOT(setValue(int)));
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(updateStatusBarIndicator (int)));
• 多个信号连接到同一个槽Connect(lcd, SIGNAL(overflow()), this, SLOT(handleMathError()));
Connect(calculator, SIGNAL(divisionByZero()), this, SLOT(handleMathError()));
信号和槽的连接方式二• 一个信号连接到另外一个信号
connect(lineEdit, SIGNAL(textChanged(const Qstring&)), this, SLOT(updateRecord(const Qstring&)))
• 取消一个连接 disconnect(lcd, SIGNAL(overflow()),this,
SLOT(handleMathError()));
取消一个连接不是很常用,因为 Qt 会在一个对象被删除后自动取消这个对象所包含的所有连接
Qt安装• Qt 下载 http://qt.nokia.com/downloads
Qt安装• 下载安装文件
Qt_SDK_Lin32_offline_v1_1_beta_en.run ,在 linux 上安装步骤如下:
1.添加执行权限 chmod u+x Qt_SDK_Lin32_offline_v1_1_beta_en.run
2.运行安装文件 ./ Qt_SDK_Lin32_offline_v1_1_beta_en.run
3. 添加环境变量 将 Qt 安装目录下的 bin目录加入到环境变量
PATH 中
Hello World程序实例• 创建目录 mkdir /examples/hello
• 创建源文件 touch hello.cpp
• 编写源文件 vi hello.cpp
Hello World程序实例• 切换到 hello目录 cd /examples/hello• 创建平台独立的工程文件 project file
qmake –project• 创建平台独立的 Makefile 文件 qmake hello.pro• 编译工程 make• 运行程序 ./hello
Qt对话框• 对话框是一种特殊的窗口,一般用来提供反馈信息或从用户获取输入。
• 给用户提供了同应用程序进行交互的方式
Qt对话框• 模态对话框– 最普遍的对话框。在未消失前用户不能够与同一个应用程序的其他窗口进行交互,直到该对话框关闭。
• 非模态对话框– 当对话框打开的同时,用户还可与同一应用程序的其他窗口进行交互。
Qt对话框• Qt 对话框的类层次结构图
几种 Qt内置对话框介绍• 颜色对话框 QColorDialog,允许用户选择设置颜色• 错误对话框 QErrorDialog,显示错误信息• 文件对话框 QFileDialog,允许用户选择一个或多个文
件或目录• 字体对话框 QFontDialog,允许用户选择、设置字体• 输入对话框 QInputDialog,允许用户输入文本信息• 页设置对话框 QPageSetupDialog, 可配置与打印相关
的页面设置• 进度对话框 QProgressDialog,指示出一项操作的工作进度,而且提示用户该操作是否停滞
• 打印对话框 QPrintDialog,配置打印机相关选项
几种 Qt内置对话框介绍• 颜色对话框 QColorDialog,允许用户选择设置颜色• 错误对话框 QErrorDialog,显示错误信息• 文件对话框 QFileDialog,允许用户选择一个或多个文
件或目录• 字体对话框 QFontDialog,允许用户选择、设置字体• 输入对话框 QInputDialog,允许用户输入文本信息• 页设置对话框 QPageSetupDialog, 可配置与打印相关
的页面设置• 进度对话框 QProgressDialog,指示出一项操作的工作进度,而且提示用户该操作是否停滞
• 打印对话框 QPrintDialog,配置打印机相关选项
查找对话框示例• 通过一个简单的查找对话框的实现了解
Qt 中对话框的创建过程,布局管理,信号和槽机制以及一些简单控件的使用
查找对话框示例头文件 finddialog.h
1 #ifndef FINDDIALOG_H
2 #define FINDDIALOG_H
3 #include <QDialog>
4 class QCheckBox;
5 class QLabel;
6 class QLineEdit;
7 class QPushButton;
8 class FindDialog : public QDialog
9 {
10 Q_OBJECT
11 public:
12 FindDialog(QWidget *parent = 0);
查找对话框示例13 signals:
14 void findNext(const QString &str, Qt::CaseSensitivity cs);
15 void findPrevious(const QString &str, Qt::CaseSensitivity cs);
16 private slots:
17 void findClicked();
18 void enableFindButton(const QString &text);
19 private:
20 QLabel *label;
21 QLineEdit *lineEdit;
22 QCheckBox *caseCheckBox;
23 QCheckBox *backwardCheckBox;
24 QPushButton *findButton;
25 QPushButton *closeButton;
26 };
27 #endif
查找对话框示例• 12 行 FindDialog 的构造函数是典型的
Qt 窗口部件类的定义方式。 Parent 参数指定了父窗口部件。该参数默认值是一个空指针,意味着该对话框没有父对象。
• 13行开始的 signal 部分声明了当用户单击 Find按钮时对话框发出的两个信号。
查找对话框示例1 #include <QtGui>
2 #include "finddialog.h"
3 FindDialog::FindDialog(QWidget *parent)
4 : QDialog(parent)
5 {
6 label = new QLabel(tr("Find &what:"));
7 lineEdit = new QLineEdit;
8 label->setBuddy(lineEdit);
9 caseCheckBox = new QCheckBox(tr("Match &case"));
10 backwardCheckBox = new QCheckBox(tr("Search &backward"));
11 findButton = new QPushButton(tr("&Find"));
12 findButton->setDefault(true);
13 findButton->setEnabled(false);
14 closeButton = new QPushButton(tr("Close"));
查找对话框示例15 connect(lineEdit, SIGNAL(textChanged(const QString &)),
16 this, SLOT(enableFindButton(const QString &)));
17 connect(findButton, SIGNAL(clicked()),
18 this, SLOT(findClicked()));
19 connect(closeButton, SIGNAL(clicked()),
20 this, SLOT(close()));
查找对话框示例• 通过 connect 函数实现了信号和槽的连接• 只要行编辑器中的文本发生变化,就会调用私有槽 enableFindButton
• 当用户单击 Find按钮时,会调用findClicked私有槽
• 当用户单击 Close 时,对话框关闭
查找对话框示例21 QHBoxLayout *topLeftLayout = new QHBoxLayout;
22 topLeftLayout->addWidget(label);
23 topLeftLayout->addWidget(lineEdit);
24 QVBoxLayout *leftLayout = new QVBoxLayout;
25 leftLayout->addLayout(topLeftLayout);
26 leftLayout->addWidget(caseCheckBox);
27 leftLayout->addWidget(backwardCheckBox);
28 QVBoxLayout *rightLayout = new QVBoxLayout;
29 rightLayout->addWidget(findButton);
30 rightLayout->addWidget(closeButton);
31 rightLayout->addStretch();
32 QHBoxLayout *mainLayout = new QHBoxLayout;
33 mainLayout->addLayout(leftLayout);
34 mainLayout->addLayout(rightLayout);
35 setLayout(mainLayout);
36 setWindowTitle(tr("Find"));
37 setFixedHeight(sizeHint().height());
38 }
查找对话框示例• Qt 提供了布局管理器布局子窗口部件• 通过 QHBoxLayout , QVBoxLayout 和
QGridLayout这三个布局的不同嵌套组合,就可以构建出相当复杂的对话框。
查找对话框示例39 void FindDialog::findClicked()
40 {
41 QString text = lineEdit->text();
42 Qt::CaseSensitivity cs =
43 caseCheckBox->isChecked() ? Qt::CaseSensitive :Qt::CaseInsensitive;
44 if (backwardCheckBox->isChecked()) {
45 emit findPrevious(text, cs);
46 } else {
47 emit findNext(text, cs);
48 }
49 }
50 void FindDialog::enableFindButton(const QString &text)
51 {
52 findButton->setEnabled(!text.isEmpty());
53 }
查找对话框示例• 以上两个函数是对话框中用到的槽• 当用户单击 Find按钮时,就会调用
findClicked 槽。而该槽会发射 findPrevious 或findNext 信号,这取决于 Search backward选项的取值
• 只要用户改变了行编辑器中的文本,就会调用enableFindButton 槽。如果在行编辑器中有文本,该槽就会启用 Find按钮,否则它会禁用Find按钮
查找对话框示例创建main.cpp 文件测试FindDialog 窗口部件1 #include <QApplication>
2 #include "finddialog.h"
3 int main(int argc, char *argv[])
4 {
5 QApplication app(argc, argv);
6 FindDialog *dialog = new FindDialog;
7 dialog->show();
8 return app.exec();
9 }
Qt主窗口介绍• 应用程序的主窗口提供了用于构建应用程序用户界面的框架
• 主窗口一般包括菜单栏,工具栏,状态栏,中央窗口部件等子控件
• 在 Qt 中,通过子类化 QMainWindow 可以创建一个应用程序的主窗口
Qt主窗口介绍
Qt主窗口介绍• 下面通过一个简单的代码分析了解 Qt 中主窗口的创建过程
• 实现主窗口的源代码分别放在mainwindow.h 和 mainwindow.cpp 中
Qt主窗口介绍Mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void newFile();
void openFile();
void cut();
void copy();
private:
void createActions();
void createMenus();
void createStatusBar();
void createToolsBar();
Qt主窗口介绍private:
QMenu *fileMenu;
QMenu *editMenu;
QAction *newAction;
QAction *openAction;
QAction *cutAction;
QAction *copyAction;
QToolBar *fileToolBar;
QToolBar *editToolBar;
};
Qt主窗口介绍• 在头文件中,将 MainWindow 类定义为
QMainWindow 的子类。• 像 File->New这样的菜单项,在
MainWindow 中被实现为私有槽
Qt主窗口介绍mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
createActions();
createMenus();
createToolsBar();
createStatusBar();
}
MainWindow 类的构造函数,通过调用类的私有函数 createActions();
createMenus(); createToolsBar(); createStatusBar(); 分别创建主窗口的菜单栏,工具栏和状态栏
菜单栏和工具栏• Qt 通过动作的概念简化了菜单和工具栏的编程
• 一个动作 action就是一个可以添加到任意数量的菜单和工具栏上的项
• 创建菜单和工具栏一般包括如下步骤:– 创建并设置动作– 创建菜单并把动作添加到菜单上– 创建工具栏并把动作添加到工具栏上
菜单栏和工具栏创建动作void MainWindow::createActions()
{
//actions in fileMenu
newAction = new QAction(tr("&New"),this);
connect(newAction,SIGNAL(triggered()),this,SLOT(newFile()));
openAction = new QAction(tr("&Open"),this);
connect(openAction,SIGNAL(triggered()),this,SLOT(openFile()));
//actions in editMenu
cutAction = new QAction(tr("&Cut"),this);
connect(cutAction,SIGNAL(triggered()),this,SLOT(cut()));
copyAction = new QAction(tr("&Copy"),this);
connect(copyAction,SIGNAL(triggered()),this,SLOT(copy()));
}
菜单栏和工具栏创建菜单并将动作添加到菜单上void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(newAction);
fileMenu->addAction(openAction);
editMenu = menuBar()->addMenu(tr("&Edit"));
editMenu->addAction(cutAction);
editMenu->addAction(copyAction);
}
菜单栏和工具栏创建工具栏并将动作添加到工具栏上void MainWindow::createToolsBar()
{
fileToolBar = addToolBar(tr("&File"));
fileToolBar->addAction(newAction);
fileToolBar->addAction(openAction);
editToolBar = addToolBar(tr("&Edit"));
editToolBar->addAction(cutAction);
editToolBar->addAction(copyAction);
}
状态栏创建状态栏void MainWindow::createStatusBar()
{
locationLabel = new QLabel("XY");
statusBar()->addWidget(locationLabel);
}
Qt主窗口介绍创建 main.cpp 文件,测试主窗口的建立int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Q&A
本讲结束 !