《四》系统模块整体功能关联与实现

在上一篇里,我们完成了动作的创建,那么这一次,我们把它加载到界面上,把需要是实现的动作都加上。

MyWord::MyWord(QWidget *parent)
    : QMainWindow(parent)
{
    mdiArea=new QMdiArea;
    mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    setCentralWidget(mdiArea);

    connect(mdiArea,SIGNAL(subWindowActivated(QMdiSubWindow*)),this,SLOT(updateMenus()));
    windowMapper=new  QSignalMapper(this);
    //映射器重新发送信号,根据信号设置活动窗口
    connect(windowMapper,SIGNAL(mapped(QWidget*)),this,SLOT(setActiveSubWindow(QWidget*)));

    //创建菜单、工具栏、状态栏等相关操作(动作集合)
    createActions();
    
    createMenus();//调用创建菜单实现
    createToolBars();//调用创建工具条
    updateMenus();//更新菜单条目

    resize(800,600);
    setWindowTitle(tr("Office办公自动化文字编辑 软件 V2.1"));
    setUnifiedTitleAndToolBarOnMac(true);
}

上一次我们玩还曾了create Actions(),接下来,我们要完成createMenus(),createToolBars()等功能。

void MyWord::createMenus()
{
    //文件菜单
    fileMenu=menuBar()->addMenu(tr("文件(&F)"));
    fileMenu->addAction(newAct);
    fileMenu->addAction(openAct);
    fileMenu->addSeparator();//添加分隔符
    fileMenu->addAction(saveAct);
    fileMenu->addAction(saveAsAct);
    fileMenu->addSeparator();
    fileMenu->addAction(printAct);
    fileMenu->addAction(printPreviewAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);
}

创建菜单,通过menuBar()的addMenu函数添加,再往里面添加动作,顺便还添加了分隔符addSeparator()

其他也一样添加进去就好了

//编辑菜单
    editMenu=menuBar()->addMenu(tr("编辑(&E)"));
    editMenu->addAction(undoAct);
    editMenu->addAction(redoAct);
    editMenu->addSeparator();
    editMenu->addAction(cutAct);
    editMenu->addAction(copyAct);
    editMenu->addAction(pasteAct);

    //格式菜单
    formatMenu=menuBar()->addMenu(tr("格式(&O)"));

    fontMenu=formatMenu->addMenu(tr("字体(&D)"));//字体子菜单
    fontMenu->addAction(boldAct);
    fontMenu->addAction(italicAct);
    fontMenu->addAction(underlineAct);

    alignMenu=formatMenu->addMenu(tr("段落"));
    alignMenu->addAction(leftAlignAct);
    alignMenu->addAction(centerAct);
    alignMenu->addAction(rightAlignAct);
    alignMenu->addAction(justifyAct);
    formatMenu->addAction(colorAct);

    //窗口
    windowMenu=menuBar()->addMenu(tr("窗口(&W)"));
    updateWindowMenu();
    connect(windowMenu,SIGNAL(aboutToShow()),this,SLOT(updateWindowMenu()));
    menuBar()->addSeparator();

    //帮助菜单
    helpMenu=menuBar()->addMenu(tr("帮助(&H)"));
    helpMenu->addAction(aboutAct);
    helpMenu->addSeparator();
    helpMenu->addAction(aboutQtAct);

 

在窗口这个动作里,我们链接函数就好了

Qmenu类下有一个信号为 aboutToShow,该信号在Qmenu展开时触发。

所以:

在连接的槽函数里我们去添加:

void MyWord::updateWindowMenu()
{
//首先清空菜单,然后再添加各个菜单动作
    windowMenu->clear();
    windowMenu->addAction(closeAct);
    windowMenu->addAction(closeAllAct);
    windowMenu->addSeparator();

    windowMenu->addAction(tileAct);
    windowMenu->addAction(cascadeAct);
    windowMenu->addSeparator();

    windowMenu->addAction(nextAct);
    windowMenu->addAction(previousAct);
    windowMenu->addSeparator();
    //如果有活动窗口,则显示分隔条
    QList<QMdiSubWindow*> windows=mdiArea->subWindowList();
    separatorAct->setVisible(!windows.isEmpty());

    //遍历各个子窗口,显示当前已打开的文档子窗口项
    for(int i=1;i<windows.size();i++){
        MyChild *child=qobject_cast<MyChild*>(windows.at(i)->widget());

        QString text;
        if(i<9){
            text=tr("&%1 %2").arg(i+1).arg(child->userFriendlyCurrentFile());
        }else{
            text=tr("%1 %2").arg(i+1).arg(child->userFriendlyCurrentFile());
        }
//添加动作作到菜单,设置动作可以选择
        QAction *action=windowMenu->addAction(text);
        action->setCheckable(true);
 //设置当前活动窗口动作作为选中状态
        action->setChecked(child==activeMyChild());
//关联动作的触发信号到信号映射器的map()槽,这个槽会发送mapped()信号
        connect(action,SIGNAL(triggered()),windowMapper,SLOT(map()));
//动作作与相应的窗口部件进行映射,在发送mapped()信号时就会以这个窗口部件为参数
        windowMapper->setMapping(action,windows.at(i));

    }
    enabledText();//使得字体设置菜单可用
}

接下来就是要创建工具条了:

跟创建菜单行为其实差不多,就是函数名字稍微变了一下:

void MyWord::createToolBars()
{
    //文件
    fileToolBar=addToolBar(tr("文件"));
    fileToolBar->addAction(newAct);
    fileToolBar->addAction(openAct);
    fileToolBar->addSeparator();
    fileToolBar->addAction(saveAct);
    fileToolBar->addAction(printAct);

    //编辑
    editToolBar=addToolBar(tr("文件"));
    editToolBar->addAction(undoAct);
    editToolBar->addAction(redoAct);
    editToolBar->addSeparator();
    editToolBar->addAction(cutAct);
    editToolBar->addAction(copyAct);
    editToolBar->addAction(pasteAct);

    //格式
    formatToolBar=addToolBar(tr("格式"));
    formatToolBar->addAction(boldAct);
    formatToolBar->addAction(italicAct);
    formatToolBar->addAction(underlineAct);
    formatToolBar->addSeparator();
    formatToolBar->addAction(leftAlignAct);
    formatToolBar->addAction(rightAlignAct);
    formatToolBar->addAction(justifyAct);
    formatToolBar->addSeparator();
    formatToolBar->addAction(colorAct);

    //组合
    addToolBarBreak(Qt::TopToolBarArea);//
    comboToolBar=addToolBar(tr("组合选择"));
    comboStyle=new QComboBox();
    comboToolBar->addWidget(comboStyle);
    comboStyle->addItem("标准");
    comboStyle->addItem("项目符号(●)");
    comboStyle->addItem("项目符号(○)");
    comboStyle->addItem("项目符号(□)");
    comboStyle->addItem("编号(1.2.3.)");
    comboStyle->addItem("编号(a.b.c.)");
    comboStyle->addItem("编号(A.B.C.)");
    comboStyle->addItem("编号(ⅰ.ⅱ.ⅲ.)");
    comboStyle->addItem("编号(Ⅰ.Ⅱ.Ⅲ.)");
    comboStyle->setStatusTip("段落加上标号或者编号");

    connect(comboStyle,SIGNAL(activated(int)),this,SLOT(textStyle(int)));

    comboFont=new QFontComboBox();
    comboToolBar->addWidget(comboFont);
    comboFont->setStatusTip("更改字体");
    connect(comboFont,SIGNAL(activated(QString)),this,SLOT(textFamily(QString)));

    comboSize=new QComboBox();
    comboToolBar->addWidget(comboSize);
    comboSize->setEditable(true);
    comboSize->setStatusTip("更改字体");

    QFontDatabase db;
    foreach(int size,db.standardSizes()){
        comboSize->addItem(QString::number(size));
    }
}

 把他们连接到对应槽函数,我们一步一步去实现就好了,

Qt foreach是一种用于遍历容器类型的语法结构。与传统的for循环相比,foreach更加易读、易写、易错,由此减少代码出错的概率。Qt foreach在Qt 4.0中被引入,可以用于遍历数组、QList、QVector、QSet、QMap和QHash等容器类型。

foreach (声明变量, 容器) {
    ……          
}

 接着我们把细节一点一点去完善:

//判断是否有活动子窗口用activeMyChild()函数
MyChild *MyWord::activeMyChild()
{
//若有活动窗口,则将其内的中心部件转换为MyChild类型,若没有直接返回0
    if(QMdiSubWindow *activeSubWindows=mdiArea->activeSubWindow()){
        return  qobject_cast<MyChild*>(activeSubWindows->widget());
    }
    return 0;
}
//发现子窗口操作
QMdiSubWindow *MyWord::findMyChild(const QString &filename)
{
    /*canonicalFilePath ()可以除去路径中符号链接,如“.”和“..”等符号。这个

     *函数只是将加载文件的路径首先保存到canonicalFilePath中,然后再进行一些状态的设置*/
    QString canonicalFilePath=QFileInfo(filename).canonicalFilePath();
//遍历整个多文档区域的所有子窗口
    foreach (QMdiSubWindow *window, mdiArea->subWindowList()) {
        MyChild *myChild=qobject_cast<MyChild*>(window->widget());
        if(myChild->currentFile()==canonicalFilePath){
            return window;
        }
    }
    return 0;
}
void MyWord::setActiveSubWindow(QWidget *window)
{
    if(!window){
        return;
    }
    mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow*>(window));
}
MyChild *MyWord::createMyChild()
{
    MyChild *child = new MyChild;

    mdiArea->addSubWindow(child);
    connect(child,SIGNAL(copyAvailable(bool)),cutAct,SLOT(setEnabled(bool)));
    connect(child,SIGNAL(copyAvailable(bool)),copyAct,SLOT(setEnabled(bool)));

    return  child;
}

还有其他一些动作的函数没有实现,下一期就写出来!!!

感谢阅读!!!!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

工厂数字化转型实现路线

工厂数字化转型实现路线 随着科技的飞速发展&#xff0c;数字化转型已成为当今社会的热门话题。尤其是对于工厂企业而言&#xff0c;数字化转型更是一种必然趋势。然而&#xff0c;在这个过程中&#xff0c;许多企业面临着种种困难和挑战。因此&#xff0c;探讨工厂企业数字化转…

NASA数据即——Aqua AIRS 第 3 级光谱出射长波辐射 (OLR) 月报 (AIRSIL3MSOLR)

Aqua AIRS Level 3 Spectral Outgoing Longwave Radiation (OLR) Monthly (AIRSIL3MSOLR) Aqua AIRS 第 3 级光谱出射长波辐射 (OLR) 月报 (AIRSIL3MSOLR) 简介 这个 L3 光谱出射长波辐射&#xff08;OLR&#xff09;是根据密歇根大学黄向磊开发的算法&#xff0c;利用 AIRS…

2024精选7个wordpress模板

通用多用途wordpress模板 中国红WordPress模板&#xff0c;适合服务行业企业建站的通用多用途wordpress模板。 WordPress是一款使用PHP语言开发的开源内容管理系统(CMS)&#xff0c;最初设计用于个人博客&#xff0c;但随着时间的发展&#xff0c;它已经演化成为一个功能强大的…

【算法优选】 动态规划之子数组、子串系列——壹

文章目录 &#x1f38b;前言&#x1f38b;最大子数组和&#x1f6a9;题目描述&#x1f6a9;算法思路&#x1f6a9;代码实现 &#x1f334;环形子数组的最大和&#x1f6a9;题目描述&#x1f6a9;算法思路&#xff1a;&#x1f6a9;代码实现 &#x1f332;乘积最大子数组&#x…

【PostgreSQL支持中文的全文检索插件(zhparser)】

PostgreSQL本身是支持全文检索的&#xff0c;提供两个数据类型&#xff08;tsvector,tsquery&#xff09;&#xff0c;并且通过动态检索自然语言文档的集合&#xff0c;定位到最匹配的查询结果。其内置的默认的分词解析器采用空格进行分词&#xff0c;但是因为中文的词语之间没…

想要安装Word、Excel、PowerPoint,但却找不到对应软件?

前言 前几天有小伙伴在找Word和Excel软件&#xff0c;但找了半天都没发现怎么安装。 这件事情其实很简单&#xff0c;那就是Word、Excel并不是单独的一个个软件&#xff0c;而是集成在MS Office套件里的。 咱们大部分人常用的办公软件大概是Word、Excel和PowerPoint这三个。还…

保研机试之【设备驱动程序】

B选项&#xff1a; 综上&#xff0c;我认为这道题选择D~

Host is not allowed to connect to this MySQL server解决方法

在阿里云服务器上安装了Mysql数据库&#xff0c;在阿里云上使用一切正常。我用navicat 去连接服务器时显示Host is not allowed to connect to this MySQL server。 ​ 看见这个错误&#xff0c;第一反应是是不是阿里云服务器防火墙没有配置mysq的出入站规则。去阿里云检查了一…

Day 46 139.单词拆分

单词拆分 给定一个非空字符串 s 和一个包含非空单词的列表 wordDict&#xff0c;判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。 说明&#xff1a; 拆分时可以重复使用字典中的单词。 你可以假设字典中没有重复的单词。 示例 1&#xff1a; 输入: s “leet…

Nginx配置Referer防盗链

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 HTTP Referer是Hea…

ASP.NET银行大厅自助信息系统的开发与实现

摘 要 本毕业设计在基于银行业务大厅现有业务的基础上&#xff0c;针对自助银行的概念和其独有特点&#xff0c;通过.NETSQL技术&#xff0c;开发一个简单的银行大厅自助信息系统&#xff0c;完成一些自助银行的业务需求如帐户信息查询、帐户挂失、自助交费、留言、新闻查询…

惠普发布全新AI战略,重塑办公空间 引领企业智能化新浪潮

近日、全球知名科技公司惠普在北京隆重举办了以“用智能&#xff0c;开启无限可能”为主题的2024惠普商用AI战略暨AI PC新品发布会&#xff0c;此次盛会标志着惠普在人工智能领域迈出了重要一步&#xff0c;惠普紧跟时代步伐&#xff0c;推出了更高效、更安全、更灵活的AI PC产…

AI与人类生活的融合:安克创新CEO阳萌的深度洞见

安克创新CEO阳萌分享了他对人工智能未来发展的深刻见解。阳萌不仅深入探讨了大模型技术的应用前景&#xff0c;还对AI与人类生活的融合提出了引人入胜的思考。以下是对这次访谈内容的总结和分析。 大模型技术的现实应用 阳萌提到&#xff0c;尽管大模型在处理通用知识方面表…

huggingface 笔记:pipeline

1 介绍 pipeline() 是使用预训练模型进行推理的最简单和最快速的方式。可以针对不同模态的许多任务直接使用 pipeline() 2 举例&#xff1a;情感分析 2.1 创建pipeline实例 from transformers import pipelineclassifier pipeline("sentiment-analysis") #首先创…

[Java EE] 文件IO (二):文件内容读写-----数据流

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

使用 RyTuneX 增强您的 Windows 10 和 11 体验 – Rayen Ghanmi 的首选优化器。

&#x1f4dd; 关于 RyTuneX 是使用 WinUI 3 框架构建的尖端优化器&#xff0c;旨在增强 Windows 设备&#x1f680;的性能。 RyTuneX 专为 Windows 10 和 11 打造&#xff0c;使用户能够毫不费力地删除顽固的预装应用程序并优化系统资源&#x1f6e0;️。 &#x1f680; 功能…

在线caj转换成pdf免费吗?caj变成pdf很容易!点进来!

在数字化阅读日益盛行的今天&#xff0c;各种电子文献格式层出不穷&#xff0c;其中CAJ和PDF无疑是两种最为常见的格式。CAJ是中国知网推出的一种专用全文阅读格式&#xff0c;而PDF则因其跨平台、不易被修改的特性&#xff0c;受到了广大读者的青睐。因此&#xff0c;将CAJ格式…

【Kibana】快速上手Kibana平台(KQL)

文章目录 快速使用Kibana平台常用查询语句KQL基本查询覆合查询模糊查询 目前市面上大部分的公司的日志系统都是使用ELK系统&#xff0c;因此我们进行工作必须得掌握Kibana平台的基本使用&#xff0c;这里主要说明怎么“快速使用Kibana平台”以及记录一些常用的“KQL语言”。 快…

鸿蒙内核源码分析(消息封装篇) | 剖析LiteIpc(上)进程通讯内容

基本概念 LiteIPC是OpenHarmony LiteOS-A内核提供的一种新型IPC&#xff08;Inter-Process Communication&#xff0c;即进程间通信&#xff09;机制&#xff0c;为轻量级进程间通信组件&#xff0c;为面向服务的系统服务框架提供进程间通信能力&#xff0c;分为内核实现和用户…

centos7中如何优雅的动态切换jdk版本?

在 CentOS 7 中动态切换 JDK 版本可以通过多种方法实现&#xff0c;其中最常见的方法是使用 alternatives 命令&#xff0c;这是 CentOS 和其他基于 Red Hat 的系统中用于管理多个软件版本的标准工具。下面我会详细介绍如何使用 alternatives 命令来切换 JDK 版本。 步骤 1: 安…