我的第一个Symbian Qt 应用 – 第一部分
你也许知道,本周将在慕尼黑举办Qt 开发伙伴日 活动,我们认为这是与大家一起讨论如 何开始Symbian Qt 开发的极好机会。建立自己的开发环境,从头开始直接编写一个简单的应用,没有比这更好的起步方式了。因此,如果你有兴趣在Symbian 上进行Qt 开 发,但此前却从未对之有所接触,本教程将帮助你立即起动。如果你希望从Qt on Symbian 的技术概要起步,那么你可以在我们的维基百科 上找到更多的信息。
首先请从诺基亚论坛下载QtSDK (针对本教程我使用的是版本1.0 ),这个SDK 让你能编制各种跨平台应用,并让其运行于桌面、仿真环境,你也能将其打包然后安装到终端上。
安装过程很简洁,你要做的就是:确定SDK 所要安装的位置,并确定是默认安装还是定制安装;在本教程中我们将全部使用默认设置。安装完成后你就能立即启用Qt Creator IDE 了。
Qt 提供了既面向桌面开发也面向移动开发的极为丰富的widgets 集:开发伙伴们能在自己的应用中直接使用这些widgets ,或者将这些widgets 用作其定制widgets 的构建块。今天我们要向大家展示的是QtWebKit 模块中的QWebView widget 。如果你希望在自己的应用中显示web 页面,那么这个widget 将非常有用,而且也很好用。
为创建一个新工程,请先启动Qt Creator, 然后在File 菜单中选择New File or Project ( 也可以按CTRL+N) ;这将启动一个对话框,在这个对话框中我们能选择让Qt Creator 为我们设定哪种类型的应用,显然我们要选择的是Mobile Qt Application ( 移动Qt 应用) ,如下图所示:
现在我们就能为自己的工程选一个名字并定一个位置了。我将自己的工程命名为mywebwidget ,但你可以随意取用更好的名字:-)
如果我们认可这些设置,那么我们可以按Next 然后转到Class Information (类信息)对话框:
按Next 然后按Finish 完成工程设置。现在你就能在Qt Creator 中看到你的工程了,现在它处于Edit (编辑)模式,如下图中的高亮显示图标所示:
因为我们即将使用QWebViewWidget ,我们需要向工程文件- mywebwidget.pro - 中添加QtWebKit 模块,以及QtCore 和QtGui 模块,它们都是默认添加的:
QT += core gui webkit
如果仔细观察这个文件,你还会注意到Qt Creator 已创建了一段针对Symbian 特定设置的代码段,对此我们后面将作讨论。现在让我们返回到main.cpp ;因为这是我们的首个范例程 序,我们还不会马上使用MyWebWidget 类,所以,我们的首个应用的源代码将处于主函数中:
#include <QtGui/QApplication>
#include <QtWebKit/QWebView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//MyWebWidget w; //not used for now
QWebView view;
view.load(QUrl(”http://www.google.com”));
#if defined(Q_WS_S60)
view.showMaximized();
#else
view.show();
#endif
return a.exec();
}
上面这个宏能确保当我们针对终端进行构建时应用窗口保持最大化。
好了,做好了。让我们运行这个工程,看看其在模拟器中的样子:
这就是正在模拟器中运行的应用;你看到,我们仅以几条语句就构建了一个web 浏览器的雏形:-)
希望大家喜欢这首个”Qt on Symbian” 教程。明天我们将详细讨论一些Qt 主类,并向我们的第一个应用添加一些功能。因而,如果你有兴趣,请保持关注!
我的第一个Symbian Qt 应用 – 第二部分
在昨天的课程中我们演示了如何为你的Symbian Qt 应用开发建立自己的环境。我们已已经开始编制一个简单的“ 浏览器” 应用,它能加载一个预定义的URL 并能在模拟器中运行。
今天(及明天)我们将向自己的首个 Qt 应用添加一些功能。特别是,我们会向我们的“ 浏览器” 中加入一个URL 地址条,并稍微地重新规划一下代码以便在今后能进一步向其添加一些 widgets 。在这个过程中我们将介绍Qt 编程的两个重要概念:布局管理器 及信号与槽 。
我们将从修改主函数开始:在昨天的范例程序中,全部源代码都被置于这个函数中;今天,我们将让主函数去显示应用的主widget 。这是一个标准方案:主函数只是你的应用入口,而所有的实际逻辑都是在一个widget 或在主窗口中实现的。
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyWebWidget w;
#if defined(Q_WS_S60)
w.showMaximized();
#else
w.show();
#endif
return a.exec();
}
class MyWebWidget:public QWidget
{
Q_OBJECT
public:
MyWebWidget(QWidget *parent = 0);
~MyWebWidget();
private slots:
void openUrl();
void onLoadFinished(bool finished);
private:
QWebView* m_view;
QLineEdit* m_lineEdit;
QVBoxLayout* m_layout;
};
你也许已经注意到了,我们向我们的类声明中添加了一个宏,即Q_OBJECT 。这么做的第一个理由是,没有它我们就无法使用信号和槽;还有许多其它理由,如果你想了解更多,也许你可以参阅Qt Meta-Object 系统 。 因此,MyWebWidget 可以显示一个web 视图widget 、一个行编辑widget (这就是我们用于URL 地址条的widget ),并同时使用QVBoxLayout 布局管理器。让我们看看如何在我们的.cpp 文件中使用这些东西:
MyWebWidget::MyWebWidget(QWidget *parent)
: QWidget(parent)
{
m_lineEdit = new QLineEdit(this);
m_lineEdit->setStyleSheet("background-color:white; padding: 6px;
color:blue");
m_lineEdit->setPlaceholderText("Enter url ...");
m_view = new QWebView(this);
m_view->load(QUrl("http://blog.symbian.org"));
m_layout = new QVBoxLayout;
m_layout->addWidget(m_lineEdit);
m_layout->addWidget(m_view);
m_layout->insertSpacing(1,10);
setLayout(m_layout);
connect(m_lineEdit,SIGNAL(editingFinished()),SLOT(openUrl()));
connect(m_view,SIGNAL(loadFinished(bool)),SLOT(onLoadFinished(bool)));
}
在构造函数中我们对这些widgets 作了初始化,将MyWebWidget 作为它们的父widgets 传递进去:在Qt 中,这意味着MyWebWidget 将在调用其析构函数时负责释放子widgets 所分配的内存。
行编辑widget (自解释)具有一项有趣的功能(Qt 4.7 中引入),即设定一个占位符文本,因此我们会使用这项功能。如你所见,我们能直接使用CSS 句法来设定我们的行编辑widget 的样式。在我们的范 例中我们将背景设成“ 白色” ,而将文本设为“ 蓝色” 。“ 样式” 是Qt 中的一大课题,如果你想了解更多有关样式的知识,QStyle 类 在线文档是你的首选。
web 视图类 – 对此我们已有所了解 – 也在此得到构造,而我们的“ 主页” 现在被设置成blog.symbian.org 。
最后,我们要将这两个widgets 以垂直布局放置,从而把它们添加到布局管理器中;我们还用insertSpacing 函数在两个widgets 间插入了一些空间。
正如我们所预期的,我们也利用了Qt 编程中一个非常重要的概念:信号与槽。概括道来,信号与槽是能让两种对象“ 连接起来” 的一些“ 特别函数” :也就是说,当发生了某些有趣事件时,一个对象能提示另一个对象,而另一个对象能执行一个动作以响应这种提示。
在我们的范例中,行编辑widget – 它让用户能输入一个URL – 当用户结束URL 编辑时需要向MyWebWidget 发出提示。为实现这一点,我们使用函数QObject::connect 将MyWebWidget 中的一个槽 (名为openUrl() )连接到QLineEdit 中的名为editingFinished() 的一个信号 。每当行编辑widget 发出这个信号时,MyWebWidget 就会返回openURL() 函数。
类似地,我们也将MyWebWidget::onLoadFinished 连接到由QWebView 发出的loadFinished 信号。
有关信号与槽方面的更多信息,请参阅Qt 在线文档 。
好了,现在我们就来实现这些槽:
void MyWebWidget::openUrl()
{
QString url(m_lineEdit->text());
if(!url.contains("http://",Qt::CaseInsensitive))
url.prepend("http://");
m_view->load(QUrl(url));
}
void MyWebWidget::onLoadFinished(bool finished)
{
if(finished){
m_lineEdit->clear();
m_lineEdit->setPlaceholderText(tr("Enter url ..."));
}
}
这两个槽都很直观:openUrl() 槽抓取行编辑widget 中输入的URL ,然后在web 视图widget 中将其作为一个网页打开。onLoadFinished 槽则当所要求的网页被加载完毕后清除URL 地址条中的文本。
下面就是我们的应用的外观:
希望大家喜欢本教程的第二部分。明天我将继续改进我们的首个Symbian Qt 应用。
我的第一个Symbian Qt 应用 – 第三部分
昨天我们对自己的第一个Qt 应用作了些许改进,向大家展示了如何使用信号与槽来“ 连接” 两个对象,同时我们也介绍了布局管理器。今天我们要向自己那个简单的浏览器应用中再添加一个功能:一个工具条,其中具有一个返回按钮,用于导航回web 历史纪录,外加一个标签,使用由QtMobility 所提供的Location API 来显示用户的位置。
我们将把工具条实现为一个独立的widget ,它拥有两个widgets :一个是QPushButton ,另一个则是QLabel 。用于工具条widget 的布局为水平方向的,因而我们也会使用一个QHBoxLayout 布局管理器。
我们已经展示了如何以Qt Creator 在自己的工程中创建并添加一个新类,因此我们将直接转向代码部分。
class MyToolBar:public QWidget
{
Q_OBJECT
public:
MyToolBar(QWidget *parent = 0);
~MyToolBar();
signals:
void goBack();
void showLocation();
private slots:
void onBackPressed();
void onPositionUpdated(const QGeoPositionInfo& posInfo);
private:
QPushButton* m_backButton;
QLabel* m_locationLabel;
QHBoxLayout* m_layout;
QGeoPositionInfoSource* m_location;
};
如你所见,MyToolBar 拥有自己的信号 – 能被MyWebWidget 所连接- 同时也有两个槽,用于连接由其子widgets 所发出的那些信号。让我们看看这个类实现后的样子:
MyToolBar::MyToolBar(QWidget* parent)
:QWidget(parent)
{
m_backButton = new QPushButton("Back",this);
m_locationLabel = new QLabel(this);
m_location = QGeoPositionInfoSource::createDefaultSource(this);
m_location->setUpdateInterval(20000); //msec
m_location->startUpdates();
m_layout = new QHBoxLayout;
m_layout->addWidget(m_backButton);
m_layout->addWidget(m_locationLabel);
m_layout->insertSpacing(1,10);
setLayout(m_layout);
m_layout->addStretch();
connect(m_backButton,SIGNAL(clicked()),SLOT(onBackPressed()));
connect(m_location,SIGNAL(positionUpdated(QGeoPositionInfo)),
SLOT(onPositionUpdated(QGeoPositionInfo)));
}
void MyToolBar::onPositionUpdated(const QGeoPositionInfo& posInfo)
{
QGeoCoordinate coordinate = posInfo.coordinate();
QString label_coordinate = coordinate.toString();
m_locationLabel->setText(locString+" "+label_coordinate);
}
void MyToolBar::onBackPressed()
{
emit goBack();
}
看上去这与我们从MyWebWidget 类的实现中所看到没多大不同,是不是?我们再次创建了一些子widgets ,将它们加入到了一个布局中(在 这种情况下,我们也添加了一个可伸缩布局,以使返回按钮的尺寸为最小),而且我们每隔20 秒都会收到位置信息更新。这两个槽也非常直 白:onBackPressed() 发送一个信号 – 该信号被MyWebWidget 连接,等一回我们就会看到 – 而当收到最新的位置信息时,onPositionUpdated() 会更新文本标签。
现在让我们看一下MyWebWidget 类,看看有何变化。在构造函数中,我们需要创建工具条widget 并将其加入到现有(垂直)布局中:
MyWebWidget::MyWebWidget(QWidget* parent)
: QWidget(parent)
{
m_softkeyAction = new QAction( tr("Options"), this);
m_softkeyAction->setSoftKeyRole(QAction::PositiveSoftKey);
addAction(m_softkeyAction);
//...
m_toolbar = new MyToolBar(this);
m_layout->addWidget(m_toolbar);
//...
connect(m_toolbar,SIGNAL(goBack()),SLOT(loadPreviousPage()));
}
我们还创建了一个新动作,用于让左功能键具备一个选项 菜单,右功能键则为退出 。
而这就是loadPreviousPage( ) 槽,它在用户按返回 按钮时能让我们返回到导航历史纪录。由于Qt 所提供的一个非常方便的类,该功能极为简单。这个类能将相关于QWebPage 的web 历史纪录储存到一个独立对象中,并提供一个函数,以便能导航返回(及前进)n 页。真是酷极了。
void MyWebWidget::loadPreviousPage()
{
if(m_view->history()->canGoBack())
{
m_view->history()->back();
}
}
而这就是我们的应用的最新版本,它显示我们的位置更新信息,也新增了后退 按钮:
如果你以模拟器控制台将改变特定位置,你将明显地看到位置信息每隔20 秒就更新一次。
明天,在教程的最后部分,我们会最终展示如何在Symbian 终端上安装我们的首个应用。我们的首个Symbian Qt 应用的源码可于此 下载,我再次希望大家觉得本教程对自己有所帮助。
原文链接:http://blogcn.symbian.org/?p=391
http://qt.csdn.net/articles.aspx?pointid=653&pointid2=