热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

用Qt开发简单的浏览器(一)

用Qt开发简单的浏览器(一),Go语言社区,Golang程序员人脉社





1.代码实现



工程目录结构如下:







AddressBar类包含了地址栏和按钮两个控件,将地址栏回车和按钮点击信号与goToSite()槽连接。

当回车和点击事件发生时,goToSite()将获得Url地址并发送go(QUrl)信号。



addressbar.h


#ifndef ADDRESSBAR_H
#define ADDRESSBAR_H
#include
#include
#include
#include
#include
#include
class AddressBar : public QWidget
{
Q_OBJECT
public:
explicit AddressBar(QWidget *parent = 0);

signals:
void go(QUrl);

public slots:
void goToSite();
private:
QLineEdit *addressEdit;
QPushButton *goButton;
QHBoxLayout *layout;
};
#endif // ADDRESSBAR_H


addressbar.cpp


#include "addressbar.h"
AddressBar::AddressBar(QWidget *parent) :
QWidget(parent)
{
addressEdit = new QLineEdit(parent);
goButton = new QPushButton("Go", parent);
layout = new QHBoxLayout;
layout->addWidget(addressEdit);
layout->addWidget(goButton);
this->setLayout(layout);
connect(goButton, SIGNAL(clicked()), this, SLOT(goToSite()));
connect(addressEdit, SIGNAL(returnPressed()), this, SLOT(goToSite()));
}
void AddressBar::goToSite()
{
QString address = addressEdit->text();
emit go(QUrl(address));
}


接下来是QtWebkit包中的主要类QWebView,我们借助这个类来渲染Url指向的网页。

为了当用户在地址栏回车或者点击Go按钮时能够自动加载网页,我们需要给QWebView

添加loadNewPage(QUrl)槽(因为QWebView没有类似load(QUrl)的槽),并将其与go(QUrl)

信号连接。所以我们实现一个QWebView的子类HtmlView。



htmlview.h


#ifndef HTMLVIEW_H
#define HTMLVIEW_H
#include
class HtmlView : public QWebView
{
Q_OBJECT
public:
explicit HtmlView(QWidget *parent = 0);

signals:

public slots:
void loadNewPage(const QUrl &url);

};
#endif // HTMLVIEW_H


htmlview.cpp

#include "htmlview.h"
HtmlView::HtmlView(QWidget *parent) :
QWebView(parent)
{
}
void HtmlView::loadNewPage(const QUrl &url)
{
this->load(url);
}



接下来实现程序的主窗口QMainWindow,将AddressBar和HtmlView放置其中。



mainwindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
#include
#include "addressbar.h"
#include "htmlview.h"
class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
};
#endif // MAINWINDOW_H


mainwindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
// 1.Create widget
QWidget *centralWidget = new QWidget(this);
AddressBar *bar = new AddressBar;
HtmlView *view = new HtmlView;
// 2.Add widget to layout
QGridLayout *layout = new QGridLayout;
layout->addWidget(bar, 0, 0, 1, 10);
layout->addWidget(view, 1, 0, 1, 10);
centralWidget->setLayout(layout);
// 3.Connect widget
QObject::connect(bar, SIGNAL(go(QUrl)), view, SLOT(loadNewPage(QUrl)));
this->setCentralWidget(centralWidget);
this->setWindowTitle("My Browser v1.0");
this->resize(640, 480);
}


最后是程序的入口main.cpp

#include
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow *window = new MainWindow;
window->show();

return app.exec();
}





2.事件流分析








我们分别为AddressBar和HtmlView自定义了两个槽goToSite(QUrl)和loadNewPage(QUrl),以及新的信号go(QUrl)。

就是为了将Url地址传递给QWebView的load函数。



这里需要注意的是SIGNAL-SLOT机制是Qt的内部机制,它是同步执行的。源头上returnPressed()和clicked()槽的触发,

是从操作系统的事件队列中得到的,并进行异步的处理。以QPushButton的clicked()槽的触发为例,QApplication.exec()

执行后将会监听操作系统事件队列,当鼠标事件发生时,事件将会发送到QPushButton的event()函数进行分发:


QPushButton::event ->
QAbstractButton::event ->
QWidget::event [Dispatch event]:
case QEvent::KeyPress: {
QKeyEvent *k = (QKeyEvent *)event;
bool res = false;
if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
if (k->key() == Qt::Key_Backtab
|| (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
res = focusNextPrevChild(false);
else if (k->key() == Qt::Key_Tab)
res = focusNextPrevChild(true);
if (res)
break;
}
keyPressEvent(k);
-> QPushButton::keyPressEvent
void QPushButton::keyPressEvent(QKeyEvent *e)
{
Q_D(QPushButton);
switch (e->key()) {
case Qt::Key_Enter:
case Qt::Key_Return:
if (autoDefault() || d->defaultButton) {
click();
break;
}
// fall through
default:
QAbstractButton::keyPressEvent(e);
}
}
-> QAbstractButton::click:
void QAbstractButton::click()
{
if (!isEnabled())
return;
Q_D(QAbstractButton);
QPointer guard(this);
d->down = true;
d->emitPressed();
if (guard) {
d->down = false;
nextCheckState();
if (guard)
d->emitReleased();
if (guard)
d->emitClicked();
}
}




3.SIGNAL-SLOT类的编译



关于Q_OBJECT宏以及SIGNAL,SLOT,emit等关键字奇怪的语法,其实他们是通过一个叫做MOC元对象编译器

的组件来进行预编译的,因此我们可以使用SIGNAL,SLOT,emit来清晰地连接各个信号槽,而非函数指针。

SIGNAL-SLOT使用很方便,但也是会损失一点执行效率,使用时要谨慎。





4.总结及学习资料



通过这个例子可以对Qt的SIGNAL-SLOT机制有个简单的了解,它可以减少对象间的依赖。假如不使用它,我们就

需要在AddressBar中直接调用HtmlView的load()函数,两个类耦合在了一起。在这个例子中MainWindow负责AddressBar

和HtmlView的构建和连接,使它们互相不知道对方的存在!



让我更感兴趣的其实是QtWebKit,通过它我们可以在Qt开发桌面应用时使用Web技术,而不用局限于Qt,MFC等等。

Web开发人员也可以投身桌面应用开发之中。



QtWebKit官方文档:http://doc.qt.nokia.com/4.7-snapshot/qtwebkit.html

学习笔记:http://caterpillar.onlyfun.net/Gossip/Qt4Gossip/Qt4Gossip.html

QtWebKit系列教程:http://software.intel.com/zh-cn/blogs/2010/06/08/qt-webkit-qt-webkit/

信号槽深入学习:http://www.ibm.com/developerworks/cn/linux/guitoolkit/qt/signal-slot/

QtWeb - 一个开源的Qt浏览器项目




推荐阅读
  • 在使用 Qt 进行 YUV420 图像渲染时,由于 Qt 本身不支持直接绘制 YUV 数据,因此需要借助 QOpenGLWidget 和 OpenGL 技术来实现。通过继承 QOpenGLWidget 类并重写其绘图方法,可以利用 GPU 的高效渲染能力,实现高质量的 YUV420 图像显示。此外,这种方法还能显著提高图像处理的性能和流畅性。 ... [详细]
  • 本次发布的Qt音乐播放器2.0版本在用户界面方面进行了细致优化,提升了整体的视觉效果和用户体验。尽管核心功能与1.0版本保持一致,但界面的改进使得操作更加直观便捷,为用户带来了更为流畅的使用体验。此外,我们还对部分细节进行了微调,以确保软件的稳定性和性能得到进一步提升。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 为了在VS2017和Qt环境中高效配置Open Inventor与Coin3D,本文提供了详细的实操指南和验证步骤。通过这些步骤,用户可以顺利导入机械臂模型进行三维仿真。本文详细介绍了Coin3D作为开源软件的优势及其在三维图形渲染中的应用,并提供了具体的配置方法和常见问题的解决方案。 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • 本文详细介绍了如何在Unity中实现一个简单的广告牌着色器,帮助开发者更好地理解和应用这一技术。 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • 在探讨P1923问题时,我们发现手写的快速排序在最后两个测试用例中出现了超时现象,这在意料之中,因为该题目实际上要求的是时间复杂度为O(n)的算法。进一步研究题解后,发现有选手使用STL中的`nth_element`函数成功通过了所有测试点。本文将详细分析这一现象,并提出相应的优化策略。 ... [详细]
  • 本文深入探讨了Ajax的工作机制及其在现代Web开发中的应用。Ajax作为一种异步通信技术,改变了传统的客户端与服务器直接交互的模式。通过引入Ajax,客户端与服务器之间的通信变得更加高效和灵活。文章详细分析了Ajax的核心原理,包括XMLHttpRequest对象的使用、数据传输格式(如JSON和XML)以及事件处理机制。此外,还介绍了Ajax在提升用户体验、实现动态页面更新等方面的具体应用,并讨论了其在当前Web开发中的重要性和未来发展趋势。 ... [详细]
  • 使用 `git stash` 可以将当前未提交的修改保存到一个临时存储区,以便在后续恢复工作目录时使用。例如,在处理中间状态时,可以通过 `git stash` 命令将当前的所有未提交更改推送到一个新的储藏中,从而保持工作目录的整洁。此外,本文还将详细介绍如何解决 `git stash pop` 时可能出现的冲突问题,帮助用户高效地管理代码变更。 ... [详细]
  • 在今天的实践中,我深入学习了网页图像抓取技术,通过编写爬虫程序批量获取网站上的图片资源。具体来说,我选择了一个包含大量高质量图片的网站作为练习对象,并成功实现了将这些图片批量下载到本地存储。这一过程不仅提升了我对爬虫技术的理解,还增强了我的编程能力。 ... [详细]
author-avatar
汽车之家马甲小宝宝_457
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有