用Qt开发简单的浏览器(一)
来源:互联网 发布:商品关键字的seo处理 编辑:程序博客网 时间:2024/05/16 19:22
1.代码实现
工程目录结构如下:
AddressBar类包含了地址栏和按钮两个控件,将地址栏回车和按钮点击信号与goToSite()槽连接。
当回车和点击事件发生时,goToSite()将获得Url地址并发送go(QUrl)信号。
addressbar.h
#ifndef ADDRESSBAR_H#define ADDRESSBAR_H#include <QWidget>#include <QLineEdit>#include <QPushButton>#include <QHBoxLayout>#include <QUrl>#include <QString>class AddressBar : public QWidget{ Q_OBJECTpublic: 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 <QWebView>class HtmlView : public QWebView{ Q_OBJECTpublic: 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 <QWidget>#include <QLineEdit>#include <QPushButton>#include <QGridLayout>#include <QtWebKit>#include <QMainWindow>#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 <QApplication>#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::keyPressEventvoid 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<QAbstractButton> 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浏览器项目2015年8月16日
需要源码的同学还真不少啊,现在源码已经共享到GitHub上了,请自行获取吧!地址是:https://github.com/cdai/qtbrowser
- 用Qt开发简单的浏览器(一)
- 用Qt开发简单的浏览器(二)
- Qt开发-使用QWebEngineView开发一个简易的浏览器(一)
- Qt/QML开发支持下载的简单浏览器
- qt版本的浏览器开发
- QT 图片浏览器(一)
- 用QtWebKit开发简单的浏览器
- 用QtWebKit开发简单的浏览器
- Android-用WebView开发简单的浏览器
- QT学习,最简单的Web浏览器
- QT浏览器插件的开发过程总结
- webdriver基础python版(一)简单的浏览器操作
- Qt学习之路一(一个简单的时钟)
- Qt简单的解析Json数据例子(一)
- Qt开发杂记(一)
- 谈谈BS开发中的各种浏览器的兼容性(一)
- (一) Qt Model/View 的简单说明
- (一) Qt Model/View 的简单说明
- HAVING Clause Without a Group Function
- 返回去掉最后两级目录的目录字符串
- android基础笔记1
- NSXMLParser具体解析xml的应用详解
- android json
- 用Qt开发简单的浏览器(一)
- 12.05.06 ~ 12.05.19
- Combining java and Node.js through redis pub/sub and a json remote interface
- 关于PF_INET和AF_INET的区别
- 30分钟掌握STL系列(三)
- struts2 获取配置的系统信息
- Basic RPCs in Node.js with a Java Backend
- Windows phone开发初体验之(一)-基本概念的了解
- SuperLabel