基于QTreeWidget实现多级组织结构

基于QTreeWidget实现多级组织结构以及带Checkbox的选择树

采用基于QWidget+Mingw实现的原生的消息气泡
通过QTreeWidget控件实现的多级组织结构树。

基于QTreeWidget实现多级组织结构代码已上传到【https://gitee.com/duyanjun/bubbleChat.git】

目录

  • 基于QTreeWidget实现多级组织结构以及带Checkbox的选择树
  • 1、效果图
  • 2、运行
    • 2.1、从git导入
    • 2.2、修改头像图片的路径
    • 2.3、运行
    • 2.4、实现

1、效果图

在这里插入图片描述在这里插入图片描述在这里插入图片描述

2、运行

2.1、从git导入

文件 -> 新建文件或项目 -> Import Project -> Git Clone
【https://gitee.com/duyanjun/QT_treeDemo.git】

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2、修改头像图片的路径

运行本Demo需要修改mainwindow.cpp第130行代码中的images目录的绝对路径;

在这里插入图片描述

2.3、运行

在这里插入图片描述

2.4、实现

1)、主画面部局

在画面添加QTreeWidget控件

在这里插入图片描述
2)、人员节点部局

整体部局采用横向部局,依次是头像和(姓名+心情),(姓名+心情)采用纵向部局

在这里插入图片描述
3)、main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

4)、MainWindow类
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTreeWidgetItem>
#include <QPixmap>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private slots:
    void onItemExpanded(QTreeWidgetItem * item);
    void onItemCollapsed(QTreeWidgetItem * item);
    void onItemClicked(QTreeWidgetItem * item, int column);

private:
    void initTree();

    QTreeWidgetItem* addChildNode(QTreeWidgetItem *parent, int index, QString namePre);

    QTreeWidgetItem* addChildEmpNode(QTreeWidgetItem *parent, int index);
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "departnodeitem.h"
#include "EmployeeNodeItem.h"

#include <QList>
#include <QPainter>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initTree();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onItemExpanded(QTreeWidgetItem *item)
{
    bool bIsChild = item->data(0, Qt::UserRole).toBool();
    if (!bIsChild) {
        DepartNodeItem *departNode = dynamic_cast<DepartNodeItem*>(ui->tree->itemWidget(item, 0));
        if (departNode) {
            departNode->setExpanded(true);
        }
    }
}

void MainWindow::onItemCollapsed(QTreeWidgetItem *item)
{
    bool bIsChild = item->data(0, Qt::UserRole).toBool();
    if (!bIsChild) {
        DepartNodeItem *departNode = dynamic_cast<DepartNodeItem*>(ui->tree->itemWidget(item, 0));
        if (departNode) {
            departNode->setExpanded(false);
        }
    }
}

void MainWindow::onItemClicked(QTreeWidgetItem *item, int column)
{
    bool bIsChild = item->data(0, Qt::UserRole).toBool();
    if (!bIsChild)
    {
        item->setExpanded(!item->isExpanded());
    }
}


void MainWindow::initTree()
{
    ui->tree->setHeaderHidden(true);
    //展开和收缩时信号,以达到变更我三角图片;
    connect(ui->tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(onItemClicked(QTreeWidgetItem *, int)));
    connect(ui->tree, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(onItemExpanded(QTreeWidgetItem *)));
    connect(ui->tree, SIGNAL(itemCollapsed(QTreeWidgetItem *)), this, SLOT(onItemCollapsed(QTreeWidgetItem *)));
    for(int i = 0; i < 10; i++){
        // 一级部门节点
        QTreeWidgetItem *pRootDeptItem = new QTreeWidgetItem();
        pRootDeptItem->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
        //设置Data用于区分,Item是分组节点还是子节点,0代表分组节点,1代表子节点
        pRootDeptItem->setData(0, Qt::UserRole, 0);
        DepartNodeItem *pItemName = new DepartNodeItem(ui->tree);
        pItemName->setLevel(0);

        int nMyFriendNum = 6;
        QString qsGroupName = QString("一级部门%3 [%1/%2]").arg(0).arg(nMyFriendNum).arg(i);
        pItemName->setText(qsGroupName);
        //插入分组节点
        ui->tree->addTopLevelItem(pRootDeptItem);
        ui->tree->setItemWidget(pRootDeptItem, 0, pItemName);
        for(int j = 0; j < 5; j++){
            addChildEmpNode(pRootDeptItem, j);
        }
        for(int j = 0; j < 5; j++){
            QString name = QString("二级部门%1").arg(j);
            QTreeWidgetItem *childItem = addChildNode(pRootDeptItem, i * 10 + j,name);
            for(int g = 0; g < 5; g++){
                addChildEmpNode(childItem, g);
            }
        }
    }
}

QTreeWidgetItem* MainWindow::addChildNode(QTreeWidgetItem *parent, int index, QString namePre)
{
    QTreeWidgetItem *pDeptItem = new QTreeWidgetItem();
    pDeptItem->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
    //设置Data用于区分,Item是分组节点还是子节点,0代表分组节点,1代表子节点
    pDeptItem->setData(0, Qt::UserRole, 0);
    DepartNodeItem *pItemName = new DepartNodeItem(ui->tree);
    int level = 0;
    DepartNodeItem *departNode = dynamic_cast<DepartNodeItem*>(ui->tree->itemWidget(parent, 0));
    if (departNode) {
        level = departNode->getLevel();
        level ++;
    }
    pItemName->setLevel(level);

    int nMyFriendNum = 6;
    QString qsGroupName = QString("%4%3 [%1/%2]").arg(0).arg(nMyFriendNum).arg(index).arg(namePre);
    pItemName->setText(qsGroupName);
    //擦入分组节点
    parent->addChild(pDeptItem);
    ui->tree->setItemWidget(pDeptItem, 0, pItemName);

    return pDeptItem;
}

QTreeWidgetItem *MainWindow::addChildEmpNode(QTreeWidgetItem *parent, int index)
{
    QTreeWidgetItem *pDeptItem = new QTreeWidgetItem();
    //设置Data用于区分,Item是分组节点还是子节点,0代表分组节点,1代表子节点
    pDeptItem->setData(0, Qt::UserRole, 1);
    int level = 0;
    DepartNodeItem *departNode = dynamic_cast<DepartNodeItem*>(ui->tree->itemWidget(parent, 0));
    if (departNode) {
        level = departNode->getLevel();
        level ++;
    }

    EmployeeNodeItem *pItemName = new EmployeeNodeItem(ui->tree);
    pItemName->setLevel(level);
    // 加载本地文件,需要修改成本地的路径
     pItemName->setHeadPath(QString("D:/work/Qt/workspace/QT_treeDemo/images/pic/%1.jpg").arg(index));

    QString qfullName = QString("人员%1").arg(index);
    pItemName->setFullName(qfullName);
    pItemName->setSign(QString("欢迎访问杜燕军工作号-test!!!"));
    //擦入分组节点
    parent->addChild(pDeptItem);
    ui->tree->setItemWidget(pDeptItem, 0, pItemName);
    return pDeptItem;
}

5)、DepartNodeItem类
departnodeitem.h

#ifndef DEPARTNODEITEM_H
#define DEPARTNODEITEM_H

#include <QLabel>
#include <QPaintEvent>
#include <QPropertyAnimation>

#define INDENTATION 20

class DepartNodeItem : public QLabel
{
    Q_OBJECT
    Q_PROPERTY(int rotation READ rotation WRITE setRotation)
public:
    DepartNodeItem(QWidget *parent = 0);

    ~DepartNodeItem();

    void setText(const QString& title);

    void setExpanded(bool expand);

    int getIndentation();

    void setLevel(int level);

    int getLevel();

private:
    int rotation();

    void setRotation(int rotation);

private:
    void paintEvent(QPaintEvent *event);

private:
    QPropertyAnimation *m_animation;
    // 部门名称
    QString m_name;
    // 部门ID
    QString m_id;
    // 旋转角度
    int m_rotation;
    // 当前节点缩进距离
    int m_indentation;
    // 当前节点的深度(级数)
    int m_level;
};

#endif // DEPARTNODEITEM_H

departnodeitem.cpp

#include "departnodeitem.h"

#include <QPainter>
#include <QDebug>

DepartNodeItem::DepartNodeItem(QWidget *parent)
    : QLabel(parent),
      m_rotation(0),
      m_level(0),
      m_indentation(0)
{
    setFixedHeight(32);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    m_animation = new QPropertyAnimation(this, "rotation");
    m_animation->setDuration(50);
    m_animation->setEasingCurve(QEasingCurve::InQuad);
}

DepartNodeItem::~DepartNodeItem()
{
    m_animation = NULL;
    delete m_animation;
}

void DepartNodeItem::setText(const QString &title)
{
    m_name = title;
    update();
}

void DepartNodeItem::setExpanded(bool expand)
{
    if (expand) {
        m_animation->setEndValue(90);
    } else {
        m_animation->setEndValue(0);
    }
    m_animation->start();
}


int DepartNodeItem::getIndentation()
{
    return this->m_indentation;
}

void DepartNodeItem::setLevel(int level)
{
    this->m_level = level;
    this->m_indentation = this->m_level * INDENTATION;
}

int DepartNodeItem::getLevel()
{
    return this->m_level;
}

int DepartNodeItem::rotation()
{
    return m_rotation;
}

void DepartNodeItem::setRotation(int rotation)
{
    m_rotation = rotation;
    update();
}

void DepartNodeItem::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    {
        painter.setRenderHint(QPainter::TextAntialiasing, true);
        QFont font;
        font.setPointSize(10);
        painter.setFont(font);
        int txtX = m_indentation + 24;
        painter.drawText(txtX, 0, this->width() - txtX, this->height(), Qt::AlignLeft | Qt::AlignVCenter, m_name);
    }

    {
        painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
        painter.save();

        QPixmap pixmap(":/tree/Resources/arrow.png");
        QPixmap tmpPixmap(pixmap.size());
        tmpPixmap.fill(Qt::transparent);

        QPainter p(&tmpPixmap);
        p.setRenderHint(QPainter::SmoothPixmapTransform, true);
        // 旋转m_rotation角度
        p.translate(pixmap.width() /2, pixmap.height() /2);
        p.rotate(m_rotation);
        p.drawPixmap(0 - pixmap.width() /2, 0 - pixmap.height() / 2,pixmap);
        painter.drawPixmap(m_indentation+6, (this->height() - pixmap.height()) / 2, tmpPixmap);
        painter.restore();
    }
    QLabel::paintEvent(event);
}

6)、EmployeeNodeItem类
EmployeeNodeItem.h

#ifndef EMPLOYEENODEITEM_H
#define EMPLOYEENODEITEM_H

#include <QWidget>
#include <QPaintEvent>
#include <QPixmap>
#include <QSize>

#define INDENTATION 20
#define HEAD_LABEL_WIDTH 40

namespace Ui {
class EmployeeNodeItem;
}

class EmployeeNodeItem : public QWidget
{
    Q_OBJECT

public:
    EmployeeNodeItem(QWidget *parent = 0);

    ~EmployeeNodeItem();

public:
    void setFullName(const QString& fullName);

    void setSign(const QString& sign);

    void setHeadPixmap(const QPixmap& headPath);

    void setHeadPath(const QString& headPath);

    QSize getHeadLabelSize() const;

    int getIndentation();

    int getLevel();

    void setLevel(int level);

private:
    void initControl();
    QPixmap getRoundImage(const QPixmap &src, QPixmap& mask, QSize masksize);

private:
    void paintEvent(QPaintEvent *event);

private:
    Ui::EmployeeNodeItem *ui;

    // 当前节点缩进距离
    int m_indentation;

    // 当前节点的深度(级数)
    int m_level;

    // 头像Label的宽度
    int m_headLabelWidth;
};

#endif // EMPLOYEENODEITEM_H

EmployeeNodeItem.cpp

#include "EmployeeNodeItem.h"
#include "ui_EmployeeNodeItem.h"

#include <QDebug>
#include <QPainter>

EmployeeNodeItem::EmployeeNodeItem(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::EmployeeNodeItem),
    m_headLabelWidth(0),
    m_level(0),
    m_indentation(0)
{
    ui->setupUi(this);
    initControl();
}

EmployeeNodeItem::~EmployeeNodeItem()
{
    delete ui;
}

void EmployeeNodeItem::setFullName(const QString &fullName)
{
    ui->lbFullName->setText(fullName);
}

void EmployeeNodeItem::setSign(const QString &sign)
{
    ui->lbSign->setText(sign);
}

void EmployeeNodeItem::setHeadPixmap(const QPixmap &headPath)
{
    ui->lbHeadPic->setPixmap(headPath);
}

void EmployeeNodeItem::setHeadPath(const QString &headPath)
{
    /*
    ui->lbHeadPic->setScaledContents(true);
    QString style = ui->lbHeadPic->styleSheet();
    style.append("image:url(").append(headPath).append(");");
    qDebug() << style;
    ui->lbHeadPic->setStyleSheet(style);
    */
    // 方式3.加载QPixmap
    QPixmap pixmap1;
    pixmap1.load(headPath);
    QPixmap pixmap2;
    pixmap2.load(":/tree/Resources//head_mask.png");
    //qDebug() << "m_level:" << m_level << "  m_indentation:" << m_indentation << " m_headLabelWidth:" << m_headLabelWidth << "  " << HEAD_LABEL_WIDTH;
    QPixmap roundPic = this->getRoundImage(pixmap1, pixmap2, QSize(m_headLabelWidth,HEAD_LABEL_WIDTH));
    this->setHeadPixmap(roundPic);
}

QSize EmployeeNodeItem::getHeadLabelSize() const
{
    return ui->lbHeadPic->size();
}

int EmployeeNodeItem::getIndentation()
{
    return this->m_indentation;

}

int EmployeeNodeItem::getLevel()
{
    return this->m_level;
}

void EmployeeNodeItem::setLevel(int level)
{
    this->m_level = level;
    this->m_indentation = this->m_level * INDENTATION;
    this->m_headLabelWidth = this->m_indentation + HEAD_LABEL_WIDTH;
    ui->lbHeadPic->setMinimumWidth(m_indentation);
}

void EmployeeNodeItem::initControl()
{

}

QPixmap EmployeeNodeItem::getRoundImage(const QPixmap &src, QPixmap &mask, QSize masksize)
{
    if (masksize == QSize(0, 0))
    {
        masksize = mask.size();
    }
    else
    {
        mask = mask.scaled(masksize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    }

    QImage resultImage(masksize, QImage::Format_ARGB32_Premultiplied);
    QPainter painter(&resultImage);
    painter.setCompositionMode(QPainter::CompositionMode_Source);
    painter.fillRect(resultImage.rect(), Qt::transparent);
    painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
    painter.drawPixmap(m_indentation, 0, mask);
    painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
    painter.drawPixmap(m_indentation, 0, src.scaled(masksize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
    painter.end();
    return QPixmap::fromImage(resultImage);
}

void EmployeeNodeItem::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
}

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

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

相关文章

浅谈微服务架构的演进

本文将介绍微服务架构和相关的组件&#xff0c;介绍他们是什么以及为什么要使用微服务架构和这些组件。本文侧重于简明地表达微服务架构的全局图景&#xff0c;因此不会涉及具体如何使用组件等细节。 要理解微服务&#xff0c;首先要先理解不是微服务的那些。通常跟微服务相对…

Redis系列之简单实现watchDog自动续期机制

在分布锁的实际使用中&#xff0c;可能会遇到一种情况&#xff0c;一个业务执行时间很长&#xff0c;已经超过redis加锁的时间&#xff0c;也就是锁已经释放了&#xff0c;但是业务还没执行完成&#xff0c;这时候其它线程还是可以获取锁&#xff0c;那就没保证线程安全 项目环…

【Unity学习笔记】光照简介

本节主要是简单介绍一些常见的光照组件和渲染设置。 文章目录 灯光类型平行光Directional Light点光源Point Light聚光灯Spot Light面积光 Area Light 阴影设置全局光照明光照模式直接光照与间接光照Mixed Lighting 光照探针Light Probe Group光照探针组 反射探针 灯光类型 在…

使用 Python 实现简单的爬虫框架

爬虫是一种自动获取网页内容的程序&#xff0c;它可以帮助我们从网络上快速收集大量信息。在本文中&#xff0c;我们将学习如何使用 Python 编写一个简单的爬虫框架。 一、请求网页 首先&#xff0c;我们需要请求网页内容。我们可以使用 Python 的 requests 库来发送 HTTP 请…

CLEAR MOT评估指标

错误正样本&#xff08;False Positive&#xff0c;FP&#xff09;&#xff1a;整个视频中被预测为正的负样本数。 错误负样本&#xff08;False Negatives&#xff0c;FN&#xff09;&#xff1a;整个视频中被预测为负的正样本数。 IDs&#xff1a;跟踪过程中目标ID切换总数。…

springcloud微服务篇--2.微服务之间的调用

一、微服务案例需求1&#xff1a; 根据订单id查询订单的同时&#xff0c;把订单所属的用户信息一起返回 1、新建订单项目&#xff0c;用户服务。 2.RestTemplate实现微服务之间的访问。 在order-service的OrderApplication中注册RestTemplate 注入调用&#xff1a; Autowire…

【ModBus进阶日记】①ModBus协议栈解析

关注星标公众号&#xff0c;不错过精彩内容 文章目录 前言一、ModBus简介二、ModBus协议概述2.1 ModBus RTU主机框架2.2 ModBus RTU从机框架 三、ModBus帧描述四、ModBus RTU模式的报文断帧五、ModBus字节序六、ModBus事务处理流程七、ModBus异常响应八、ModBus功能码定义九、…

如何实现nacos的配置的热更新

我们在使用nacos进行修改配置后&#xff0c;需要微服务无需重启即可让配置生效&#xff0c;也就是使配置进行热更新我们可以采用下面的两种方式进行配置的热更新操作 方式一&#xff1a;在Value所注入的变量的类上添加注解RefreshScope RestController RequestMapping("/o…

Local Color Distributions Prior for ImageEnhancement

图1&#xff1a;给定同时具有过曝光&#xff08;背景窗口&#xff09;和欠曝光&#xff08;前景人物&#xff09;的输入图像&#xff08;a&#xff09;&#xff0c;现有方法不能很好地处理这两个问题。虽然&#xff08;b&#xff09;在背景上表现更好&#xff0c;但前景仅略微变…

anolisos8.8安装显卡+CUDA工具+容器运行时支持(containerd/docker)+k8s部署GPU插件

anolisos8.8安装显卡及cuda工具 一、目录 1、测试环境 2、安装显卡驱动 3、安装cuda工具 4、配置容器运行时 5、K8S集群安装nvidia插件 二、测试环境 操作系统&#xff1a;Anolis OS 8.8 内核版本&#xff1a;5.10.134-13.an8.x86_64 显卡安装版本&#xff1a;525.147.05 c…

学习笔记——GDB调试器

感谢B站up主 xiaobing1016 的学习视频&#xff1a;基于VSCode和CMake实现C/C开发 | Linux篇_哔哩哔哩_bilibili

电脑加密软件哪个最好用(电脑加密软件排行榜2023)

你公司的电脑数据在裸奔&#xff1f; 你公司的核心文件完全开放&#xff1f; 你公司的机密图纸谁都能获取&#xff1f; …… 作为老板的你&#xff0c;该不会还不知道电脑加密软件能够解决上述这些问题吧&#xff01; 我看过一个案例&#xff0c;新闻报道的略显夸张&#x…

企业资产管理技巧,这一点厉害了!

​随着市场竞争的不断加剧和金融环境的日益复杂&#xff0c;有效地管理和优化资产已经成为保持竞争优势和实现财务目标的不可或缺的一环。资产不仅仅是组织或个人的财富&#xff0c;更是潜在的增长动力和风险源。 传统的资产管理方法已经不再适应现代快速变化的经济环境。为了适…

【C语言程序设计】选择结构程序设计

目录 前言 一、程序阅读 二、程序改错 三、程序设计 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da;。 &#x1f4e3;如…

时间序列预测 — CNN-LSTM实现多变量多步光伏预测(Tensorflow)

目录 1 数据处理 1.1 导入库文件 1.2 导入数据集 1.3 缺失值分析 2 构造训练数据 ​3 模型训练 3.1 CNN-LSTM网络 3.2 模型训练 4 模型预测 专栏链接&#xff1a;https://blog.csdn.net/qq_41921826/category_12495091.html 1 数据处理 1.1 导入库文件 import scip…

一些paper工具帮你搞定日常科研工作

如果你是在校生&#xff0c;科研er 你的日常避免各种各样的pepers&#xff1b;找papers&#xff0c;读papers&#xff0c;写papers。这三部曲贯穿这你整个科研工作&#xff0c;如何在有限的时间里&#xff0c;能够高效的完成科研&#xff0c;且保质保量&#xff0c;我们需要一些…

C# WPF上位机开发(内嵌虚拟机的软件开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 学习过halcon的同学都知道&#xff0c;它不仅有很多的图像算子可以使用&#xff0c;而且调试很方便。每一步骤的调试结果&#xff0c;都可以看到对…

MES系统设备日常点检:提升设备管理效率与维护质量

一、MES系统设备日常点检概述 MES系统设备日常点检是指通过MES系统对设备进行定期的外观、功能、性能等方面的检查&#xff0c;以评估设备的运行状态和潜在问题。这种检查方式有助于及时发现设备故障和隐患&#xff0c;确保设备的正常运行&#xff0c;提高生产效率。 二、MES系…

公益众筹源码系统:水滴筹模式+完整的安装包+部署教程

今天小编i来非大家来介绍一款公益众筹源码系统&#xff0c;带有完整的搭建教程。 一、系统开发 1.需求分析&#xff1a;在开发公益众筹源码系统之前&#xff0c;我们首先进行了深入的需求分析&#xff0c;明确了系统的目标、功能、性能等方面的要求。 2.技术选型&#xff1a;根…

什么是泊松图像混合

泊松图像混合&#xff08;Poisson Image Editing&#xff09;的原理基于泊松方程。该方法旨在保持图像中的梯度一致性&#xff0c;从而在图像编辑中实现平滑和无缝的混合。以下是泊松图像混合的基本原理和公式&#xff1a; 泊松方程 泊松方程是一个偏微分方程&#xff0c;通常…