Qt和HTML笔记:初始化

Plux posted @ 2012年4月04日 07:50 in C/C++ with tags c/c++ Qt QtWebkit , 12477 阅读

为了应对最近的比赛,但对很对 GUI 系统都不怎么熟悉,而且又要用 C++ 进行项目核心代码的编辑。RetVal 希望团队做出一个很炫的图形界面,不过,对 C++ 的窗口系统还真的不熟悉。于是尝试用 Qt 和 HTML 5 来进行界面的编程,也算是一个新挑战。

不过似乎关于 Qt 和 HTML 5 的中文资料还不多,于是整理一下笔记吧。这个博客也很久没更新了……

新建项目

要新建 Qt HTML 5 应用程序,可以直接在 Qt Creator 里新建“HTML 5 Application”,但要注意的是,这样新建的Qt程序并没有包含菜单栏之类控件,完全是一个 Qt 窗口里面有一个 Webkit 组件。但有一个好处是,新建的 Webkit 组件被 Qt Creator 对移动设备(主要是触摸屏设备)优化过,可以应用于桌面端和手机端。但也由于针对了触摸屏,所以,默认禁用了“hover”事件(即鼠标悬停事件)。使我还纠结了很久为什么 Qt Webkit 不支持鼠标悬停事件。

如果我们是针对桌面端开发,那么其实不必要考虑Webkit的移动支持,因此,我们可以自己新建一个 Qt GUI 项目。此时,要注意的是在 .pro 文件中添加对 Webkit 的编译支持。

参考 .pro 文件如下:

#-------------------------------------------------
#
# Project created by QtCreator 2012-04-02T09:29:02
#
#-------------------------------------------------

QT       += core gui webkit

TARGET = ColdTest
TEMPLATE = app

SOURCES += main.cpp\
        mainwindow.cpp \
    sampleobject.cpp

HEADERS  += mainwindow.h \
    sampleobject.h

FORMS    += mainwindow.ui

uiml.source = html
uiml.target = .
DEPLOYMENTFOLDERS = uiml

defineTest(qtcAddDeployment) {
for(deploymentfolder, DEPLOYMENTFOLDERS) {
    item = item$${deploymentfolder}
    itemsources = $${item}.sources
    $$itemsources = $$eval($${deploymentfolder}.source)
    itempath = $${item}.path
    $$itempath= $$eval($${deploymentfolder}.target)
    export($$itemsources)
    export($$itempath)
    DEPLOYMENT += $$item
}

MAINPROFILEPWD = $$PWD

win32 {
    copyCommand =
    for(deploymentfolder, DEPLOYMENTFOLDERS) {
        source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
        source = $$replace(source, /, \\)
        sourcePathSegments = $$split(source, \\)
        target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments)
        target = $$replace(target, /, \\)
        !isEqual(source,$$target) {
            !isEmpty(copyCommand):copyCommand += &&
            isEqual(QMAKE_DIR_SEP, \\) {
                copyCommand += $(COPY_DIR) \"$$source\" \"$$target\"
            } else {
                source = $$replace(source, \\\\, /)
                target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
                target = $$replace(target, \\\\, /)
                copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\"
            }
        }
    }
    !isEmpty(copyCommand) {
        copyCommand = @echo Copying application data... && $$copyCommand
        copydeploymentfolders.commands = $$copyCommand
        first.depends = $(first) copydeploymentfolders
        export(first.depends)
        export(copydeploymentfolders.commands)
        QMAKE_EXTRA_TARGETS += first copydeploymentfolders
    }
} else:unix {
    desktopfile.path = /usr/share/applications
    copyCommand =
    for(deploymentfolder, DEPLOYMENTFOLDERS) {
        source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
        source = $$replace(source, \\\\, /)
        macx {
            target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target)
        } else {
            target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
        }
        target = $$replace(target, \\\\, /)
        sourcePathSegments = $$split(source, /)
        targetFullPath = $$target/$$last(sourcePathSegments)
        !isEqual(source,$$targetFullPath) {
            !isEmpty(copyCommand):copyCommand += &&
            copyCommand += $(MKDIR) \"$$target\"
            copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\"
        }
    }
    !isEmpty(copyCommand) {
        copyCommand = @echo Copying application data... && $$copyCommand
        copydeploymentfolders.commands = $$copyCommand
        first.depends = $(first) copydeploymentfolders
        export(first.depends)
        export(copydeploymentfolders.commands)
        QMAKE_EXTRA_TARGETS += first copydeploymentfolders
    }
    installPrefix = /opt/$${TARGET}
    for(deploymentfolder, DEPLOYMENTFOLDERS) {
        item = item$${deploymentfolder}
        itemfiles = $${item}.files
        $$itemfiles = $$eval($${deploymentfolder}.source)
        itempath = $${item}.path
        $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target)
        export($$itemfiles)
        export($$itempath)
        INSTALLS += $$item
    }
    icon.files = $${TARGET}.png
    icon.path = /usr/share/icons/hicolor/64x64/apps
    desktopfile.files = $${TARGET}.desktop
    target.path = $${installPrefix}/bin
    export(icon.files)
    export(icon.path)
    export(desktopfile.files)
    export(desktopfile.path)
    export(target.path)
    INSTALLS += desktopfile icon target
}

export (ICON)
export (INSTALLS)
export (DEPLOYMENT)
export (TARGET.EPOCHEAPSIZE)
export (TARGET.CAPABILITY)
export (LIBS)
export (QMAKE_EXTRA_TARGETS)
}
qtcAddDeployment()

项目依赖部分(qtcAddDeployment)是参考了 Qt Creator 为 HTML 5 Application 项目自动生成的代码。

然后,在项目根目录下新建文件夹 html ,把用到的 HTML 5 构建的文件添加到这里。

初始化 QtWebkit

新建 Qt GUI 项目后,默认应该会生成 MainWindow 类,简单起见,直接以 MainWindow 类为基础,用 Qt Desginer 画好界面。

然后回到 MainWindow 类(或者你自己新建的其他类)的初始化函数中,添加slot:

private slots:
    void addToJavaScript();

然后,方法实现为:

void MainWindow::addToJavaScript()
{
    ui->webView->page()->mainFrame()->addToJavaScriptWindowObject("Qt", qt);
    ui->webView->page()->mainFrame()->addToJavaScriptWindowObject("app", this);
}

这个函数是为 Webkit 组件建立页面的时候,把 C++ 对象包装为 JavaScript对象传递给 JavaScript 调用的。这里,即是把 qt(一个QApplication 对象)、app(QMainWindow 对象)添加到 QtWebkit 的 JavaScript 运行环境中。

然后,添加本地路径调整函数:(这里省略头文件的声明了)

QString MainWindow::adjustPath(const QString &path)
{
#ifdef Q_OS_UNIX
#ifdef Q_OS_MAC
    if (!QDir::isAbsolutePath(path))
        return QCoreApplication::applicationDirPath()
                + QLatin1String("/../Resources/") + path;
#else
    const QString pathInInstallDir = QCoreApplication::applicationDirPath()
        + QLatin1String("/../") + path;
    if (pathInInstallDir.contains(QLatin1String("opt"))
            && pathInInstallDir.contains(QLatin1String("bin"))
            && QFileInfo(pathInInstallDir).exists()) {
        return pathInInstallDir;
    }
#endif
#endif
    return path;
}

这段代码也是参考 HTML 5 Application 生成的函数,可以把相对项目路径转化为 QUrl 标识。

于是,初始化 WebView 的时候就可以:

ui->webView->setUrl(QUrl(MainWindow::adjustPath("html/ui.html")));

来调用 html 文件夹下面的 ui.html 文件了。

到这里,一个 Qt HTML 5 程序的初始化工作就完成了。可以编辑一下 ui.html 文件试用一下 Qt Webkit ~


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter