【QT】MDI应用程序设计

目录

1 MDI简介

2 文档窗口类QFormDoc的设计

3 MDI主窗口设计与子窗口的使用

3.1 主窗口界面设计

3.2 MDI子窗口的创建与加入

3.3 QMdiArea常用功能函数

3.4 MDI的信号

1 MDI简介

        传统的应用程序设计中有多文档界面(Multi-documentInterface,MDI)应用程序,Qt为设计
MDI应用程序提供了支持。
        本节的实例samp6_4是一个MDI应用程序,程序运行效果如图6-14所示。MDI应用程序就
是在主窗口里创建多个同类型的MDI子窗口,这些MDI子窗口在主窗口里显示,并共享主窗口
上的工具栏和菜单等操作功能,主窗口上的操作都针对当前活动的MDI子窗口进行。
        设计MDI应用程序需要在主窗口工作区放置一个QMdiArea作为子窗体的容器。实例samp6_4
主窗口的工作区使用一个QMdiArea组件,实例的子窗口类是QFormDoc,是一个使用QPlainTextEdit进行简单文本显示和编辑的窗体。
图6-14 MDI应用程序实例samp6_4的运行时界面
        创建的QFormDoc窗体对象作为一个子窗口加入到mdiArea组件中。QMdiArea组件类似于 实例 samp6_3 中主窗口上的 tabWidget 组件,只是 QMdiArea 提供更加完备的功能。更改 MDI 的 显示模式,可以得到与实例 samp6_3 相似的以多页组件管理的 MDI 界面效果。

2 文档窗口类QFormDoc的设计

        以可视化方式创建一个基于QWidget的类QFormDoc,设计可视化界面时,只放置一个 QPlainTextEdit组件,并以水平布局填充满整个窗口。这里不再用可视化的方式设计Action,因为 QFormDoc窗口不需要创建自己的工具栏,而是使用主窗口上的工具栏按钮对QFormDoc窗体上
的QPlainTextEdit组件进行操作。
        为QFormDoc添加一些用于文件打开和编辑操作的接口函数,QFormDoc类的完整定义如下:
class QFormDoc : public QWidget
{
    Q_OBJECT

private:
    QString mCurrentFile; //当前文件
    bool    mFileOpened=false; //文件已打开

public:
    explicit QFormDoc(QWidget *parent = 0);
    ~QFormDoc();

    void    loadFromFile(QString& aFileName); //打开文件
    QString currentFileName();//返回当前文件名
    bool    isFileOpened();//文件已经打开

    void    setEditFont();//设置字体
    void    textCut(); //cut
    void    textCopy(); //copy
    void    textPaste(); //paste

private:
    Ui::QFormDoc *ui;

};

                这些接口函数是为了在主窗口里调用,实现对MDI子窗口的操作。实现代码如下:

QFormDoc::QFormDoc(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::QFormDoc)
{
    ui->setupUi(this);

    this->setWindowTitle("New Doc"); //窗口标题
    this->setAttribute(Qt::WA_DeleteOnClose); //关闭时自动删除
}

QFormDoc::~QFormDoc()
{
    QMessageBox::information(this,"信息","文档窗口被释放");
    delete ui;
}

void QFormDoc::loadFromFile(QString &aFileName)
{//打开文件
    QFile aFile(aFileName);  //以文件方式读出
    if (aFile.open(QIODevice::ReadOnly | QIODevice::Text)) //以只读文本方式打开文件
    {
        QTextStream aStream(&aFile); //用文本流读取文件
        ui->plainTextEdit->clear();//清空
        ui->plainTextEdit->setPlainText(aStream.readAll()); //读取文本文件
        aFile.close();//关闭文件

        mCurrentFile=aFileName;//保存当前文件名
        QFileInfo   fileInfo(aFileName); //文件信息
        QString str=fileInfo.fileName(); //去除路径后的文件名
        this->setWindowTitle(str);
        mFileOpened=true;
    }
}

QString QFormDoc::currentFileName()
{
    return  mCurrentFile;
}

bool QFormDoc::isFileOpened()
{ //文件是否已打开
    return mFileOpened;
}

void QFormDoc::setEditFont()
{
    QFont   font;
    font=ui->plainTextEdit->font();

    bool    ok;
    font=QFontDialog::getFont(&ok,font);
    ui->plainTextEdit->setFont(font);
}

void QFormDoc::textCut()
{
    ui->plainTextEdit->cut();
}

void QFormDoc::textCopy()
{
    ui->plainTextEdit->copy();
}

void QFormDoc::textPaste()
{
    ui->plainTextEdit->paste();
}
         注意:作为MDI子窗口,不管其是否设置为关闭时删除,在主窗口里关闭一个MDI子窗口时,都会删除子 窗口对象。

3 MDI主窗口设计与子窗口的使用

3.1 主窗口界面设计

        要在主窗口实现MDI功能,只需在主窗口的工作区放置一个QMdiArea组件。图6·-15是设计 好的主窗口界面。
图6-15 设计时的主窗口
        在UI设计器里创建Action,并应用Action设计主工具栏。在主窗口的工作区放置一个 QMdiArea组件,然后在主窗口的构造函数里设置mdiArea填充满工作区。
QWMainWindow::QWMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::QWMainWindow)
{
    ui->setupUi(this);

    this->setCentralWidget(ui->mdiArea);
    this->setWindowState(Qt::WindowMaximized); //窗口最大化显示
    ui->mainToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
}

3.2 MDI子窗口的创建与加入

        下面是主窗口上“新建文档”按钮的响应代码:
void QWMainWindow::on_actDoc_New_triggered()
{ //新建文件
    QFormDoc *formDoc = new QFormDoc(this); //
    ui->mdiArea->addSubWindow(formDoc); //文档窗口添加到MDI
    formDoc->show(); //在单独的窗口中显示
}

        代码功能是新建一个QFormDoc类的窗口formDoc,构造函数中传入了主窗口指针,所以主窗口是formDoc的父窗口,然后使用QMdiArea的addSubWindow()函数将formDoc加入到mdiArea。

        下面是主窗口上“打开文档”按钮的响应代码:

void QWMainWindow::on_actDoc_Open_triggered()
{//打开文件
//必须先获取当前MDI子窗口,再使用打开文件对话框,否则无法获得活动的子窗口
    bool needNew=false;// 是否需要新建子窗口

    QFormDoc    *formDoc;
    if (ui->mdiArea->subWindowList().count()>0) //如果有打开的主窗口,获取活动窗口
    {
        formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();
        needNew=formDoc->isFileOpened();//文件已经打开,需要新建窗口
    }
    else
        needNew=true;

    QString curPath=QDir::currentPath();
    QString aFileName=QFileDialog::getOpenFileName(this,tr("打开一个文件"),curPath,
                 "C程序文件(*.h *cpp);;文本文件(*.txt);;所有文件(*.*)");
    if (aFileName.isEmpty())
        return; //如果未选择文件,退出

    if (needNew) //需要新建子窗口
    {
        formDoc = new QFormDoc(this);//指定父窗口,必须在父窗口为Widget窗口提供一个显示区域
        ui->mdiArea->addSubWindow(formDoc);
    }

    formDoc->loadFromFile(aFileName); //打开文件
    formDoc->show();

    ui->actCut->setEnabled(true);
    ui->actCopy->setEnabled(true);
    ui->actPaste->setEnabled(true);
    ui->actFont->setEnabled(true);
}
       通过QMdiArea::subWindowList()可以获得子窗口对象列表,从而可以判断子窗口的个数。如 果没有一个MDI子窗口,就创建一个新的窗口并打开文件。
        如果有MDI子窗口,则总有一个活动窗口,通过QMdiArea::activeSubWindow()可以获得此活 动的子窗口,通过子窗口的isFileOpened()函数判断是否打开了文件,如果没有打开过文件,就在这个活动窗口里打开文件,否则新建窗口打开文件。
        注意:一定要先获取MDI子窗口,再使用QFileDialog选择需要打开的文件。如果顺序更换了,则无法获得 正确的MDI活动子窗口。

3.3 QMdiArea常用功能函数

        QMdiArea提供了一些成员函数,可以进行一些操作,工具栏上的“关闭全部”“MDI模式” “级联展开”“平铺展开”等按钮都是调用QMdiArea类的成员函数实现的。下面是这几个按钮功 能的实现代码:
void QWMainWindow::on_actViewMode_triggered(bool checked)
{//MDI 显示模式
    if (checked) //Tab多页显示模式
    {
        ui->mdiArea->setViewMode(QMdiArea::TabbedView); //Tab多页显示模式
        ui->mdiArea->setTabsClosable(true); //页面可关闭
        ui->actCascade->setEnabled(false);
        ui->actTile->setEnabled(false);
    }
    else 子窗口模式
    {
        ui->mdiArea->setViewMode(QMdiArea::SubWindowView); //子窗口模式
        ui->actCascade->setEnabled(true); //
        ui->actTile->setEnabled(true); //
    }
}

void QWMainWindow::on_actCascade_triggered()
{ //窗口级联展开
    ui->mdiArea->cascadeSubWindows();
}

void QWMainWindow::on_actTile_triggered()
{//平铺展开
    ui->mdiArea->tileSubWindows();
}

void QWMainWindow::on_actCloseALL_triggered()
{//关闭全部子窗口
    ui->mdiArea->closeAllSubWindows();
}

其中,设置MDI视图模式用setViewMode()函数,有两种模式可以选择。
    * QMdiArea::SubWindowView是传统的子窗口模式,显示效果如图6-14所示。
    * QMdiArea::TabbedView是多页的显示模式,显示效果如图6-16所示。

图6-16多页模式下的MDI界面

3.4 MDI的信号


        QMdiArea有一个信号subWindowActivated(QMdiSubWindow*argl),在当前活动窗口切换时发射,利用此信号可以在活动窗口切换时进行一些处理,例如,在状态栏里显示活动MDI子窗口的文件名,在没有MDI子窗口时,将工具栏上的编辑功能按钮设置为禁用。下面是该信号的槽函数代码:

void QWMainWindow::on_mdiArea_subWindowActivated(QMdiSubWindow *arg1)
{//当前活动子窗口切换时
    if (ui->mdiArea->subWindowList().count()==0)
    { //若子窗口个数为零
        ui->actCut->setEnabled(false);
        ui->actCopy->setEnabled(false);
        ui->actPaste->setEnabled(false);
        ui->actFont->setEnabled(false);
        ui->statusBar->clearMessage();
    }
    else
    {
        QFormDoc *formDoc=static_cast<QFormDoc*>(ui->mdiArea->activeSubWindow()->widget());
        ui->statusBar->showMessage(formDoc->currentFileName()); //显示主窗口的文件名
    }
}

     主窗口工具栏上的“剪切”“复制”“粘贴”“字体设置”等按钮都是调用当前子窗口的相应函数,关键是获取当前MDI子窗体对象,例如,“剪切”和“字体设置”按钮的代码如下:

void QWMainWindow::on_actCut_triggered()
{ //cut
    QFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();
    formDoc->textCut();
}

void QWMainWindow::on_actFont_triggered()
{//设置字体
    QFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();
    formDoc->setEditFont();
}

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

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

相关文章

Spring源码学习-Spring流程概述(一)

Spring启动的流程 public class Test {public static void main(String[] args) {ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext("applicationContext.xml");Student bean context.getBean(Student.class);context.close();} }调用…

php低版本(7.4)配置过程中遇到的问题及基本解决手段

目前php不支持较低版本的安装&#xff0c;如果安装低版本必须借助第三方库shivammathur //将第三方仓库加入brewbrew tap shivammathur/php //安装PHPbrew install shivammathur/php/php7.4 可能出现的问题 像这样突然中止然后报错&#xff0c;一般是网络问题&#xff0c;或…

JOSEF约瑟 漏电继电器 JHOK-ZBG1 φ25mm AC220V 30-500ma 1S

系列型号 JHOK-ZBG1一体式漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG2一体式漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG1漏电继电器原为分体式固定式安装&#xff0c;为适应现行安装场合需要&#xff0c;上海约瑟继电器厂在产品原JHOK-ZBG漏电继电器基础上进行产…

Python中元祖的用法

元祖tuple(,) 元祖就是不可变的列表&#xff0c;元祖用()表示,元素与元素之间用逗号隔开,数据类型没有限制。 tu (科比,詹姆斯,乔丹) tu tuple(123) 小括号中有一个元素,有逗号就是元祖,没有就是它本身。 空的小括号就是元祖 索引和切片与列表和字符串相同 不可变指的是,…

Centos使用Docker搭建自己的Gitlab社区版16.8.0-ce.0(设置汉化 修改密码 设置SSH秘钥 添加拉取命令端口号 备份至网盘和恢复)

根据我的经验 部署Gitlab&#xff08;社区版&#xff09; 至少需要2核4g的服务器 带宽3~4M 1. 在自己电脑上安装终端&#xff1a;宝塔ssl终端 或者 FinalShell&#xff0c;根据喜好安装即可 http://www.hostbuf.com/t/988.html http://www.hostbuf.com/downloads/finalshell_w…

什么品牌洗地机最好?专业旗舰级洗地机推荐

作为一个打工族&#xff0c;很能理解大家对日常清洁繁琐的烦恼&#xff0c;尤其是在忙碌工作后难以有力气打扫卫生。这时候&#xff0c;洗地机就是解决问题的利器了。它不仅方便轻松&#xff0c;还能有效消菌杀毒&#xff0c;助力深度清洁。若你正在为选择哪款洗地机而烦恼&…

实用VBA:17.大量word文件中的文本内容进行批量替换

1.需求场景 在工作中可能会遇到需要对大量word文件中的文字内容进行批量替换的情况。相比excel的批量处理&#xff0c;个人感觉word文档中由于包含大量样式信息&#xff0c;批处理时总感觉有顾虑。一者担心影响了文档的格式&#xff0c;误修改了文档的样式&#xff0c;那后果……

计算机网络-数据通信基础知识(数据通信模型 相关术语 单工/半双工/全双工 串行/并行 同步/异步 码元 数据传输速率 带宽)

文章目录 典型的数据通信模型数据通信的相关术语设计数据通信系统要考虑的三个问题单工/半双工/全双工 串行/并行同步/异步小结码元数据传输速率的两种表示方法思考题1思考题2 带宽 典型的数据通信模型 广域网中有模拟信道&#xff0c;模拟信道能传模拟信号&#xff0c;不能传…

Vue2和Vue3生命周期映射关系及异同

目录 一、Vue2 二、Vue3 三、什么是生命周期 四、Vue2和Vue3生命周期映射关系及异同 一、Vue2 Vue是一种用于构建用户界面的渐进式JavaScript框架。它专注于视图层&#xff0c;采用了组件化的开发方式&#xff0c;使得开发者可以轻松地构建复杂的应用程序。 Vue具有以下特…

alfred自定义谷歌翻译workflow

如果要实现自定义workflow&#xff0c;则必须安装付费版的alfred&#xff0c;囊中羞涩的话可以自行淘宝。自定义步骤如下&#xff1a; 1. 新建空的workflow&#xff0c;填写基本信息 2. 开发python脚本 打开该workflow所在目录&#xff0c;进行下面步骤&#xff1a; 首先安装…

app重新签名之后,teamID会改变吗?

哈喽大家好&#xff0c;我是咕噜美乐蒂&#xff0c;很高兴又见面啦&#xff01; 在iOS和macOS开发中&#xff0c;我们经常需要对应用进行重新签名&#xff0c;以便在发布或测试时更改应用的证书或代理。在重新签名应用程序时&#xff0c;可能会出现teamID变化的情况。本文将探…

安科瑞弧光保护装置助力煤矿高压开关柜的可靠供电

摘要 在煤矿高压开关柜运行中&#xff0c;由于受到多种因素的干扰&#xff0c;中低压母线发生故障的概率较高&#xff0c;在中低压母线装设中又没有设置专门的保护&#xff0c;所以开关柜电弧光短路等问题时有发生&#xff0c;对变压器等设备造成一定的损害。鉴于此&#xff0c…

【高效开发工具系列】Intellj IDEA 2023.3 版本

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Git学习 -- 分支合并、版本修改相关

目录 learn GIT Learn Git Branching merge和rebase的使用 基础命令 版本回退 工作区和暂存区 管理修改 撤销修改 删除修改 learn GIT Learn Git Branching 这是Gitee上的Git学习教程 Learn Git Branching Git Rebase Learn Git Branching 最终的实操 merge和rebase的…

常见的6种软件测试用例设计方法

常见的软件测试用例设计方法&#xff0c;个人认为主要是下面这6种&#xff1a; 流程图法&#xff08;也叫场景法&#xff09;等价类划分法边界值分析判定表正交法错误推测法 这6种常见方法中&#xff0c;我分别按照定义、应用场景、使用步骤、案例讲解这4个部分进行讲解。 所…

thinkphp+mysql高校跳蚤二手市场交易系统vue

商品信息是卖家供应用户必不可少的一个部分。在跳蚤市场发展的整个过程中&#xff0c;商品担负着最重要的角色。为满足如今日益复杂的管理需求&#xff0c;各类管理系统程序也在不断改进。本课题所设计的普通高校网上跳蚤市场&#xff0c;使用Thinkphp5框架&#xff0c;php语言…

Java日期和时间学习记录2

1、Java的LocalDate类当前时间往未来几天和过去时间几天 import java.time.LocalDate;public class Main {public static void main(String[] args) {// 获取当前日期LocalDate currentDate LocalDate.now();System.out.println("当前日期&#xff1a;" currentDa…

Web09--jQuery基础

1、jQuery概述 1.1 什么是jQuery jQuery是一款优秀的JavaScript的轻量级框架之一&#xff0c;封装了DOM操作、事件绑定、ajax等功能。特别值得一提的是基于jQuery平台的插件非常丰富&#xff0c;大多数前端业务场景都有其封装好的工具可直接使用。 jQuery下载和版本介绍 官…

HTTP动态代理的原理及其对网络性能的影响

HTTP动态代理是一种通过代理服务器来转发HTTP请求和响应数据的网络技术&#xff0c;它可以优化网络性能、提高网络安全性&#xff0c;并解决跨域请求的问题。本文将详细介绍HTTP动态代理的原理及其对网络性能的影响。 一、HTTP动态代理的原理 HTTP动态代理的基本原理是在客户…

什么是交换机端口镜像?

热门IT课程【视频教程】-华为/思科/红帽/oraclehttps://xmws-it.blog.csdn.net/article/details/134398330 镜像可以在不影响交换机/路由器等网络设备报文正常处理流程的情况下&#xff0c;将指定源的报文复制一份到目的端口。目的端口与监控设备直接或间接相连&#xff0c;监控…