Qt5开发及实例V2.0-第二十三章-Qt-多功能文档查看器实例

Qt5开发及实例V2.0-第二十三章-Qt-多功能文档查看器实例

  • 第23章 多功能文档查看器实例
    • 23.1. 简介
    • 23.2. 界面与程序框架设计
      • 23.2.1. 图片资源
      • 23.2.2. 网页资源
      • 23.2.3. 测试用文件
    • 23.3 主程序代码框架
    • 23.4 浏览网页功能实现
      • 23.4.1 实现HtmIHandler处理器
    • 23.5. 部分代码实现
      • 23.5.1 定义主显示区元素
      • 23.5.2 实现“打开图片”对话框
      • 23.5.3 本例对图片的处理
  • 本章相关例程源码下载
    • 1.Qt5开发及实例-CH2301.rar,多功能文档查看器 代码下载

第23章 多功能文档查看器实例

23.1. 简介

我们将会使用Qt5开发一个多文档浏览器,多功能文档查看器。该应用程序可以打开文本文件、图片和网页,对图片进行操作(放大、缩小、旋转等),并支持基本的编辑功能(剪切、复制、粘贴等)。此外,还将提供帮助功能。
该程序可用于浏览网页、阅读文本和查看图片,并支持对文本进行编辑以及对图片进行缩放、
旋转等操作,运行效果如图所示。
在这里插入图片描述

查看图片
在这里插入图片描述
缩放与旋转图片
在这里插入图片描述

23.2. 界面与程序框架设计

新建Qt Quick Controls应用程序,项目名为“MultiDocViewer”。这个文档查看器的界面菜单系统及工具栏的设计如图所示,其中还展示了程序的“关于”对话框 (单击主菜单“帮助”一“关于…”项打开),内有软件功能简介及版权声明信息。
在这里插入图片描述

23.2.1. 图片资源

程序运行时要显示在各菜单项前和工具栏按钮上的图标,必须以图片资源的形式载入项目中方可正常使用。这里为项目准备的资源图片都放在项目工程目录的images文件夹中,如图所示,总共有11个尺寸为32像素x32像素的PNG格式图片。
在这里插入图片描述

23.2.2. 网页资源

easybooks.htm及其资源文件夹easybooks (如图所示),
程序启动时初始打开的网页 (如图所示)也要作为资源事先载入项目中,准备网页文件
将它们一起复制到项目工程目录下。
在这里插入图片描述

23.2.3. 测试用文件

为方便测试程序的功能,还要在计算机上创建一些文件和准备一些图片,如图所示。
在这里插入图片描述

23.3 主程序代码框架

本例程序主体部分的代码写在main.qml文件中,代码量较多,为了给读者一个总体印象以便于理解,这里先只给出程序整体的代码框架。
其中
(a) Action: Action是Qt Quick为菜单式桌面应用开发提供的一种特殊元素,它的主要作用是将界面上UI控件之间的关联属性及需要完成的动作单独分离出来并重新封装成为一个实体,以便用户在设计界面时可以随时引用。Action的功能相当强大,Action类有text、iconSource、iconName、shortcut等属性及triggered信号,因为几乎所有Menultem里的属性在Action里都能找到对应的成员,故Menultem的text、iconSource、 trigger信号等实现的效果都可以通过Action来实现,这两种方式是等同的。例如,本例中定义的一个Action(“打开图片” Action)代码为 :

Action {id: imgOpenAction                   //Action:iconSource:"images/fileimage.png    //图标来源iconName:"image-open"               //图标名text:"打开图片"                     //提示文本onTriggered: imgDlg.open()          //触发动作

这样定义后,在设计菜单项时就可直接引用该Action的标识名,如下

Menultem {text:"图片..."action: imgOpenAction       //指定所用Action的标识名

如此一来,该菜单项就具备了这个Action的全部功能。若有需要,用户还可以只定义一个Action而在多个预设功能完全相同的子菜单项中重复多次使用(提高代码复用性) 。使用Action还有一大好处即在设计工具栏时只须指定工具按钮ToolButton的action属性为之前定义的某个Action的标识,就能很容易将它与对应菜单项关联起来,如本例中的语句 :

ToolButton {action:imgOpenAction }

就生成了一个“打开图片”工具按钮,其上的图标、功能都与“图片.”菜单项相同,如图所示的效果。
在这里插入图片描述

(b) ToolSeparator什:因Qt Quick中并没有提供工具栏分隔条元素,故需要用户自己定义。本例采用自定义组件的方式来设计工具栏上按钮间的分隔条,代码在ToolSeparator.qml文件中,如下:

import QtQuick 2.4Item {width: 8anchors.top: parent.topanchors.bottom: parent.bottomanchors.margins: 6Rectangle {width: 1height: parent.heightanchors.horizontalCenter: parent.horizontalCentercolor: "#22000000"}Rectangle {width: 1height: parent.heightanchors.horizontalCenterOffset: 1anchors.horizontalCenter: parent.horizontalCentercolor: "#33ffffff"}
}

©/* 定义界面主显示区域的元素 /: 界面中央是主显示区,用于显示打开文档的内容。根据打开文档的类型不同,本例定义了不同的组件元素来加以显示,它们都包含在统一的ltem元素中,作为其子元素存在,并以控制可见性的方式分别显示和隐藏
(d)/
定义各种文档处理器对象 */:处理打开的文档内容,有两种方式。第一种是在主程序(main.qml) 中直接编写文件处理函数。第二种是通过自定义的文档处理器对象。本例定义了两个处理器对象 (HtmlHandler和TextHandler) ,分别用来处理网页和文本格式的文档。

23.4 浏览网页功能实现

23.4.1 实现HtmIHandler处理器

具体实现步骤如下 :
(1) 右击项目视图的项目名“MultiDocViewer”一“添加新文件…”项,弹出“新建文件”对话框,如图所示,选择文件和类“C++”下的“C++ Header File”(C++头文件) 模板。
在这里插入图片描述

单击“Choose…”按钮,在“Location”页的“名称”栏中输入“htmlhandler”单击“下一步”按钮,再单击“完成”按钮,就创建好了一个C++头文件 (后缀为.h),系统会自动在“头文件”项目视图中生成一个节点以存放该文件。
如图所示。
在这里插入图片描述
(2)在htmlhandler.h文件中编写如下代码.
(3)创建htmlhandler.cpp源文件,方法同第 (1) 步创建头文件的方法,不同的仅仅是在选择模板时要选“C++ Source File” (C++源文件)
(4) 编写htmlhandler.cpp文件,代码
(5) 处理器编写完成后,要注册为QML类型的元素才能使用,注册语句写在main.cpp中:

qmlRegisterType<HtmlHandler>("org.qtproject.easybooks", 1, 0,"HtmlHandler");

注册之后,再在main.qmI开头导入命名空间:

import org.qtproject.easybooks 1.0

这样就可以在Qt Quick编程中直接使用HtmlHandler处理器元素了。

23.5. 部分代码实现

23.5.1 定义主显示区元素

图像的主显示区元素是一个Image,定义如下

Image {id: imageAreaanchors.fill: parentvisible: falseasynchronous: truefillMode: Image.PreserveAspectFitonStatusChanged: {if (status === Image.Loading) {busy.running = true;}else if(status === Image.Ready) {busy.running = false;}else if(status === Image.Error) {busy.running = false;mainStatusBar.text = "图片无法显示"}}
}

23.5.2 实现“打开图片”对话框

打开图片”对话框的实现代码如下:

FileDialog {id: imgDlgtitle: "打开图片"nameFilters: ["图像文件 (*.jpg *.png *.gif *.bmp *.ico)"]onAccepted: {var filepath = new String(fileUrl);mainStatusBar.text = filepath.slice(8);var dot = filepath.lastIndexOf(".");var sep = filepath.lastIndexOf("/");if(dot > sep){var filename = filepath.substring(sep + 1);main.processFile(fileUrl, filename);}else{mainStatusBar.text = "出错!MultiDocViewer不支持此格式的图片";}}
}

23.5.3 本例对图片的处理

与网页和文本不同,本例对图片的处理采用在main.qml中直接编写文件处理函数的方式来实现文件处理函数processFile的代码如下

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import org.qtproject.easybooks 1.0ApplicationWindow {id: maintitle: htmldoc.htmlTitle + " - 多功能文档查看器"width: 640height: 480visible: trueminimumWidth: 400minimumHeight: 300property color textBackgroundColor: "black"property color textColor: "white"Action {id: cutActiontext: "剪切"shortcut: "Ctrl+X"iconSource: "images/editcut.png"iconName: "edit-cut"enabled: falseonTriggered: textArea.cut()}Action {id: copyActiontext: "复制"shortcut: "Ctrl+C"iconSource: "images/editcopy.png"iconName: "edit-copy"enabled: falseonTriggered: textArea.copy()}Action {id: pasteActiontext: "粘贴"shortcut: "Ctrl+V"iconSource: "images/editpaste.png"iconName: "edit-paste"enabled: falseonTriggered: textArea.paste()}Action {id: htmlOpenActioniconSource: "images/filehtml.png"iconName: "html-open"text: "打开网页"onTriggered: htmlDlg.open()}Action {id: txtOpenActioniconSource: "images/filetext.png"iconName: "text-open"text: "打开文本"onTriggered: txtDlg.open()}Action {id: imgOpenActioniconSource: "images/fileimage.png"iconName: "image-open"text: "打开图片"onTriggered: imgDlg.open()}Action {id: imgZoominActioniconSource: "images/zoomin.png"iconName: "image-zoomin"text: "放大图片"enabled: falseonTriggered: {imageArea.scale += 0.1if(imageArea.scale > 3) {imageArea.scale = 1}}}Action {id: imgZoomoutActioniconSource: "images/zoomout.png"iconName: "image-zoomout"text: "缩小图片"enabled: falseonTriggered: {imageArea.scale -= 0.1if(imageArea.scale < 0.1) {imageArea.scale = 1}}}Action {id: imgRotaleftActioniconSource: "images/rotaleft.png"iconName: "image-rotaleft"text: "逆时针旋转"enabled: falseonTriggered: {imageArea.rotation -= 45}}Action {id: imgRotarightActioniconSource: "images/rotaright.png"iconName: "image-rotaright"text: "顺时针旋转"enabled: falseonTriggered: {imageArea.rotation += 45}}menuBar: MenuBar {Menu {title: "文档"MenuItem {text: "文本..."action: txtOpenAction}MenuItem {text: "网页..."action: htmlOpenAction}MenuItem {text: "图片..."action: imgOpenAction}MenuSeparator {}MenuItem {text: "退出"onTriggered: Qt.quit();}}Menu {title: "编辑"MenuItem { action: copyAction }MenuItem { action: cutAction }MenuItem { action: pasteAction }}Menu {title: "图像"MenuItem {text: "放大"action: imgZoominAction}MenuItem {text: "缩小"action: imgZoomoutAction}MenuSeparator {}MenuItem {text: "向左旋转"action: imgRotaleftAction}MenuItem {text: "向右旋转"action: imgRotarightAction}}Menu {title: "帮助"MenuItem {text: "关于..."onTriggered: aboutBox.open()}}}toolBar: ToolBar {id: mainToolBarwidth: parent.widthRowLayout {anchors.fill: parentspacing: 0ToolButton { action: htmlOpenAction }ToolSeparator {}ToolButton { action: txtOpenAction }ToolButton { action: copyAction }ToolButton { action: cutAction }ToolButton { action: pasteAction }ToolSeparator {}ToolButton { action: imgOpenAction }ToolButton { action: imgRotaleftAction }ToolButton { action: imgRotarightAction }ToolButton { action: imgZoominAction }ToolButton { action: imgZoomoutAction }Item { Layout.fillWidth: true }}}Item {id: centralAreaanchors.fill: parentvisible: trueproperty var current: htmlArea          //当前显示的区域元素BusyIndicator {id: busyanchors.centerIn: parentrunning: falsez: 3}TextArea {id: htmlAreaanchors.fill: parentreadOnly: trueframeVisible: falsebaseUrl: "qrc:/"text: htmldoc.texttextFormat: Qt.RichText}TextArea {id: textAreaanchors.fill: parentvisible: falseframeVisible: falsewrapMode: TextEdit.WordWrapfont.pointSize: 12text: textdoc.textstyle: TextAreaStyle {backgroundColor: main.textBackgroundColortextColor: main.textColorselectedTextColor: "red"selectionColor: "aqua"          //水绿色}Component.onCompleted: forceActiveFocus()}Image {id: imageAreaanchors.fill: parentvisible: falseasynchronous: truefillMode: Image.PreserveAspectFitonStatusChanged: {if (status === Image.Loading) {busy.running = true;}else if(status === Image.Ready) {busy.running = false;}else if(status === Image.Error) {busy.running = false;mainStatusBar.text = "图片无法显示"}}}}statusBar: Rectangle {id: mainStatusBarcolor: "lightgray";implicitHeight: 30;width: parent.width;property alias text: status.text;Text {id: status;anchors.fill: parent;anchors.margins: 4;font.pointSize: 12;}}FileDialog {id: htmlDlgtitle: "打开网页"nameFilters: ["网页 (*.htm *.html *.mht)"]onAccepted: {htmldoc.fileUrl = fileUrl;var filepath = new String(fileUrl);mainStatusBar.text = filepath.slice(8);centralArea.current = htmlAreatextArea.visible = false;imageArea.visible = false;htmlArea.visible = true;main.title = htmldoc.htmlTitle + " - 多功能文档查看器"//设置功能可用性copyAction.enabled = falsecutAction.enabled = falsepasteAction.enabled = falseimgRotaleftAction.enabled = falseimgRotarightAction.enabled = falseimgZoominAction.enabled = falseimgZoomoutAction.enabled = false}}FileDialog {id: txtDlgtitle: "打开文本"nameFilters: ["文本文件 (*.txt)"]onAccepted: {textdoc.fileUrl = fileUrlvar filepath = new String(fileUrl);mainStatusBar.text = filepath.slice(8);centralArea.current = textAreahtmlArea.visible = false;imageArea.visible = false;textArea.visible = true;main.title = textdoc.textTitle + " - 多功能文档查看器"//设置功能可用性copyAction.enabled = truecutAction.enabled = truepasteAction.enabled = trueimgRotaleftAction.enabled = falseimgRotarightAction.enabled = falseimgZoominAction.enabled = falseimgZoomoutAction.enabled = false}}FileDialog {id: imgDlgtitle: "打开图片"nameFilters: ["图像文件 (*.jpg *.png *.gif *.bmp *.ico)"]onAccepted: {var filepath = new String(fileUrl);mainStatusBar.text = filepath.slice(8);var dot = filepath.lastIndexOf(".");var sep = filepath.lastIndexOf("/");if(dot > sep){var filename = filepath.substring(sep + 1);main.processFile(fileUrl, filename);}else{mainStatusBar.text = "出错!MultiDocViewer不支持此格式的图片";}}}MessageDialog {id: aboutBoxtitle: "关于"text: "MultiDocViewer 1.1 \n这是一个多功能文档查看器,可打开文本、网页、图片等多种类型的文档 \n使用 Qt Quick Controls 开发而成。 \nCopyright © 2010 - 2017 easybooks. 版权所有"icon: StandardIcon.Information}HtmlHandler {id: htmldocComponent.onCompleted: htmldoc.fileUrl = "qrc:/easybooks.htm"}TextHandler {id: textdoc}function processFile(fileUrl, name) {if(centralArea.current != imageArea) {if(centralArea.current != null) {centralArea.current.visible = false;}imageArea.visible = true;centralArea.current = imageArea;}imageArea.source = fileUrl;main.title = name + " - 多功能文档查看器"//设置功能可用性copyAction.enabled = falsecutAction.enabled = falsepasteAction.enabled = falseimgRotaleftAction.enabled = trueimgRotarightAction.enabled = trueimgZoominAction.enabled = trueimgZoomoutAction.enabled = true}
}


本章相关例程源码下载

1.Qt5开发及实例-CH2301.rar,多功能文档查看器 代码下载

Qt5开发及实例_CH2301.rar

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/86894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI 编码助手 Codewhisperer 安装步骤和使用初体验

文章作者&#xff1a;为了自己加油 最近亚⻢逊云科技推出了一款基于机器学习的AI编程助手 Amazon Code Whisperer&#xff0c;可以实时提供代码建议。在编写代码时&#xff0c;它会自动根据现有的代码和注释给出建议。Amazon Code Whisperer与 GitHub Copilot 类似&#xff0c;…

Vite的安装与使用

Vite也是前端的构建工具&#xff0c;相较于Webpack&#xff0c;Vite使用了不同的运行方式&#xff1a; 开发时并不对项目进行打包&#xff0c;而是直接采用ESM的方式来运行项目。在项目部署时再进行打包。 因此vite的执行速度相较于Webpack快了许多&#xff0c;操作起来也比W…

SQL中:提示不允许修改表结构,如何更改

SQL&#xff1a;不允许修改表结构 步骤图例注意 步骤 选择菜单栏中的“工具”-“选项”&#xff0c;在选项对话框左栏中找到“设计器”&#xff0c;在设计器右边取消勾选“阻止保存要求重新创建表的更改”即可。 图例 注意 设计表时&#xff0c;尽量一次性设计成功&#xff…

Android12之解封装NuMediaExtractor::setDataSource过程(四十七)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

Springboot ruoyi配置mysql备份定时任务

一、RuoYiConfig.class 新增获取备份路径方法 public static String getDataBaseBackUp() {return getProfile() "/dbBackUp";} 二、RyTask&#xff1a;新增备份数据库方法 mySqlDump方法&#xff1a;参数详见代码 package com.ruoyi.quartz.task;import cn.hut…

【动手学深度学习-Pytorch版】序列到序列的学习(包含NLP常用的Mask技巧)

序言 这一节是对于“编码器-解码器”模型的实际应用&#xff0c;编码器和解码器架构可以使用长度可变的序列作为输入&#xff0c;并将其转换为固定形状的隐状态&#xff08;编码器实现&#xff09;。本小节将使用“fra-eng”数据集&#xff08;这也是《动手学习深度学习-Pytor…

linux用户和权限命令学习记录

文章目录 版权声明root用户&#xff08;超级管理员&#xff09;su和exit命令sudo命令为普通用户配置sudo认证 用户、用户组管理用户组管理getent命令 查看权限控制认知权限信息 修改权限控制chmod修改文件、文件夹的权限权限的数字序号chown修改所属用户、用户组 版权声明 本博…

华为NFC设置教程(门禁卡/公交卡/校园卡等)

今天把华为NFC设置教程分享给大家 出门带门禁卡、校园卡、银行卡、身份证……东西又多&#xff0c;携带又麻烦&#xff0c;还容易搞丢&#xff0c;有没有一种方法可以把它们都装下&#xff1f;有&#xff01;只要一部手机&#xff0c;出门不带卡包&#xff0c;各种证件&#x…

机器学习第十课--提升树

一.Bagging与Boosting的区别 在上一章里我们学习了一个集成模型叫作随机森林&#xff0c;而且也了解到随机森林属于Bagging的成员。本节我们重点来学习一下另外一种集成模型叫作Boosting。首先回顾一下什么叫Bagging? 比如在随机森林里&#xff0c;针对于样本数据&#xff0c;…

使用命令行快速创建Vite项目

一、构建项目 在终端中使用如下命令行&#xff1a; npm create vite 二、定义项目名称 三、选择项目类型 Vanilla是我们常用的JavaScript&#xff0c;Vue和React是常用前端框架&#xff0c;可以根据自己的需要进行选择 通过上下键进行选择&#xff0c;按下回车进行确认 创建…

docker容器安装MongoDB数据库

一&#xff1a;MongoDB数据库 1.1 简介 MongoDB是一个开源、高性能、无模式的文档型数据库&#xff0c;当初的设计就是用于简化开发和方便扩展&#xff0c;是NoSQL数据库产品中的一种。是最 像关系型数据库&#xff08;MySQL&#xff09;的非关系型数据库。 它支持的数据结构…

Neo4j图数据库_web页面关闭登录实现免登陆访问_常用的cypher语句_删除_查询_创建关系图谱---Neo4j图数据库工作笔记0013

由于除了安装,那么真实使用的时候,就是导入数据了,有了关系和节点的csv文件以后如果用 cypher进行导入数据和创建关系图谱,还有进行查询,以及如果导入错误如何清空,大概是这些 用的最多的,单独把这些拿进来,总结一下,用的会比较方便. 1.实现免登陆访问: /data/module/neo4j-…

Spring学习笔记6 Bean的实例化方式

Spring学习笔记5 GoF之工厂模式_biubiubiu0706的博客-CSDN博客 Spring为Bean提供了多种实例化方式,通常包括4中(目的:更加灵活) 1.通过构造方法实例化 2.通过简单工厂模式实例化 3.通过factory-bean实例化 4.通过FactoryBean接口实例化 新建模块 spring-005 依赖 <!--S…

结构体,联合体与位段

1.结构体的内存对齐(计算结构体的大小) 1.1 为什么需要结构体内存对齐? 原因1:平台原因 不是所有的硬件平台都能访问任意地址上的任意数据的&#xff1b;某些平台只能在某些地址处取得某些特定类型的数据&#xff0c;否则抛出硬件异常。 比如&#xff0c;当一个平台要取一个…

Qt5开发及实例V2.0-第二十二章-Qt.Quick Controls 2新颖界面开发

Qt5开发及实例V2.0-第二十二章-Qt.Quick Controls 2新颖界面开发 第22章 Qt Quick Controls 2新颖界面开发22.1 Qt Quick Controls 2简介22.1.1 第一个Qt Quick Controls 2程序22.1.2 Qt Quick Controls 2程序的构成 22.2 Qt Quick Controls 2与1的比较22.2.1 ApplicationWindo…

紫光展锐6nm国产5G处理器T820_国产手机芯片5G方案

紫光展锐T820是一款采用先进6nm EUV工艺的芯片&#xff0c;采用134三丛集八核心CPU架构&#xff0c;由1个主频为 2.7GHz 的 Arm Cortex-A76 大核和 3个主频为2.3GHz 的Arm Cortex-A76大核以及4个主频为2.1GHz的 Arm Cortex-A55组成 &#xff0c;支持高达3MB 三级缓存&#xff0…

MySQL 篇

目录 1、数据库三范式 2、数据库事务的特性 3、MySQL数据库引擎 4、说说 InnoDB 与 MyISAM 的区别 5、索引是什么&#xff1f; 6、索引数据结构 7、MySQL 索引类型有哪些&#xff1f; 8、索引有什么优缺点&#xff1f; 9、索引设计原则 9、使用索引应该注意些什…

ubuntu 开启笔记本摄像头并修复画面颠倒问题

文章目录 基本环境状况&#xff1a; 没找到摄像头检查 opencv检查系统应用 键盘右侧&#xff0c;硬件层面开启摄像头画面镜像问题 基本环境 笔记本&#xff1a; 联想拯救者 系统&#xff1a; ubuntu 22.04 状况&#xff1a; 没找到摄像头 检查 opencv 使用 cv::VideoCaptu…

实验室安全教育与考试

目录 我的错题&#xff08;2个&#xff09;新知识题目&#xff08;10个&#xff09;刚开始不太理解的题目&#xff08;10个&#xff09;写在最后&#xff08;免责声明&#xff09; 我的错题&#xff08;2个&#xff09; 18.发生电气火灾时可以使用的灭火设备包括&#xff1a;&…

【100天精通Python】Day65:Python可视化_Matplotlib3D绘图mplot3d,绘制3D散点图、3D线图和3D条形图,示例+代码

1 mpl_toolkits.mplot3d 功能介绍 mpl_toolkits.mplot3d 是 Matplotlib 库中的一个子模块&#xff0c;用于绘制和可视化三维图形&#xff0c;包括三维散点图、曲面图、线图等。它提供了丰富的功能来创建和定制三维图形。以下是 mpl_toolkits.mplot3d 的主要功能和功能简介&am…