python实现输入mermaid 代码生成流程图

原理:使用npm的mmdc命令,将有mermaid内容的Markdown文件生成图片。

用命令行也就一句话的事:

mmdc -i  xxx.md -o xxx.jpg

环境:mmdc  11.4.2

遗留问题:这个mmdc 生成图片指定宽度 --width 不生效,只能用--scale 按比例缩放。

成果界面:

mermaid代码:

graph TD
    A[开始] --> B[吃饭]
    B --> C[睡觉]
    C --> D[打豆豆]
    D --> B
    D --> E[结束]

生成图片

使用vscode AIcode插件+deepseek辅助开发。

完整代码如下:

import sys
import os
import subprocess
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QTextEdit, QPushButton, QFileDialog, QLineEdit, QMessageBox, QHBoxLayout, QLabel, QComboBox, QSplitter
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QImage, QPixmap

class MermaidApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.output_dir = os.path.dirname(os.path.abspath(__file__))  # 默认保存路径为程序所在目录
        self.file_counter = 1
        self.initUI()
    
    def initUI(self):
        self.setWindowTitle("Mermaid 图表生成器")
        self.setGeometry(100, 100, 800, 600)
        
        # 主布局
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        layout = QVBoxLayout()
        
        # 使用QSplitter实现可调整大小的代码和图表区域
        splitter = QSplitter(Qt.Horizontal)
        
        # Mermaid代码输入
        self.code_input = QTextEdit()
        self.code_input.setPlainText("""graph TD
    A[开始] --> B[吃饭]
    B --> C[睡觉]
    C --> D[打豆豆]
    D --> B
    D --> E[结束]""")
        
        # 图表显示区域
        self.image_label = QLabel()
        self.image_label.setAlignment(Qt.AlignCenter)
        
        # 添加组件到splitter
        splitter.addWidget(self.code_input)
        splitter.addWidget(self.image_label)
        
        # 设置初始比例 60:40
        splitter.setSizes([600, 400])
        
        layout.addWidget(splitter)
        # 按钮布局
        btn_layout = QHBoxLayout()
        
        # 生成按钮
        self.generate_btn = QPushButton("生成图表")
        self.generate_btn.clicked.connect(self.generate_diagram)
        btn_layout.addWidget(self.generate_btn)
        
        # 保存按钮
        self.save_btn = QPushButton("保存图表")
        self.save_btn.clicked.connect(self.save_diagram)
        btn_layout.addWidget(self.save_btn)
        
        layout.addLayout(btn_layout)
        # 保存路径设置
        path_layout = QHBoxLayout()
        
        # 图片格式选择
        self.format_combo = QComboBox()
        self.format_combo.addItems(["PNG (*.png)", "JPEG (*.jpg)"])
        path_layout.addWidget(self.format_combo)
        
        # 缩放比例设置
        scale_layout = QHBoxLayout()
        scale_layout.addWidget(QLabel("缩放比例:"))
        self.scale_combo = QComboBox()
        self.scale_combo.addItems(["1", "1.5", "2", "2.5", "3"])
        self.scale_combo.setCurrentIndex(2)  # 默认选择2倍
        scale_layout.addWidget(self.scale_combo)
        path_layout.addLayout(scale_layout)
        
        # 路径显示
        self.path_label = QLabel()
        self.path_label.setText(f"保存路径: {self.output_dir}")
        path_layout.addWidget(self.path_label)
        
        self.modify_btn = QPushButton("修改")
        self.modify_btn.clicked.connect(self.select_output_dir)
        path_layout.addWidget(self.modify_btn)
        
        layout.addLayout(path_layout)
        main_widget.setLayout(layout)
    
    def generate_diagram(self):
        mermaid_code = self.code_input.toPlainText()
        if not mermaid_code.strip():
            self.show_message("错误", "请输入Mermaid代码")
            return
        
        # 使用mermaid-cli生成图表
        temp_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "temp.mmd")
        with open(temp_file, "w", encoding="utf-8") as f:
            f.write(mermaid_code)
        
        output_file = "diagram.png"
        config_file = "mermaid-config.json"
        try:
            # 创建配置文件
            with open(config_file, "w") as f:
                f.write('{"theme": "default", "fontFamily": "Microsoft YaHei"}')
            
            # 获取缩放比例
            scale = self.scale_combo.currentText()
            
            # 生成图表
            subprocess.run([
                "C:/Users/Administrator/AppData/Roaming/npm/mmdc.cmd",
                "-i", temp_file,
                "-o", output_file,
                "--configFile", config_file,
                "--scale", scale
            ], check=True)
            
            # 显示生成的图表
            image = QImage(output_file)
            
            # 清理临时文件
            os.remove(config_file)
        except subprocess.CalledProcessError as e:
            self.show_message("错误", f"生成图表失败: {str(e)}")
            return
        self.image_label.setPixmap(QPixmap.fromImage(image))
    
    def save_diagram(self):
        if not os.path.exists("diagram.png"):
            self.show_message("错误", "请先生成图表")
            return
        
        # 获取选择的格式
        selected_format = self.format_combo.currentText()
        format_map = {
            "PNG (*.png)": "png",
            "JPEG (*.jpg)": "jpg"
        }
        ext = format_map[selected_format]
        
        # 生成自动递增的文件名
        while True:
            filename = f"diagram_{self.file_counter}.{ext}"
            file_path = os.path.join(self.output_dir, filename)
            if not os.path.exists(file_path):
                break
            self.file_counter += 1
        
        try:
            image = QImage("diagram.png")
            image.save(file_path)
            
            self.show_message("成功", f"图表已保存至 {file_path}")
            self.file_counter += 1
        except Exception as e:
            self.show_message("错误", f"保存失败: {str(e)}")
    
    def select_output_dir(self):
        dir_path = QFileDialog.getExistingDirectory(
            self,
            "选择保存路径",
            self.output_dir
        )
        if dir_path:
            self.output_dir = dir_path
            self.path_label.setText(f"保存路径: {dir_path}")
    
    def show_message(self, title, message):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText(message)
        msg.setWindowTitle(title)
        msg.exec_()


def main():
    app = QApplication(sys.argv)
    window = MermaidApp()
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

打包了一个可执行文件地址:

https://download.csdn.net/download/bobodadao/90460665
可能需要单独安装mmdc 环境 百度搜:window 安装 nodejs mmdc

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄色茶杯

如果我能够自由,你就能自由

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值