使用tkinter 制作工作流ui

说明

这段Python代码使用Tkinter库创建了一个图形用户界面(GUI)应用程序,名为"WorkflowEditor"。这个程序允许用户创建和编辑工作流中的功能及其参数。以下是代码的主要部分和功能:

  1. WorkflowEditor类:这是主类,负责设置窗口和框架,并管理功能按钮和参数编辑器。
  2. __init__方法:初始化方法创建窗口,设置标题,并创建左侧的功能框和右侧的工作流编排框(注释掉了)。它还添加了一些示例功能,并设置了一个计数器来跟踪功能数量。
  3. add_function方法:这个方法用于在左侧的功能框中添加一个新的功能按钮。每个按钮都可以点击编辑其参数。
  4. add_new_function方法:这个方法通过弹出一个对话框来请求用户输入新功能的名称,然后调用add_function方法添加新功能。
  5. edit_params方法:这个方法用于编辑功能的参数。它创建一个ParamEditor实例,并等待用户编辑参数。
  6. ParamEditor类:这个类用于创建一个对话框,允许用户编辑输入和输出参数。用户可以添加、编辑和删除参数。
  7. ParamEditorNew类:这个类与ParamEditor类非常相似,也用于创建一个对话框,允许用户编辑输入和输出参数。这个类似乎是ParamEditor类的副本,可能是用于实现不同的编辑功能或作为备份。
  8. on_drag_starton_drag_motion函数:这两个函数实现了拖拽功能,允许用户拖拽功能按钮。
  9. if __name__ == "__main__"::这是Python程序的入口点,它创建一个Tk窗口实例,并创建一个WorkflowEditor实例来启动应用程序。
    这个程序的主要功能是让用户能够创建和编辑工作流中的功能及其参数。用户可以通过点击"Add Function"按钮添加新功能,然后通过点击功能按钮编辑其参数。这个程序可能用于流程自动化、脚本编写或其他需要管理功能及其参数的应用场景。

代码

python 复制代码
import tkinter as tk
from tkinter import simpledialog, messagebox


class WorkflowEditor:
    def __init__(self, root):

        self.root = root
        self.root.title("Workflow Editor")
        # 创建左侧的功能框

        self.functions_frame = tk.Frame(self.root, width=600, height=600, bg='white', borderwidth=2, relief="solid")
        self.functions_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        add_function_button = tk.Button(self.functions_frame, text="Add Function", command=self.add_new_function)
        add_function_button.pack(side=tk.BOTTOM, fill=tk.BOTH)

        # 创建右侧的工作流编排框
        # self.workflow_frame = tk.Canvas(self.root, width=600, height=600, bg='white',borderwidth=2, relief="solid")
        # self.workflow_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        # 添加一些示例功能
        self.add_function('Function 1', {'input': {'param1': 'value1', 'param2': 'value2'}, 'output': {'result': ''}})
        self.add_function('Function 2', {'input': {'param1': 'value1', 'param2': 'value2'}, 'output': {'result': ''}})
        self.add_function('Function 3', {'input': {'param1': 'value1', 'param2': 'value2'}, 'output': {'result': ''}})
        self.func_count = 3

    def add_function(self, name, params):
        # 创建一个功能按钮,可以点击编辑参数

        functions_frame = tk.Frame(root)
        functions_frame.pack()

        # 创建9个按钮,并使用Grid布局管理器将它们放置在3x3的网格中
        for row in range(3):
            for col in range(3):
                if row == 1 and col == 1:
                    button = tk.Button(functions_frame, text=name)
                else:

                    button = tk.Button(functions_frame, text=f"Button {row},{col}")
                button.grid(row=row, column=col, padx=5, pady=5)
                button.bind('<Button-3>', lambda event, p=params: self.edit_params(p))

        # button = tk.Button(self.functions_frame, text=name)
        # button.pack(fill=tk.X)

        functions_frame.bind("<Button-1>", on_drag_start)
        functions_frame.bind("<B1-Motion>", on_drag_motion)

    def add_new_function(self):
        # 弹出对话框,请求用户输入新功能的名称

        name = simpledialog.askstring("Function {}".format(self.func_count), "Enter function name:")
        if name:
            self.func_count += 1
            # 创建一个默认的参数字典
            params = {'input': {}, 'output': {'result': ''}}
            # 添加新功能到界面
            self.add_function("Function {}".format(self.func_count)+name, params)
            # 打印新功能的参数,以便于调试
            print(f"Added new function '{name}': {params}")

    def edit_params(self, params):
        # 弹出对话框,允许用户编辑参数
        dialog = ParamEditor(self.root, params)
        self.root.wait_window(dialog.top)
        # 获取编辑后的参数
        new_params = dialog.get_params()
        print("Edited Parameters:", new_params)

    def edit_params_new(self, params):
        # 弹出对话框,允许用户编辑参数
        dialog = ParamEditorNew(self.root, params)
        self.root.wait_window(dialog.top)
        # 获取编辑后的参数
        new_params = dialog.get_params()
        print("Edited Parameters:", new_params)


class ParamEditor:
    def __init__(self, parent, params):

        self.params = params
        self.top = tk.Toplevel(parent)
        self.top.title("Edit Parameters")
        # 创建输入和输出标签框架
        self.input_frame = tk.LabelFrame(self.top, text="Input Parameters", padx=5, pady=5)
        self.input_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        self.output_frame = tk.LabelFrame(self.top, text="Output Parameters", padx=5, pady=5)
        self.output_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        # 初始化参数字典
        self.entries = {'input': {}, 'output': {}}
        # 添加输入参数
        for i, (key, value) in enumerate(self.params['input'].items()):
            self.add_parameter_entry(self.input_frame, 'input', key, value, i)
        # 添加输出参数
        for i, (key, value) in enumerate(self.params['output'].items()):
            self.add_parameter_entry(self.output_frame, 'output', key, value, i)
        # 创建添加参数的按钮

        add_input_button = tk.Button(self.input_frame, text="Add Input",
                                     command=lambda: self.add_parameter(self.input_frame, 'input'))
        add_input_button.grid(row=len(self.params['input']), columnspan=3, sticky="ew")  # 使用grid而不是pack
        add_output_button = tk.Button(self.output_frame, text="Add Output",
                                      command=lambda: self.add_parameter(self.output_frame, 'output'))
        add_output_button.grid(row=len(self.params['output']), columnspan=3, sticky="ew")  # 使用grid而不是pack
        # 创建确认按钮
        ok_button = tk.Button(self.top, text="OK", command=self.ok)
        ok_button.pack()

    def add_parameter_entry(self, frame, param_type, key, value, row):
        # 创建标签、输入框和删除按钮
        label = tk.Label(frame, text=key)
        entry = tk.Entry(frame)
        entry.insert(0, value)  # 设置默认值
        delete_button = tk.Button(frame, text="X", command=lambda k=key: self.delete_parameter(frame, param_type, k))
        label.grid(row=row, column=0, sticky="e")
        entry.grid(row=row, column=1)
        delete_button.grid(row=row, column=2)
        # 将输入框添加到字典中
        self.entries[param_type][key] = {'label': label, 'entry': entry, 'button': delete_button}

    def add_parameter(self, frame, param_type):
        # 获取新的参数名
        key = simpledialog.askstring("New Parameter", "Enter parameter name:")
        if key and key not in self.params[param_type]:
            # 计算行号
            row = len(self.entries[param_type])
            # 添加参数
            self.params[param_type][key] = ''

            self.add_parameter_entry(frame, param_type, key, '', row)

    def delete_parameter(self, frame, param_type, key):
        # 删除参数输入框和按钮
        entry = self.entries[param_type].pop(key)
        entry['label'].grid_forget()
        entry['entry'].grid_forget()
        entry['button'].grid_forget()
        # 从参数字典中删除参数
        del self.params[param_type][key]

    def ok(self):
        # 更新参数并关闭对话框
        for param_type in self.entries:
            for key, entry_dict in self.entries[param_type].items():
                self.params[param_type][key] = entry_dict['entry'].get()
        self.top.destroy()

    def get_params(self):
        return self.params


class ParamEditorNew:
    def __init__(self, parent, params):

        self.params = params
        self.top = tk.Toplevel(parent)
        self.top.title("Edit Parameters")
        # 创建输入和输出标签框架
        self.input_frame = tk.LabelFrame(self.top, text="Input Parameters", padx=5, pady=5)
        self.input_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        self.output_frame = tk.LabelFrame(self.top, text="Output Parameters", padx=5, pady=5)
        self.output_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        # 初始化参数字典
        self.entries = {'input': {}, 'output': {}}
        # 添加输入参数
        for i, (key, value) in enumerate(self.params['input'].items()):
            self.add_parameter_entry(self.input_frame, 'input', key, value, i)
        # 添加输出参数
        for i, (key, value) in enumerate(self.params['output'].items()):
            self.add_parameter_entry(self.output_frame, 'output', key, value, i)
        # 创建添加参数的按钮

        add_input_button = tk.Button(self.input_frame, text="Add Input",
                                     command=lambda: self.add_parameter(self.input_frame, 'input'))
        add_input_button.grid(row=len(self.params['input']), columnspan=3, sticky="ew")  # 使用grid而不是pack
        add_output_button = tk.Button(self.output_frame, text="Add Output",
                                      command=lambda: self.add_parameter(self.output_frame, 'output'))
        add_output_button.grid(row=len(self.params['output']), columnspan=3, sticky="ew")  # 使用grid而不是pack
        # 创建确认按钮
        ok_button = tk.Button(self.top, text="OK", command=self.ok)
        ok_button.pack()

    def add_parameter_entry(self, frame, param_type, key, value, row):
        # 创建标签、输入框和删除按钮
        label = tk.Label(frame, text=key)
        entry = tk.Entry(frame)
        entry.insert(0, value)  # 设置默认值
        delete_button = tk.Button(frame, text="X", command=lambda k=key: self.delete_parameter(frame, param_type, k))
        label.grid(row=row, column=0, sticky="e")
        entry.grid(row=row, column=1)
        delete_button.grid(row=row, column=2)
        # 将输入框添加到字典中
        self.entries[param_type][key] = {'label': label, 'entry': entry, 'button': delete_button}

    def add_parameter(self, frame, param_type):
        # 获取新的参数名
        key = simpledialog.askstring("New Parameter", "Enter parameter name:")
        if key and key not in self.params[param_type]:
            # 计算行号
            row = len(self.entries[param_type])
            # 添加参数
            self.params[param_type][key] = ''

            self.add_parameter_entry(frame, param_type, key, '', row)

    def delete_parameter(self, frame, param_type, key):
        # 删除参数输入框和按钮
        entry = self.entries[param_type].pop(key)
        entry['label'].grid_forget()
        entry['entry'].grid_forget()
        entry['button'].grid_forget()
        # 从参数字典中删除参数
        del self.params[param_type][key]

    def ok(self):
        # 更新参数并关闭对话框
        for param_type in self.entries:
            for key, entry_dict in self.entries[param_type].items():
                self.params[param_type][key] = entry_dict['entry'].get()
        self.top.destroy()

    def get_params(self):
        return self.params


def on_drag_start(event):
    """开始拖拽"""
    widget = event.widget
    widget._drag_start_x = event.x
    widget._drag_start_y = event.y


def on_drag_motion(event):
    """拖拽中"""
    widget = event.widget
    x = widget.winfo_x() - widget._drag_start_x + event.x
    y = widget.winfo_y() - widget._drag_start_y + event.y
    widget.place(x=x, y=y)


if __name__ == "__main__":
    root = tk.Tk()
    app = WorkflowEditor(root)
    root.mainloop()
相关推荐
前端缘梦3 分钟前
LangGraph 核心特性技术详解:流式输出、持久化、记忆体系与中断实战。
前端·人工智能·程序员
张龙6875 分钟前
前端错误监控生产级方案:从 onerror 捕获到 Source Map 精准还原
前端·javascript
渣波5 分钟前
从零手写 Vite Mock 流式 AI 对话,搞懂 LLM 的“打字机”特效
前端·javascript
m沐沐6 分钟前
【机器学习】基于 dlib 面部关键点的多表情分类
人工智能·python·深度学习·机器学习·计算机视觉·人脸识别·表情识别
温柔过期啦8 分钟前
网站改了标题但是搜索引擎却没改?怎么样才能快速更新?
前端·搜索引擎·百度
cxxcode10 分钟前
JavaScript 模块化:从模块规范到打包原理
前端·webpack
驰子10511 分钟前
不重写、不换框架:让十年 jQuery 老项目写出 Vue 手感的渐进式改造
前端
Starry-sky(jing)11 分钟前
如何判断 Windows 是否安装 Node.js:三种方法 + 常见漏判场景
运维·windows·node.js·环境检测
月弦笙音12 分钟前
# SSE 连接可靠性方案
前端
weedsfly13 分钟前
从表单校验到订单流转,彻底搞懂前端开发中的策略模式与状态模式
前端·javascript·面试