使用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()
相关推荐
CXDNW8 分钟前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
使者大牙8 分钟前
【大语言模型学习笔记】第一篇:LLM大规模语言模型介绍
笔记·学习·语言模型
neter.asia10 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫10 分钟前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
Open-AI17 分钟前
Python如何判断一个数是几位数
python
极客代码20 分钟前
【Python TensorFlow】入门到精通
开发语言·人工智能·python·深度学习·tensorflow
ssf-yasuo21 分钟前
SPIRE: Semantic Prompt-Driven Image Restoration 论文阅读笔记
论文阅读·笔记·prompt
义小深23 分钟前
TensorFlow|咖啡豆识别
人工智能·python·tensorflow
疯一样的码农27 分钟前
Python 正则表达式(RegEx)
开发语言·python·正则表达式
光影少年29 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js