http://blog.csdn.net/dc_726/article/details/7584205
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_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 <QWebView>
- 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 <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::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<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浏览器项目
http://blog.csdn.net/dc_726/article/details/7600192
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_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 <QWebView>
- 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 <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::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<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浏览器项目
一、功能改进
经过对QtWebKit的一些学习,对之前的浏览器进行一些改进:
1.增加分页显示多个网页的功能。每个分页都是一个QWebView控件,实现对多个网页的加载。
2.加入欢迎主页。学习如何创建Qt资源文件,从本地读取欢迎主页的HTML。
3.添加了前进Forward和后退Back按钮。
4.此外还明确了SIGNAL和SLOT的命名,SLOT都以handleXXX开头与SIGNAL区分开。
二、Qt资源文件
Qt可以很方便的通过资源文件来管理各种资源,就像在VS中创建资源文件一样。
项目结构如下:
在Qt Creator中创建四个资源文件html.qrc,script.qrc,style.qrc,resource.qrc分别对应html,
script,style和resource文件夹,用来存储网页、JS脚本、CSS样式文件和各种图片音频视频资源。
以html.qrc为例,添加html文件夹中的welcome.html,那么在程序中我们就可以用路径
qrc:/html/welcome.html来引用它。这里的欢迎页面引用了之前Chrome天气预报插件的
代码。
welcome.html
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=GB2312"/>
- <link rel="stylesheet" type="text/css" href="qrc:/style/style.css"/>
- <script type="text/javascript" src="qrc:/script/jquery-1.7.2.min.js"></script>
- <script type="text/javascript">
- function init() {
- $("#loadingdiv").html("正在加载城市天气预报...");
- $.getJSON("http://m.weather.com.cn/data/101010100.html",
- function(data) {
- $("#loadingdiv").html("");
- var weatherinfo = data["weatherinfo"];
- var datearray = ["", weatherinfo["date_y"], "第二天", "第三天", "第四天", "第五天", "第六天"];
- $("#cityname").html(weatherinfo["city"] + "城市天气预报");
- for (i = 1; i <= 6; i++) {
- var divid = "#div" + i;
- $(divid).append(datearray[i]).append("<br>");
- var imgurl = "http://m.weather.com.cn/weather_img/" + weatherinfo["img"+(i*2-1)] + ".gif";
- $(divid).append('<img src="' + imgurl + '"/>').append("<br>");
- $(divid).append(weatherinfo["temp" + i]).append("<br>");
- $(divid).append(weatherinfo["weather" + i]);
- }
- }
- );
- }
- </script>
- </head>
- <body onload="init()">
- <h1>Welcome!!!</h1>
- <div id="weatherreportdiv">
- <div id="loadingdiv"></div>
- <div id="cityname"></div>
- <hr></hr>
- <div id="div1" class="weatherdiv"></div>
- <div id="div2" class="weatherdiv"></div>
- <div id="div3" class="weatherdiv"></div>
- <div id="div4" class="weatherdiv"></div>
- <div id="div5" class="weatherdiv"></div>
- <div id="div6" class="weatherdiv"></div>
- </div>
- </body>
- </html>
style.css
- h1 {
- text-align: center;
- }
- #weatherreportdiv {
- height: 300px;
- width: 700px;
- text-align: center;
- font-size: 20px;
- font-weight: bold;
- margin: 5px;
- }
- #cityname {
- text-align: center;
- font-size: 20px;
- font-weight: bold;
- margin: 5px;
- }
- .weatherdiv {
- float: left;
- width: 15%;
- margin: 5px;
- }
管理资源就是这么简单,下面来看改进后的代码。
三、源码实现
在AddressBar中新加一个SLOT函数handleAddressChanged,处理当分页切换时URL的变化。
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_OBJECT
- public:
- explicit AddressBar(QWidget *parent = 0);
- signals:
- void go(const QUrl&);
- void back();
- void forward();
- void newPage();
- public slots:
- void handleGoToSite();
- void handleAddressChanged(const QUrl&);
- private:
- QLineEdit *addressEdit;
- QPushButton *newButton;
- QPushButton *backButton;
- QPushButton *forwardButton;
- QPushButton *goButton;
- QHBoxLayout *layout;
- };
- #endif // ADDRESSBAR_H
addressbar.cpp
- #include "addressbar.h"
- AddressBar::AddressBar(QWidget *parent) :
- QWidget(parent)
- {
- // 1.Create widget
- addressEdit = new QLineEdit;
- newButton = new QPushButton("New");
- backButton = new QPushButton("Back");
- forwardButton = new QPushButton("Forward");
- goButton = new QPushButton("Go");
- // 2.Set property
- // 3.Connect signal and slot
- connect(goButton, SIGNAL(clicked()), this, SLOT(handleGoToSite()));
- connect(addressEdit, SIGNAL(returnPressed()), this, SLOT(handleGoToSite()));
- connect(backButton, SIGNAL(clicked()), this, SIGNAL(back()));
- connect(forwardButton, SIGNAL(clicked()), this, SIGNAL(forward()));
- connect(newButton, SIGNAL(clicked()), this, SIGNAL(newPage()));
- // 4.Add to layout
- layout = new QHBoxLayout;
- layout->addWidget(newButton);
- layout->addWidget(backButton);
- layout->addWidget(forwardButton);
- layout->addWidget(addressEdit);
- layout->addWidget(goButton);
- this->setLayout(layout);
- }
- void AddressBar::handleGoToSite()
- {
- QString address = addressEdit->text();
- emit go(QUrl(address));
- }
- void AddressBar::handleAddressChanged(const QUrl &url)
- {
- addressEdit->setText(url.toString());
- }
新建了TabPage继承了QTabWidget,管理所有分页。
tabpage.h
- #ifndef TABPAGE_H
- #define TABPAGE_H
- #include <QTabWidget>
- #include <QList>
- #include "htmlview.h"
- class TabPage : public QTabWidget
- {
- Q_OBJECT
- public:
- explicit TabPage(QWidget *parent = 0);
- ~TabPage();
- signals:
- void urlChanged(const QUrl&);
- public slots:
- void handleNewTab();
- void handleLoadNewPage(const QUrl&);
- void handleBack();
- void handleForward();
- private slots:
- void handleTabChanged(int);
- void handleTabClosed(int);
- void handleLinkClicked(const QUrl&);
- private:
- QList<QWebView*> viewList;
- };
- #endif // TABPAGE_H
tabpage.cpp
- #include "tabpage.h"
- #include <QtDebug>
- TabPage::TabPage(QWidget *parent) :
- QTabWidget(parent)
- {
- // Set property
- this->setTabsClosable(true);
- // Connect built-in signal to customized one to convert index to url
- connect(this, SIGNAL(currentChanged(int)), SLOT(handleTabChanged(int)));
- connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(handleTabClosed(int)));
- // Create new tab for home page
- this->handleNewTab();
- }
- TabPage::~TabPage()
- {
- }
- void TabPage::handleNewTab()
- {
- HtmlView *view = new HtmlView;
- view->load(QUrl("qrc:/html/welcome.html"));
- //view->page()->setForwardUnsupportedContent(true);
- view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
- // Monitor linkClicked signal
- connect(view, SIGNAL(linkClicked(const QUrl&)), this, SLOT(handleLinkClicked(const QUrl&)));
- // Add and activate this new tab
- int index = this->addTab(view, "Welcome");
- this->setCurrentIndex(index);
- viewList.append(view);
- }
- void TabPage::handleLoadNewPage(const QUrl &url)
- {
- qDebug() << "loadNewPage: " << url.toString();
- HtmlView *view = (HtmlView*) this->currentWidget();
- view->load(url);
- }
- void TabPage::handleBack()
- {
- HtmlView *view = (HtmlView*) this->currentWidget();
- view->back();
- emit urlChanged(view->url());
- }
- void TabPage::handleForward()
- {
- HtmlView *view = (HtmlView*) this->currentWidget();
- view->forward();
- emit urlChanged(view->url());
- }
- void TabPage::handleTabChanged(int index)
- {
- if (index > viewList.length() - 1)
- return;
- // index is the new tab index
- QWebView* view = viewList[index];
- emit urlChanged(view->url());
- }
- void TabPage::handleTabClosed(int index)
- {
- if (index > viewList.length() - 1)
- return;
- this->removeTab(index);
- QWebView* view = viewList[index];
- viewList.removeAt(index);
- delete view;
- }
- void TabPage::handleLinkClicked(const QUrl& url)
- {
- qDebug() << "handleLinkClicked: " << url.toString();
- HtmlView *view = (HtmlView*) this->currentWidget();
- view->load(url);
- emit urlChanged(url);
- }
接下来是MainWindow,改动很小。
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"
- #include "tabpage.h"
- namespace Ui {
- class MainWindow;
- }
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- public:
- explicit MainWindow(QWidget *parent = 0);
- ~MainWindow();
- private:
- Ui::MainWindow *ui;
- };
- #endif // MAINWINDOW_H
mainwindow.cpp
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
- MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow)
- {
- //ui->setupUi(this);
- // 0.Global setting
- QWebSettings* defaultSettings = QWebSettings::globalSettings();
- // We use JavaScript, so set it to be enabled.
- defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, true);
- // Plug-ins must be set to be enabled to use plug-ins.
- defaultSettings->setAttribute(QWebSettings::PluginsEnabled,true);
- defaultSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,true);
- defaultSettings->setObjectCacheCapacities(0, 0, 0);
- // 1.Create widget
- QWidget *centralWidget = new QWidget(this);
- AddressBar *bar = new AddressBar;
- TabPage *tab = new TabPage;
- // 2.Set property
- this->setCentralWidget(centralWidget);
- this->setWindowTitle("My Browser v1.0");
- this->resize(800, 600);
- // 3.Connect widget
- QObject::connect(bar, SIGNAL(newPage()),tab, SLOT(handleNewTab()));
- QObject::connect(bar, SIGNAL(back()),tab, SLOT(handleBack()));
- QObject::connect(bar, SIGNAL(forward()),tab, SLOT(handleForward()));
- QObject::connect(bar, SIGNAL(go(QUrl)), tab, SLOT(handleLoadNewPage(QUrl)));
- QObject::connect(tab, SIGNAL(urlChanged(QUrl)), bar, SLOT(handleAddressChanged(QUrl)));
- // 4.Add widget to layout
- QGridLayout *layout = new QGridLayout;
- layout->addWidget(bar, 0, 0, 1, 10);
- layout->addWidget(tab, 1, 0, 1, 10);
- centralWidget->setLayout(layout);
- }
- MainWindow::~MainWindow()
- {
- //delete ui;
- }
四、关键问题
1.需要为QWebView中的QWebPage设置才能使页面内链接可以正常跳转。
view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
2.需要为AJAX调用设置:
QWebSettings* defaultSettings = QWebSettings::globalSettings();
// We use JavaScript, so set it to be enabled.
defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, true);
// Plug-ins must be set to be enabled to use plug-ins.
defaultSettings->setAttribute(QWebSettings::PluginsEnabled,true);
defaultSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,true);
defaultSettings->setObjectCacheCapacities(0, 0, 0);
// We use JavaScript, so set it to be enabled.
defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, true);
// Plug-ins must be set to be enabled to use plug-ins.
defaultSettings->setAttribute(QWebSettings::PluginsEnabled,true);
defaultSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,true);
defaultSettings->setObjectCacheCapacities(0, 0, 0);
五、最终效果
1.程序开始运行,进入欢迎页面。
2.多页面浏览
2012年7月4日 补充
htmlview.h
- #ifndef HTMLVIEW_H
- #define HTMLVIEW_H
- #include <QWebView>
- class HtmlView : public QWebView
- {
- Q_OBJECT
- public:
- explicit HtmlView(QWidget *parent = 0);
- signals:
- public slots:
- void loadNewPage(const QUrl &url);
- };
- #endif // HTMLVIEW_H
- #include "htmlview.h"
- HtmlView::HtmlView(QWidget *parent) :
- QWebView(parent)
- {
- }
- void HtmlView::loadNewPage(const QUrl &url)
- {
- this->load(url);
- }
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_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 <QWebView>
- 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 <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::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<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浏览器项目
一、功能改进
经过对QtWebKit的一些学习,对之前的浏览器进行一些改进:
1.增加分页显示多个网页的功能。每个分页都是一个QWebView控件,实现对多个网页的加载。
2.加入欢迎主页。学习如何创建Qt资源文件,从本地读取欢迎主页的HTML。
3.添加了前进Forward和后退Back按钮。
4.此外还明确了SIGNAL和SLOT的命名,SLOT都以handleXXX开头与SIGNAL区分开。
二、Qt资源文件
Qt可以很方便的通过资源文件来管理各种资源,就像在VS中创建资源文件一样。
项目结构如下:
在Qt Creator中创建四个资源文件html.qrc,script.qrc,style.qrc,resource.qrc分别对应html,
script,style和resource文件夹,用来存储网页、JS脚本、CSS样式文件和各种图片音频视频资源。
以html.qrc为例,添加html文件夹中的welcome.html,那么在程序中我们就可以用路径
qrc:/html/welcome.html来引用它。这里的欢迎页面引用了之前Chrome天气预报插件的
代码。
welcome.html
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=GB2312"/>
- <link rel="stylesheet" type="text/css" href="qrc:/style/style.css"/>
- <script type="text/javascript" src="qrc:/script/jquery-1.7.2.min.js"></script>
- <script type="text/javascript">
- function init() {
- $("#loadingdiv").html("正在加载城市天气预报...");
- $.getJSON("http://m.weather.com.cn/data/101010100.html",
- function(data) {
- $("#loadingdiv").html("");
- var weatherinfo = data["weatherinfo"];
- var datearray = ["", weatherinfo["date_y"], "第二天", "第三天", "第四天", "第五天", "第六天"];
- $("#cityname").html(weatherinfo["city"] + "城市天气预报");
- for (i = 1; i <= 6; i++) {
- var divid = "#div" + i;
- $(divid).append(datearray[i]).append("<br>");
- var imgurl = "http://m.weather.com.cn/weather_img/" + weatherinfo["img"+(i*2-1)] + ".gif";
- $(divid).append('<img src="' + imgurl + '"/>').append("<br>");
- $(divid).append(weatherinfo["temp" + i]).append("<br>");
- $(divid).append(weatherinfo["weather" + i]);
- }
- }
- );
- }
- </script>
- </head>
- <body onload="init()">
- <h1>Welcome!!!</h1>
- <div id="weatherreportdiv">
- <div id="loadingdiv"></div>
- <div id="cityname"></div>
- <hr></hr>
- <div id="div1" class="weatherdiv"></div>
- <div id="div2" class="weatherdiv"></div>
- <div id="div3" class="weatherdiv"></div>
- <div id="div4" class="weatherdiv"></div>
- <div id="div5" class="weatherdiv"></div>
- <div id="div6" class="weatherdiv"></div>
- </div>
- </body>
- </html>
style.css
- h1 {
- text-align: center;
- }
- #weatherreportdiv {
- height: 300px;
- width: 700px;
- text-align: center;
- font-size: 20px;
- font-weight: bold;
- margin: 5px;
- }
- #cityname {
- text-align: center;
- font-size: 20px;
- font-weight: bold;
- margin: 5px;
- }
- .weatherdiv {
- float: left;
- width: 15%;
- margin: 5px;
- }
管理资源就是这么简单,下面来看改进后的代码。
三、源码实现
在AddressBar中新加一个SLOT函数handleAddressChanged,处理当分页切换时URL的变化。
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_OBJECT
- public:
- explicit AddressBar(QWidget *parent = 0);
- signals:
- void go(const QUrl&);
- void back();
- void forward();
- void newPage();
- public slots:
- void handleGoToSite();
- void handleAddressChanged(const QUrl&);
- private:
- QLineEdit *addressEdit;
- QPushButton *newButton;
- QPushButton *backButton;
- QPushButton *forwardButton;
- QPushButton *goButton;
- QHBoxLayout *layout;
- };
- #endif // ADDRESSBAR_H
addressbar.cpp
- #include "addressbar.h"
- AddressBar::AddressBar(QWidget *parent) :
- QWidget(parent)
- {
- // 1.Create widget
- addressEdit = new QLineEdit;
- newButton = new QPushButton("New");
- backButton = new QPushButton("Back");
- forwardButton = new QPushButton("Forward");
- goButton = new QPushButton("Go");
- // 2.Set property
- // 3.Connect signal and slot
- connect(goButton, SIGNAL(clicked()), this, SLOT(handleGoToSite()));
- connect(addressEdit, SIGNAL(returnPressed()), this, SLOT(handleGoToSite()));
- connect(backButton, SIGNAL(clicked()), this, SIGNAL(back()));
- connect(forwardButton, SIGNAL(clicked()), this, SIGNAL(forward()));
- connect(newButton, SIGNAL(clicked()), this, SIGNAL(newPage()));
- // 4.Add to layout
- layout = new QHBoxLayout;
- layout->addWidget(newButton);
- layout->addWidget(backButton);
- layout->addWidget(forwardButton);
- layout->addWidget(addressEdit);
- layout->addWidget(goButton);
- this->setLayout(layout);
- }
- void AddressBar::handleGoToSite()
- {
- QString address = addressEdit->text();
- emit go(QUrl(address));
- }
- void AddressBar::handleAddressChanged(const QUrl &url)
- {
- addressEdit->setText(url.toString());
- }
新建了TabPage继承了QTabWidget,管理所有分页。
tabpage.h
- #ifndef TABPAGE_H
- #define TABPAGE_H
- #include <QTabWidget>
- #include <QList>
- #include "htmlview.h"
- class TabPage : public QTabWidget
- {
- Q_OBJECT
- public:
- explicit TabPage(QWidget *parent = 0);
- ~TabPage();
- signals:
- void urlChanged(const QUrl&);
- public slots:
- void handleNewTab();
- void handleLoadNewPage(const QUrl&);
- void handleBack();
- void handleForward();
- private slots:
- void handleTabChanged(int);
- void handleTabClosed(int);
- void handleLinkClicked(const QUrl&);
- private:
- QList<QWebView*> viewList;
- };
- #endif // TABPAGE_H
tabpage.cpp
- #include "tabpage.h"
- #include <QtDebug>
- TabPage::TabPage(QWidget *parent) :
- QTabWidget(parent)
- {
- // Set property
- this->setTabsClosable(true);
- // Connect built-in signal to customized one to convert index to url
- connect(this, SIGNAL(currentChanged(int)), SLOT(handleTabChanged(int)));
- connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(handleTabClosed(int)));
- // Create new tab for home page
- this->handleNewTab();
- }
- TabPage::~TabPage()
- {
- }
- void TabPage::handleNewTab()
- {
- HtmlView *view = new HtmlView;
- view->load(QUrl("qrc:/html/welcome.html"));
- //view->page()->setForwardUnsupportedContent(true);
- view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
- // Monitor linkClicked signal
- connect(view, SIGNAL(linkClicked(const QUrl&)), this, SLOT(handleLinkClicked(const QUrl&)));
- // Add and activate this new tab
- int index = this->addTab(view, "Welcome");
- this->setCurrentIndex(index);
- viewList.append(view);
- }
- void TabPage::handleLoadNewPage(const QUrl &url)
- {
- qDebug() << "loadNewPage: " << url.toString();
- HtmlView *view = (HtmlView*) this->currentWidget();
- view->load(url);
- }
- void TabPage::handleBack()
- {
- HtmlView *view = (HtmlView*) this->currentWidget();
- view->back();
- emit urlChanged(view->url());
- }
- void TabPage::handleForward()
- {
- HtmlView *view = (HtmlView*) this->currentWidget();
- view->forward();
- emit urlChanged(view->url());
- }
- void TabPage::handleTabChanged(int index)
- {
- if (index > viewList.length() - 1)
- return;
- // index is the new tab index
- QWebView* view = viewList[index];
- emit urlChanged(view->url());
- }
- void TabPage::handleTabClosed(int index)
- {
- if (index > viewList.length() - 1)
- return;
- this->removeTab(index);
- QWebView* view = viewList[index];
- viewList.removeAt(index);
- delete view;
- }
- void TabPage::handleLinkClicked(const QUrl& url)
- {
- qDebug() << "handleLinkClicked: " << url.toString();
- HtmlView *view = (HtmlView*) this->currentWidget();
- view->load(url);
- emit urlChanged(url);
- }
接下来是MainWindow,改动很小。
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"
- #include "tabpage.h"
- namespace Ui {
- class MainWindow;
- }
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- public:
- explicit MainWindow(QWidget *parent = 0);
- ~MainWindow();
- private:
- Ui::MainWindow *ui;
- };
- #endif // MAINWINDOW_H
mainwindow.cpp
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
- MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow)
- {
- //ui->setupUi(this);
- // 0.Global setting
- QWebSettings* defaultSettings = QWebSettings::globalSettings();
- // We use JavaScript, so set it to be enabled.
- defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, true);
- // Plug-ins must be set to be enabled to use plug-ins.
- defaultSettings->setAttribute(QWebSettings::PluginsEnabled,true);
- defaultSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,true);
- defaultSettings->setObjectCacheCapacities(0, 0, 0);
- // 1.Create widget
- QWidget *centralWidget = new QWidget(this);
- AddressBar *bar = new AddressBar;
- TabPage *tab = new TabPage;
- // 2.Set property
- this->setCentralWidget(centralWidget);
- this->setWindowTitle("My Browser v1.0");
- this->resize(800, 600);
- // 3.Connect widget
- QObject::connect(bar, SIGNAL(newPage()),tab, SLOT(handleNewTab()));
- QObject::connect(bar, SIGNAL(back()),tab, SLOT(handleBack()));
- QObject::connect(bar, SIGNAL(forward()),tab, SLOT(handleForward()));
- QObject::connect(bar, SIGNAL(go(QUrl)), tab, SLOT(handleLoadNewPage(QUrl)));
- QObject::connect(tab, SIGNAL(urlChanged(QUrl)), bar, SLOT(handleAddressChanged(QUrl)));
- // 4.Add widget to layout
- QGridLayout *layout = new QGridLayout;
- layout->addWidget(bar, 0, 0, 1, 10);
- layout->addWidget(tab, 1, 0, 1, 10);
- centralWidget->setLayout(layout);
- }
- MainWindow::~MainWindow()
- {
- //delete ui;
- }
四、关键问题
1.需要为QWebView中的QWebPage设置才能使页面内链接可以正常跳转。
view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
2.需要为AJAX调用设置:
QWebSettings* defaultSettings = QWebSettings::globalSettings();
// We use JavaScript, so set it to be enabled.
defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, true);
// Plug-ins must be set to be enabled to use plug-ins.
defaultSettings->setAttribute(QWebSettings::PluginsEnabled,true);
defaultSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,true);
defaultSettings->setObjectCacheCapacities(0, 0, 0);
// We use JavaScript, so set it to be enabled.
defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, true);
// Plug-ins must be set to be enabled to use plug-ins.
defaultSettings->setAttribute(QWebSettings::PluginsEnabled,true);
defaultSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,true);
defaultSettings->setObjectCacheCapacities(0, 0, 0);
五、最终效果
1.程序开始运行,进入欢迎页面。
2.多页面浏览
2012年7月4日 补充
htmlview.h
- #ifndef HTMLVIEW_H
- #define HTMLVIEW_H
- #include <QWebView>
- class HtmlView : public QWebView
- {
- Q_OBJECT
- public:
- explicit HtmlView(QWidget *parent = 0);
- signals:
- public slots:
- void loadNewPage(const QUrl &url);
- };
- #endif // HTMLVIEW_H
- #include "htmlview.h"
- HtmlView::HtmlView(QWidget *parent) :
- QWebView(parent)
- {
- }
- void HtmlView::loadNewPage(const QUrl &url)
- {
- this->load(url);
- }