python ui 工作流完善功能

说明

这段代码是一个使用Tkinter编写的图形用户界面(GUI)应用程序,它用于编辑工作流。以下是代码的主要部分和功能的说明:

  1. Tooltip类:这是一个自定义类,用于创建一个工具提示窗口,当鼠标悬停在指定的Tkinter小部件上时显示。它使用Tkinter的Toplevel窗口来创建工具提示,并且当鼠标离开时销毁这个窗口。
  2. WorkflowEditor类:这是应用程序的主类,它负责创建和布局窗口,添加功能按钮,并处理与按钮相关的操作。它包含一个函数add_function,用于在功能框中添加新按钮,并设置它们的位置和功能。
  3. ParamEditorParamEditorNew类:这两个类是参数编辑器,它们是弹出窗口,允许用户编辑工作流中函数的参数。ParamEditor用于编辑函数名和功能参数名,而ParamEditorNew用于编辑输入/输出方向和参数名。
  4. on_drag_starton_drag_motion函数:这些函数用于处理鼠标拖拽事件,允许用户拖拽功能框中的按钮并改变它们的位置。
  5. if __name__ == "__main__":块:这是Python脚本的入口点,它创建一个主窗口,并实例化WorkflowEditor类,启动Tkinter的事件循环。
    整个应用程序的设计是为了提供一个工作流编辑器,用户可以添加、编辑和拖拽功能按钮,以及编辑每个功能按钮的参数。工具提示的添加是为了提供额外的信息,以便用户更好地理解每个功能按钮的作用。

代码

import tkinter as tk
from tkinter import simpledialog, ttkclass Tooltip:def __init__(self, widget, text):self.widget = widgetself.text = textself.widget.bind("<Enter>", self.enter)self.widget.bind("<Leave>", self.leave)self.tooltip_window = Nonedef enter(self, event=None):x, y, _, _ = self.widget.bbox("insert")x += self.widget.winfo_rootx() + 25y += self.widget.winfo_rooty() + 25self.tooltip_window = tk.Toplevel(self.widget)self.tooltip_window.wm_overrideredirect(True)self.tooltip_window.wm_geometry(f"+{x}+{y}")label = ttk.Label(self.tooltip_window, text=self.text, background="#ffffe0", borderwidth=1, relief="solid")label.pack()def leave(self, event=None):if self.tooltip_window:self.tooltip_window.destroy()self.tooltip_window = Noneclass WorkflowEditor:def __init__(self, root):self.root = rootself.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)self.functions_frame_list = dict()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('Function1', {'input': {'param1': 'value1', 'param2': 'value2'}, 'output': {'result': ''}})self.add_function('Function2', {'input': {'param1': 'value1', 'param2': 'value2'}, 'output': {'result': ''}})self.add_function('Function3', {'input': {'param1': 'value1', 'param2': 'value2'}, 'output': {'result': ''}})self.func_count = 3def add_function(self, name, params):# 创建一个功能按钮,可以点击编辑参数functions_frame = tk.Frame(self.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)button.widgetName = "{}_{}".format(row, col)button.grid(row=row, column=col, padx=5, pady=5)button.bind('<Button-3>', lambda event, p=params, r=row, c=col: self.edit_params(p, name, r, c))else:button = tk.Button(functions_frame, text=f"edit")button.widgetName = "{}_{}".format(row, col)button.grid(row=row, column=col, padx=5, pady=5)button.bind('<Button-3>', lambda event, p=params, r=row, c=col: self.edit_params_new(p, name, r, c))# 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)self.functions_frame_list[name] = functions_framedef 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, name, r, c):# 弹出对话框,允许用户编辑参数dialog = ParamEditor(self.root, params)dialog.name = nameself.root.wait_window(dialog.top)# 获取编辑后的参数# new_params = dialog.get_params()# 增加函数功能说明Tooltip(self.functions_frame_list[name].children["!button{}".format(r * 3 + c + 1)],params["func_name"]+":"+params["tip"])# 设置颜色  设计名字self.functions_frame_list[name].children["!button{}".format(r * 3 + c + 1)].config(bg=params["arg"])def edit_params_new(self, params, name, r, c):print(name)# 弹出对话框,允许用户编辑参数dialog = ParamEditorNew(self.root, params)dialog.name = namedialog.r = rdialog.c = cself.root.wait_window(dialog.top)# 获取编辑后的参数# new_params = dialog.get_params()colors = ['red', 'blue', 'green', 'yellow', 'purple', 'orange', 'cyan', 'pink', 'brown']# self.functions_frame.children[0].config(bg=colors[1])# self.functions_frame.children["!button"].config(bg=colors[1])if r * 3 + c + 1 == 1:self.functions_frame_list[name].children["!button"].config(bg=params["arg"])self.functions_frame_list[name].children["!button"].config(text=params["s"])else:self.functions_frame_list[name].children["!button{}".format(r * 3 + c + 1)].config(bg=params["arg"])self.functions_frame_list[name].children["!button{}".format(r * 3 + c + 1)].config(text=params["s"])class ParamEditor:def __init__(self, parent, params):self.params = paramsself.top = tk.Toplevel(parent)self.top.title("参数编辑")# 创建输入和输出标签框架self.input_frame = tk.LabelFrame(self.top, text="函数名", 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="功能参数名", padx=5, pady=5)self.output_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)# self.output_frame1 = tk.LabelFrame(self.top, text="输入/输出参数名", padx=5, pady=5)# self.output_frame1.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)# 添加输入参数self.add_parameter_entry(self.input_frame)# 添加输出参数# self.add_parameter_option(self.output_frame, tk.StringVar(), options=["io_选项A", "io_选项B", "io_选项C", "io_选项D"])self.add_parameter_text(self.output_frame)# 创建确认按钮ok_button = tk.Button(self.top, text="OK", command=self.ok)ok_button.pack()def add_parameter_entry(self, frame):if self.params.get("func_name") is None:self.entry = tk.Entry(frame)self.entry.pack()else:self.entry = tk.Entry(frame, textvariable=self.params["func_name"])self.entry.pack()def add_parameter_text(self, frame):self.text_box = tk.Text(frame, height=10, width=50)self.text_box.pack()def ok(self):# 更新参数并关闭对话框self.params["func_name"] = self.entry.get()self.params["tip"] = self.text_box.get("1.0", tk.END)self.top.destroy()return self.paramsclass ParamEditorNew:def __init__(self, parent, params):self.params = paramsself.top = tk.Toplevel(parent)self.top.title("参数编辑")# 创建输入和输出标签框架self.input_frame = tk.LabelFrame(self.top, text="输入/输出方向", 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="输入/输出参数名", padx=5, pady=5)self.output_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)# self.output_frame1 = tk.LabelFrame(self.top, text="输入/输出参数名", padx=5, pady=5)# self.output_frame1.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)# 添加输入参数self.add_parameter_option(self.input_frame, tk.StringVar(), options=["s_^", "s_v", "s_<", "s_>"])# 添加输出参数# self.add_parameter_option(self.output_frame, tk.StringVar(), options=["io_选项A", "io_选项B", "io_选项C", "io_选项D"])self.add_parameter_option(self.output_frame, tk.StringVar(),options=["arg_"+i for i in ['red', 'blue', 'green', 'yellow', 'purple', 'orange', 'cyan', 'pink', 'brown']])# 创建确认按钮ok_button = tk.Button(self.top, text="OK", command=self.ok)ok_button.pack()def on_select_option(self, selected_var):# 当用户选择一个OptionMenu时,这个函数会被调用def callback(value):print(f"你选择了:{value}")self.params[value.split("_")[0]] = value.split("_")[1]return callbackdef add_parameter_option(self, frame, selected_var, options=["选项A", "选项B", "选项C", "选项D"]):# 设置一个默认值selected_var.set("请选择")# 创建下拉单选菜单dropdown = tk.OptionMenu(frame, selected_var, *options, command=self.on_select_option(selected_var))dropdown.pack()def ok(self):# 更新参数并关闭对话框self.top.destroy()def get_params(self):return self.paramsdef on_drag_start(event):"""开始拖拽"""widget = event.widgetwidget._drag_start_x = event.xwidget._drag_start_y = event.ydef on_drag_motion(event):"""拖拽中"""widget = event.widgetx = widget.winfo_x() - widget._drag_start_x + event.xy = widget.winfo_y() - widget._drag_start_y + event.ywidget.place(x=x, y=y)if __name__ == "__main__":root = tk.Tk()app = WorkflowEditor(root)root.mainloop()

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

均匀采样信号的鲁棒Savistky-Golay滤波(MATLAB)

S-G滤波器又称S-G卷积平滑器&#xff0c;它是一种特殊的低通滤波器&#xff0c;用来平滑噪声数据。该滤波器被广泛地运用于信号去噪&#xff0c;采用在时域内基于多项式最小二乘法及窗口移动实现最佳拟合的方法。与通常的滤波器要经过时域&#xff0d;频域&#xff0d;时域变换…

进程的初步认识

目录 一、硬件方面介绍 1.冯诺依曼体系结构 2.存储分级 二、软件 方面 1.操作系统是一款进行管理的软件&#xff0c;它可以管理硬件也可以管理软件 2.操作系统如何管理&#xff1f; 三、进程 1.概念 总结 四、linux中对进程的管理 1.task_ struct内容分类 2.查看进…

解决Linux环境Qt报“cannot find -lgl“问题

今天&#xff0c;在Ubuntu 18.04.6环境下&#xff0c;安装Qt5.14.2之后&#xff0c;运行一个QWidget工程&#xff0c;发现Qt报"cannot find -lgl"错误。     出现这种现象的原因&#xff1a;Qt的Path路径没有配置&#xff0c;缺少libqt4-dev依赖包和一些必要的组件…

Redis基础教程(九):redis有序集合

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

从“钓”到“管”:EasyCVR一体化视频解决方案助力水域安全管理

一、背景 随着城市化进程的加快&#xff0c;越来越多的市民热衷于钓鱼活动。钓鱼活动在带来乐趣的同时&#xff0c;也伴随着一定的安全隐患。尤其是在一些危险水域&#xff0c;也经常出现垂钓者的身影&#xff0c;非法垂钓&#xff0c;这给城市管理带来了不小的阻力。传统的人…

如何处理 PostgreSQL 中由于表连接顺序不当导致的性能问题?

文章目录 一、理解表连接和连接顺序二、识别由于表连接顺序不当导致的性能问题三、影响表连接顺序的因素四、解决方案手动调整连接顺序创建合适的索引分析数据分布和优化查询逻辑 五、示例分析手动调整连接顺序创建索引优化查询逻辑 六、总结 在 PostgreSQL 中&#xff0c;表连…

【Docker安装】OpenEuler系统下部署Docker环境

【Docker安装】OpenEuler系统下部署Docker环境 前言一、本次实践介绍1.1 本次实践规划1.2 本次实践简介二、检查本地环境2.1 检查操作系统版本2.2 检查内核版本2.3 检查yum仓库三、卸载Docker四、部署Docker环境4.1 配置yum仓库4.2 检查可用yum仓库4.3 安装Docker4.4 检查Docke…

绝区贰--及时优化降低 LLM 成本和延迟

前言 大型语言模型 (LLM) 为各行各业带来了变革性功能&#xff0c;让用户能够利用尖端的自然语言处理技术处理各种应用。然而&#xff0c;这些强大的 AI 系统的便利性是有代价的 — 确实如此。随着 LLM 变得越来越普及&#xff0c;其计算成本和延迟可能会迅速增加&#xff0c;…

Linux配置固定ip地址

虚拟机的Linux操作系统&#xff0c;其IP地址是通过DHCP服务获取的 DHCP&#xff1a;动态获取IP地址&#xff0c;即每次重启设备后都会获取一次&#xff0c;可能导致IP地址频繁变更。 一般系统默认的ip地址设置都是自动获取&#xff0c;故每次系统重启后ip地址都可能会不一样&a…

Redis的使用(二)redis的命令总结

1.概述 这一小节&#xff0c;我们主要来研究一下redis的五大类型的基本使用&#xff0c;数据类型如下&#xff1a; redis我们接下来看一看这八种类型的基本使用。我们可以在redis的官网查询这些命令:Commands | Docs,同时我们也可以用help 数据类型查看命令的帮助文档。 2. 常…

FastAPI教程——部署

部署 部署FastAPI应用程序相对容易。 部署是什么意思 部署应用程序意味着执行必要的步骤以使其可供用户使用。 对于Web API来说&#xff0c;通常涉及将上传到云服务器中&#xff0c;搭配一个性能和稳定性都不错的服务器程序&#xff0c;以便你的用户可以高效地访问你的应用…

Ubuntu安装Docker

一&#xff0c;Docker简介 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化&#xff0c;容器是完全使用沙箱机制&#xff0c;相互之间不会有…

论文回顾 | CVPR 2021 | How to Calibrate Your Event Camera | 基于图像重建的事件相机校准新方法

论文速览 | CVPR 2021 | How to Calibrate Your Event Camera | 基于图像重建的事件相机校准新方法 1 引言 在计算机视觉和机器人领域,相机校准一直是一个基础而又重要的问题。传统的相机校准方法主要依赖于从已知校准图案中提取角点,然后通过优化算法求解相机的内参和外参。这…

DDR3(三)

目录 1 预取1.1 什么是预取1.2 预取有哪些好处1.3 结构框图1.4 总结 2 突发2.1 什么是突发2.2 突发与预取 本文讲解DDR中常见的两个术语&#xff1a;预取和突发&#xff0c;对这两个概念理解的关键在于地址线的低位是否参与译码&#xff0c;具体内容请继续往下看。 1 预取 1.1…

创新配置,秒级采集,火爆短视频评论抓取

快速采集评论数据的好处 快速采集评论数据是在当今数字信息时代的市场趋势分析和用户反馈分析中至关重要的环节。通过准确获取并分析大量用户评论&#xff0c;您将能够更好地了解消费者的需求、情感和偏好。集蜂云采集平台提供了一种简单配置的方法&#xff0c;使您能够快速采…

离线安装arm架构Firefox

离线安装Firefox浏览器及其插件在ARM架构的设备上&#xff08;如树莓派、部分Android设备或其他采用ARM处理器的Linux系统&#xff09;可能需要一些特殊步骤&#xff0c;因为默认情况下&#xff0c;大多数浏览器和插件都是为x86架构设计的。对于ARM架构&#xff0c;你需要找到特…

Leetcode 338. 比特位计数

给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;[0,1,1] 解释&#xff1a; 0 --> 0 1 --> 1…

C#/WPF 自制截图工具

在日常使用电脑办公时&#xff0c;我们经常遇到需要截图然后保存图片&#xff0c;我们往往需要借助安装截图工具才能实现&#xff0c;现在我们通过C#自制截图工具&#xff0c;也能够轻松进行截图。 我们可以通过C#调用WindousAPI来实现截图&#xff0c;实例代码如下&#xff1a…

uni-app x 跨平台开发框架

目录 uni-app x 是什么 和Flutter对比 uts语言 uvue渲染引擎 组合式API的写法 选项式API写法 页面生命周期 API pages.json全局配置文件 总结 uni-app x 是什么 uni-app x&#xff0c;是下一代 uni-app&#xff0c;是一个跨平台应用开发引擎。 uni-app x 是一个庞…

计算机网络-IP组播基础

一、概述 在前面的学习交换机和路由协议&#xff0c;二层通信是数据链路层间通信&#xff0c;在同一个广播域间通过源MAC地址和目的MAC地址进行通信&#xff0c;当两台主机第一次通信由于不清楚目的MAC地址需要进行广播泛洪&#xff0c;目的主机回复自身MAC地址&#xff0c;然后…