使用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()
相关推荐
小板凳-BGM3 分钟前
C# 第二阶段 modbus
开发语言·ui·c#
许野平4 分钟前
Rust: enum 和 i32 的区别和互换
python·算法·rust·enum·i32
问道飞鱼5 分钟前
【Python知识】Python进阶-什么是装饰器?
开发语言·python·装饰器
z千鑫15 分钟前
【前端】详解前端三大主流框架:React、Vue与Angular的比较与选择
前端·vue.js·react.js
AI视觉网奇40 分钟前
Detected at node ‘truediv‘ defined at (most recent call last): Node: ‘truediv‘
人工智能·python·tensorflow
广而不精zhu小白41 分钟前
CentOS Stream 9 挂载Windows共享FTP文件夹
linux·windows·centos
m0_748256141 小时前
前端 MYTED单篇TED词汇学习功能优化
前端·学习
GuYue.bing1 小时前
网络下载ts流媒体
开发语言·python
IT古董1 小时前
【机器学习】机器学习的基本分类-半监督学习(Semi-supervised Learning)
学习·机器学习·分类·半监督学习
牛顿喜欢吃苹果1 小时前
linux创建虚拟串口
python