【QT】 Qt高级——Qt自定义标题栏

news2024/12/24 21:51:06

【QT】 Qt高级——Qt自定义标题栏

一、Qt自定义标题栏简介

QWidget及其子类窗体组件的标题栏受操作系统的控制,即标题栏的界面风格与操作系统的主题风格相同,工程实践中需要开发者自行定义,达到美化应用程序界面的目的。

二、Qt自定义标题栏实现

1、自定义标题栏的功能

自定义标题栏需要完成功能如下:
(1)自定义标题栏需要包含最小化按钮、最大化按钮、关闭按钮、标题标签、图标标签等图形元素。
(2)标题栏的拖拽。
(3)鼠标双击标题栏实现窗体的最大化、最小化。

2、自定义标题栏的界面布局

自定义标题栏的界面布局如下:
在这里插入图片描述

3、标题栏拖拽功能的实现

窗体的拖拽平移过程如下图:
在这里插入图片描述

当鼠标在窗体的标题栏按下并移动时,窗体会按照鼠标移动的轨迹进行平移。因此,窗体每次移动都是在当前位置按照鼠标移动的矢量进行移动。标题栏拖拽功能的实现需要实现mousePressEventmouseMoveEventmouseReleaseEvent三个事件处理函数。
MouseEvent中的globalPos()函数返回的是相对屏幕的位置坐标,而pos()则是返回鼠标在当前控件(即捕获该鼠标事件的控件)中的位置。
QWidget窗体的geometry().topLeft()则返回的是当前窗体的左上角在屏幕中的位置。

startPos = event->globalPos();// 鼠标的全局初始位置,按下时记住 
curWindowPos = geometry().topleft();// 窗体的全局位置,移动时 
endPos = event->globalPos();// 鼠标按下发生移动之后的位置,移动时 
move(curWindowPos+(startPos-endPos));// 根据矢量移动方向是初始位置减去末位置,移动时 
startPos = endPos;// 将初始位置记为上次末位置,然后执行直到释放拖拽,移动时

实现代码如下:

void TitleBar::mousePressEvent(QMouseEvent *event)
{
    // 鼠标左键按下事件
    if (event->button() == Qt::LeftButton)
    {
        // 记录鼠标左键状态
        m_leftButtonPressed = true;
        //记录鼠标在屏幕中的位置
        m_start = event->globalPos();
    }

}

void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
    // 持续按住才做对应事件
    if(m_leftButtonPressed)
    {
        //将父窗体移动到父窗体原来的位置加上鼠标移动的位置:event->globalPos()-m_start
        parentWidget()->move(parentWidget()->geometry().topLeft() +
                             event->globalPos() - m_start);
        //将鼠标在屏幕中的位置替换为新的位置
        m_start = event->globalPos();
    }

}

void TitleBar::mouseReleaseEvent(QMouseEvent *event)
{
    // 鼠标左键释放
    if (event->button() == Qt::LeftButton)
    {
        // 记录鼠标状态
        m_leftButtonPressed = false;
    }
}

4、标题栏双击实现最大化、最小化

鼠标双击事件处理函数mouseDoubleClickEvent实现如下:

void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    m_maximizeButton->click();
}
最大化、最小化、关闭按钮的槽函数如下:

void TitleBar::onClicked()
{
    QPushButton *pButton = qobject_cast<QPushButton *>(sender());
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        if (pButton == m_minimizeButton)
        {
            pWindow->showMinimized();
        }
        else if (pButton == m_maximizeButton)
        {
            pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
        }
        else if (pButton == m_closeButton)
        {
            pWindow->close();
        }
    }
}

三、Qt自定义窗体基类示例

1、自定义窗体基类的功能

自定义窗体基类的功能如下:
(1)自定义标题栏。
(2)增加内容组件,内容组件内部的界面布局完全由具体的用户决定。

2、自定义窗体基类的实现

TitleBar.h文件:

#ifndef TITLEBAR_H
#define TITLEBAR_H

#include <QWidget>
#include <QPushButton>
#include <QLabel>
#include <QHBoxLayout>
#include <QEvent>
#include <QMouseEvent>
#include <QApplication>
#include <QPoint>
#include <QPixmap>
#include <QString>
/**
 * @brief 标题栏界面组件
 * @author 
 */

class TitleBar : public QWidget
{
    Q_OBJECT
public:
    explicit TitleBar(QWidget *parent = NULL);
    /**
     * @brief 设置标题栏标题
     * @param title,参数,设置的标题
     */
    void setWindowTitle(const QString& title);
    /**
     * @brief 设置标题栏的图标
     * @param iconPath,参数,图标的路径
     */
    void SetTitleBarIcon(const QString& iconPath);

protected:
    /**
     * @brief 鼠标双击事件处理函数
     * @param event,参数,事件
     * @note 双击标题栏进行界面的最大化/还原
     */
    virtual void mouseDoubleClickEvent(QMouseEvent *event);

    /**
     * @brief 鼠标按下事件处理函数
     * @param event,参数,事件
     * @note 按下鼠标左键
     */
    virtual void mousePressEvent(QMouseEvent *event);
    /**
     * @brief 鼠标移动事件处理函数
     * @param event,参数,事件
     * @note 移动鼠标
     */
    virtual void mouseMoveEvent(QMouseEvent *event);
    /**
     * @brief 鼠标释放事件处理函数
     * @param event,参数,事件
     * @note 释放鼠标
     */
    virtual void mouseReleaseEvent(QMouseEvent *event);

    /**
     * @brief 事件过滤处理器
     * @param obj,参数
     * @param event,参数,事件
     * @return 成功返回true,失败返回false
     * @note 设置标题、图标
     */
    virtual bool eventFilter(QObject *obj, QEvent *event);

    /**
     * @brief 最大化/还原
     */
    void updateMaximize();

protected slots:
    /**
     * @brief 最小化、最大化/还原、关闭按钮点击时响应的槽函数
     */
    void onClicked();

private:
    QLabel* m_iconLabel;
    QLabel* m_titleLabel;
    QPushButton* m_minimizeButton;
    QPushButton* m_maximizeButton;
    QPushButton* m_closeButton;
    QPoint m_start;//起始点
    QPoint m_end;//结束点
    bool m_leftButtonPressed;//鼠标左键按下标记
};

#endif // TITLEBAR_H

TitleBar.cpp文件:

#include "TitleBar.h"

TitleBar::TitleBar(QWidget *parent) : QWidget(parent)
{
    setFixedHeight(30);
    setWindowFlags(Qt::FramelessWindowHint);
    m_iconLabel = new QLabel(this);
    m_iconLabel->setFixedSize(20, 20);
    m_iconLabel->setScaledContents(true);

    m_titleLabel = new QLabel(this);
    m_titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    m_minimizeButton = new QPushButton(this);
    m_minimizeButton->setFixedSize(27, 22);
    m_minimizeButton->setObjectName("minimizeButton");

    m_maximizeButton = new QPushButton(this);
    m_maximizeButton->setFixedSize(27, 22);
    m_maximizeButton->setObjectName("maximizeButton");

    m_closeButton = new QPushButton(this);
    m_closeButton->setFixedSize(27, 22);
    m_closeButton->setObjectName("closeButton");

    QHBoxLayout* layout = new QHBoxLayout;
    layout->addWidget(m_iconLabel);
    layout->addStretch(1);
    layout->addWidget(m_titleLabel);
    layout->addStretch(1);
    layout->addWidget(m_minimizeButton);
    layout->addWidget(m_maximizeButton);
    layout->addWidget(m_closeButton);
    setLayout(layout);

    setProperty("titleBar", true);
    setObjectName("titleBar");

    connect(m_minimizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
    connect(m_maximizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
    connect(m_closeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
}

void TitleBar::setWindowTitle(const QString &title)
{
    m_titleLabel->setAlignment(Qt::AlignCenter);
    m_titleLabel->setText(title);
}

void TitleBar::SetTitleBarIcon(const QString &iconPath)
{
    QPixmap map(iconPath);
    m_iconLabel->setPixmap(map);
}

void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    m_maximizeButton->click();
}

void TitleBar::mousePressEvent(QMouseEvent *event)
{
    // 鼠标左键按下事件
    if (event->button() == Qt::LeftButton)
    {
        // 记录鼠标左键状态
        m_leftButtonPressed = true;
        //记录鼠标在屏幕中的位置
        m_start = event->globalPos();
    }

}

void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
    // 持续按住才做对应事件
    if(m_leftButtonPressed)
    {
        //将父窗体移动到父窗体原来的位置加上鼠标移动的位置:event->globalPos()-m_start
        parentWidget()->move(parentWidget()->geometry().topLeft() +
                             event->globalPos() - m_start);
        //将鼠标在屏幕中的位置替换为新的位置
        m_start = event->globalPos();
    }

}

void TitleBar::mouseReleaseEvent(QMouseEvent *event)
{
    // 鼠标左键释放
    if (event->button() == Qt::LeftButton)
    {
        // 记录鼠标状态
        m_leftButtonPressed = false;
    }
}

bool TitleBar::eventFilter(QObject *obj, QEvent *event)
{
    switch(event->type())
    {
    //设置标题
    case QEvent::WindowTitleChange:
    {
        QWidget *pWidget = qobject_cast<QWidget *>(obj);
        if (pWidget)
        {
            m_titleLabel->setText(pWidget->windowTitle());
            return true;
        }
    }
    //设置图标
    case QEvent::WindowIconChange:
    {
        QWidget *pWidget = qobject_cast<QWidget *>(obj);
        if (pWidget)
        {
            QIcon icon = pWidget->windowIcon();
            m_iconLabel->setPixmap(icon.pixmap(m_iconLabel->size()));
            return true;
        }
    }
    // 窗口状态变化、窗口大小变化
    case QEvent::WindowStateChange:
    case QEvent::Resize:
        updateMaximize();
        return true;
    }
    return QWidget::eventFilter(obj, event);
}

void TitleBar::updateMaximize()
{
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        bool bMaximize = pWindow->isMaximized();
        if (bMaximize)
        {
            m_maximizeButton->setToolTip(tr("Restore"));
            m_maximizeButton->setProperty("maximizeProperty", "restore");
        }
        else
        {
            m_maximizeButton->setProperty("maximizeProperty", "maximize");
            m_maximizeButton->setToolTip(tr("Maximize"));
        }

        m_maximizeButton->setStyle(QApplication::style());
    }
}

void TitleBar::onClicked()
{
    QPushButton *pButton = qobject_cast<QPushButton *>(sender());
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        if (pButton == m_minimizeButton)
        {
            pWindow->showMinimized();
        }
        else if (pButton == m_maximizeButton)
        {
            pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
        }
        else if (pButton == m_closeButton)
        {
            pWindow->close();
        }
    }
}

QWindowBase.h文件:

#ifndef QWINDOWBASE_H
#define QWINDOWBASE_H

#include <QFrame>
#include <QWidget>
#include <QVBoxLayout>
#include "TitleBar.h"

/**
 * @brief 界面组件基类
 * @note QWindowBase界面组件主要用作顶层窗口,对于非顶层窗口的界面组件使用QWidget。
 */
class QWindowBase : public QFrame
{
    Q_OBJECT
public:
    QWindowBase(QFrame* parent = NULL);
    /**
     * @brief 设置标题
     * @param title,输入参数,标题内容
     */
    void setWindowTitle(const QString& title);
    /**
     * @brief 设置标题栏的图标
     * @param iconPath,输入参数,图标资源路径
     */
    void SetTitleBarIcon(const QString& iconPath);
    /**
     * @brief 获取内容组件对象指针
     * @return 返回QWidget*
     */
    QWidget* contentWidget();
    /**
     * @brief 设置标题栏高度
     * @param h,输入参数,标题栏高度
     */
    void setWindowTitleHeight(int h);

private:
    QWidget* m_contentWidget;//内容组件
    TitleBar* m_titleBar;//标题栏
    QVBoxLayout* m_layout;//布局管理器
};

#endif // QWINDOWBASE_H
QWindowBase.cpp文件:

#include "QWindowBase.h"

QWindowBase::QWindowBase(QFrame *parent): QFrame(parent)
{
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
    m_titleBar = new TitleBar(this);
    m_contentWidget = new QWidget(this);
    m_contentWidget->setObjectName("Contents");
    m_layout = new QVBoxLayout;
    m_layout->addWidget(m_titleBar);
    m_layout->addWidget(m_contentWidget);
    m_layout->setSpacing(0);
    m_layout->setContentsMargins(0, 0, 0, 0);

    setLayout(m_layout);
}

void QWindowBase::setWindowTitle(const QString &title)
{
    m_titleBar->setWindowTitle(title);
}

void QWindowBase::SetTitleBarIcon(const QString &iconPath)
{
    m_titleBar->SetTitleBarIcon(iconPath);
}

QWidget *QWindowBase::contentWidget()
{
    return m_contentWidget;
}

void QWindowBase::setWindowTitleHeight(int h)
{
    m_titleBar->setFixedHeight(h);
}
CommonHelper.h文件:

#ifndef COMMONHELPER_H
#define COMMONHELPER_H

#include <QString>
#include <QFile>
#include <QApplication>
#include <QDebug>
#include <QColor>
#include <QPalette>

/**
 * @brief 通用功能辅助类
 */
class CommonHelper
{
public:
    /**
     * @brief 为应用程序设置QSS样式表
     * @param filepath,输入参数,QSS文件路径
     */
    static void setStyleSheet(const QString& filepath)
    {
        //加载样式文件
        QFile qss(filepath);
        if(qss.open(QFile::ReadOnly))
        {
            QString stylesheet = QLatin1String(qss.readAll());
            QString paletteColor = stylesheet.mid(20, 7);
            qApp->setPalette(QPalette(QColor(paletteColor)));
            qApp->setStyleSheet(stylesheet);
        }
    }
};

#endif // COMMONHELPER_H
main.cpp文件:

#include <QApplication>
#include "CommonHelper.h"
#include "QWindowBase.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QTreeView>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWindowBase w;
    w.setWindowTitle("WidgetBase");
    QPushButton* button1 = new QPushButton("OK");
    QHBoxLayout* hLayout1 = new QHBoxLayout;
    hLayout1->addStretch(1);
    hLayout1->addWidget(button1);

    QVBoxLayout* layout = new QVBoxLayout;
    QTreeView* treeView = new QTreeView;
    layout->addWidget(treeView);
    layout->addLayout(hLayout1);
    layout->addStretch(1);
    w.contentWidget()->setLayout(layout);
    w.setWindowTitleHeight(40);
    w.show();
    CommonHelper::setStyleSheet("://qss/lightblue.qss");
    return a.exec();
}

工程文件:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = TitleBarDemo
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
    TitleBar.cpp \
    QWindowBase.cpp

HEADERS += \
    TitleBar.h \
    CommonHelper.h \
    QWindowBase.h

RESOURCES += \
    TitileBarDemo.qrc

工程目录结构:
在这里插入图片描述

3、自定义窗体基类结果展示
运行结果:
在这里插入图片描述

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

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

相关文章

每日学术速递5.1

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.Putting People in Their Place: Affordance-Aware Human Insertion into Scenes 标题&#xff1a;把人放在他们的位置&#xff1a;可供感知的人类插入场景 作者&#xff1a;Sumit…

项目管理:项目进度跟踪的好处有哪些?

项目进度跟踪主要针对项目计划、任务和项目成员三个方面&#xff0c;即为了了解整个项目计划完成情况、了解项目的实际进展情况、解成员工作完成情况。 项目跟踪可以证明计划是否可执行&#xff0c;可以说明计划是否可以被完成。 在项目执行过程中&#xff0c;我们也可以通过跟…

网络安全合规-Tisax(汽车安全评估讯息交换平台)一

**TISAX&#xff08;汽车安全评估讯息交换平台&#xff08;可信信息安全评估交换平台&#xff09;&#xff09;**是2017年由德国汽车工业联合会(VDA) 联合欧洲网络交换所(ENX) 所推出的资讯交换平台&#xff0c;通过应用欧洲网络交换协会&#xff08;ENX&#xff09;和德国汽车…

rk3568 适配摄像头 (双摄)

rk3568 适配摄像头 (mipi 双摄) rk3568 适配双摄像其实就是逐个适配单摄像头&#xff0c;只是两颗摄像头的数据总线可能不同(cifmipi)&#xff0c;也可能相同(mipi(2lane) x 2)。几乎相同的上电时许&#xff0c;不同的时钟信号和总线协议决定加载过程会略有不同。 提示&#…

CSDN周赛第49期 - 也谈马拉车

前言 C站的周赛已经很久没有新题了&#xff0c;已考过的题目我差不多都写过题解&#xff0c;若再重复写类似的文章&#xff0c;反而会降低博文质量分&#xff0c;而想要换个角度&#xff0c;却又难以找到动笔的欲望。所以虽然比赛发生在五一假期之前&#xff0c;但直到现在五一…

camunda升级事件的用途

在Camunda中&#xff0c;升级事件&#xff08;Escalation Event&#xff09;是一种可以在工作流中出现异常情况时触发相应操作的事件类型。使用升级事件可以帮助工作流更加灵活地处理异常情况&#xff0c;以确保工作流的正常运行。 使用升级事件可以处理以下情况&#xff1a; …

【Java EE 初阶】如何保证线程安全

目录 1.线程是什么&#xff1f; 2.线程安全&#xff08;重点&#xff09; 1.概念&#xff1a; 1.举例&#xff1a;用两个线程分别对同一个变量做五万次自增&#xff0c;观察答案是否符合预期 那么是哪些原因造成了这种线程不安全的现象呢&#xff1f;我们一起来分析一下&am…

搭建Plex媒体服务器,打造家庭多媒体中心【公网远程访问】

文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1.前言 用手机或者平板电脑看视频&#xff0c;已经算是生活中稀松平常的场景了&#xff0c;特别是各…

MAC安装MySQL

安装MySQL 登录官网dev.mysql.com/downloads/m… 下载社区版mysql&#xff0c;选择dmg格式的安装包。下载完成后&#xff0c;开始安装。 注意&#xff1a;选择Use Legacy Password Encryption。 解决无法启动MySQL问题 打开设置中的mysql图标&#xff0c;发现红点&#xff0…

Syslog-ng RHEL 的安装和配置

syslog-ng 作为 syslog 的替代工具&#xff0c;可以完全替代 syslog 的服务&#xff0c;并且通过定义规则&#xff0c;实现更好的过滤功能。 作为运维来说一个好的日志工具比什么都重要。 通常我们会管理不同的服务器&#xff0c;因此我们需要把日志集中一下以便于快速查找。…

GUI编程(二)

Swing Swing是GUI&#xff08;图形用户界面&#xff09;开发工具包。 早期的AWT&#xff08;抽象窗口工具包&#xff09;组件开发的图形用户界面&#xff0c;要依赖本地系统&#xff0c;当把AWT组件开发的应用程序移植到其他平台的系统上运行时&#xff0c;不能保证其外观风格…

贪心刷题~

1、洛谷P2240 【深基12.例1】部分背包问题 贪心策略&#xff1a;拿金币单价高的。 #include<iostream> #include<cstring> #include<algorithm> using namespace std;struct gold{int v;int m; } q[101];bool cmp(gold a,gold b){return a.v*b.m>b.v*a.m…

SpringCloud-微服务Eureka服务注册中心

微服务&服务注册中心 前言一、微服务1.什么是微服务2.单体架构和微服务架构2.1.单体架构2.2.微服务架构 二、服务注册中心1.服务注册中心简介2.Eureka服务注册中心2.1.Eureka Server开发2.2 Eureka Client开发 3.Eureka的自我保护机制3.1.Eureka自我保护机制简介3.2.Eureka…

MySQL数据库连接超时自动断开的解决方案

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

windows下msys2编译64位的ffmpeg源码

目前遇到过两次需求&#xff0c;需要编译ffmpeg源码。网上下载的编译好的源码里面可能不全&#xff0c;很多时候需要自行编译源码。本文介绍自行编译ffmpeg64位源码&#xff08;32位通过相似的方式为编译成功&#xff0c;不知道原因&#xff09; 环境&#xff1a; 2023.5.4下载…

团队密码管理器Passbolt的安装

老苏下载了吴恩达联手 OpenAI 推出的 Prompt for developer 课程&#xff0c;总长度大概在一个半小时左右&#xff0c;可以让我们学习正确的 ChatGPT Prompt 工程 虽然课程对话是英文&#xff0c;但有中文字幕&#xff0c;课程地址&#xff1a;https://www.aliyundrive.com/s/…

[Gitops--9]微服务项目sangomall代码配置修改及资源清单文件

微服务项目sangomall代码配置修改及资源清单文件 1. 中间件的地址 1.1 Nacos 集群外 nacos-server.intra.com 192.168.31.211集群内 nacos-server.sangomall.svc.cluster.local. nacos-server.sangomall.svc.cluster.local.:88481.2 Redis 集群内 redis.sangomall.svc.c…

ipad有必要用手写笔吗?电容笔和Apple pencil区别

与Apple Pencil最大的不同之处&#xff0c;在于普通的电容笔并不具备着重力压感&#xff0c;而是会给人一种倾斜的压感。如果不是频繁作画&#xff0c;那就用一支普通的电容笔。这种电容笔不但可以用于办公室&#xff0c;也可以用于记笔记、做练习。再说了&#xff0c;一支苹果…

深入理解 Linux 内核(二)

系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核 深入理解 Linux 内核&#xff08;二&#xff09; Linux 设备驱动程序 Linux设备驱动开发详解 文章目录 系列文章目录五、定时测量1、时钟和定时器电路2、Linux 计时体系结构&#xff08;1&#xff09;计时体系机构的数据…

200G 400G光模块介绍

200G 光模块封装有2种&#xff0c;分别是QSFP56和QSFP-DD。 200G QSFP56有2种光模块&#xff0c;第一种是200G QSFP56 SR4&#xff0c;第二种是200G QSFP56 FR。 200G QSFP56 SR4的封装形式是QSFP56&#xff0c;速率是200G&#xff0c;波长是850nm&#xff0c;最远传输距离是10…