tkinter绘制组件(44)——浮出ui控件

tkinter绘制组件(44)——浮出ui控件

  • 引言
  • 布局
    • 函数结构
    • ui框架
    • 对齐方向
    • 绑定已有控件
    • 出现和隐藏逻辑
    • 出现和隐藏动画
    • 完整代码函数
  • 效果
    • 测试代码
    • 最终效果
  • github项目
  • pip下载

引言

TinUI的浮出ui控件(flyout)其实是一个之间创建在UI框架内的完整BasicTinUI类,且已经绑定了TinUIXml。该控件并不之间占有窗口句柄,因此可以大量创建,包括但不限于:

  1. 弹出已有控件的说明
  2. 绑定已有控件,弹出某个操作、用法的说明
  3. 绑定已有控件,弹出简单的内部对话框或说明

从上面罗列的使用场景可以看出,flyout就是用来作为窗口内提示与简单交互的,只不过是一个轻量的UI框架,和TinUI的内嵌ui控件(ui)非常类似,只不过绑定在了已有的控件。


布局

函数结构

def add_flyout(self, fid, width:int=250, height:int=150, bind='<Button-1>', line='#dcdcdc', bg='#f9f9f9', anchor='n'):# 绘制一个浮出ui控件
    # 注意,默认布局在fid正上方
    """
    fid::绑定控件的uid
    width::宽度
    height::高度
    bind::绑定的事件
    line::边框颜色
    bg::背景颜色
    anchor::展开方向
    """

ui框架

上文说过,flyout本质就是一个BasicTinUI。

ui = BasicTinUI(self, bg=bg, highlightbackground=line, highlightthickness=1, relief='flat')
uixml = TinUIXml(ui)

对齐方向

由于是弹出控件,因此flyout的anchor不再代表控件本身的对齐方向,而是指布局在绑定控件的那一侧。比如n就代表正上方,nw代表左上方。

bbox = self.bbox(fid)
if anchor == 'nw':
    x = bbox[0] - 4
    y = bbox[1] - 4
    _anchor = 'se'
    dxy = (1, 1)
elif anchor == 'n':
    x = (bbox[0] + bbox[2]) / 2
    y = bbox[1] - 4
    _anchor ='s'
    dxy = (0, 1)
elif anchor == 'ne':
    x = bbox[2] + 4
    y = bbox[1] - 4
    _anchor = 'sw'
    dxy = (1, 1)
elif anchor == 'e':
    x = bbox[2] + 4
    y = (bbox[1] + bbox[3]) / 2
    _anchor = 'w'
    dxy = (1, 0)
elif anchor =='se':
    x = bbox[2] + 4
    y = bbox[3] + 4
    _anchor = 'nw'
    dxy = (1, 1)
elif anchor =='s':
    x = (bbox[0] + bbox[2]) / 2
    y = bbox[3] + 4
    _anchor = 'n'
    dxy = (0, 1)
elif anchor =='sw':
    x = bbox[0] - 4
    y = bbox[3] + 4
    _anchor = 'ne'
    dxy = (1, 1)
elif anchor == 'w':
    x = bbox[0] - 4
    y = (bbox[1] + bbox[3]) / 2
    _anchor = 'e'
    dxy = (1, 0)
else:# 默认为center
    x = (bbox[0] + bbox[2]) / 2
    y = (bbox[1] + bbox[3]) / 2
    _anchor = 'center'
    dxy = (1, 1)
uid = self.create_window(x, y, width=width, height=height, window=ui, anchor=_anchor)

dxy稍后解释

绑定已有控件

self.itemconfig(uid, state='hidden')
self.tag_bind(fid, bind, show)

出现和隐藏逻辑

出现逻辑很显然,就是对于绑定控件的绑定事件,默认就是左键单击。

对于隐藏逻辑,我能够想到的就是左键单击本UI框架,这样做可以减少对其他不确定元素的依赖,且BasicTinUI本身不对单击做出响应,也不应该对单击做出响应(窗口单击获得焦点是系统层决定,这不影响)。单击本UI框架收回flyout是比较合理的。

def show(e):
    self.tag_unbind(fid, bind)# 避免接下来绑定self <button-1>事件时同步触发
    self.itemconfig(uid, state='normal')
    motion(None, 1)
    self.after(100, go_to_bind)# 避免直接触发控件点击事件
def go_to_bind():
    self.bind('<Button-1>', hide)
def hide(e):
    self.unbind('<Button-1>')
    self.tag_bind(fid, bind, show)
    motion(None, -1)
    self.itemconfig(uid, state='hidden')

注意上面代码片段中的两个注释内容,简单来说就是避免绑定控件左键单击和本UI框架左键单击同时触发,导致showhide调用混乱。

出现和隐藏动画

这就涉及到前文提到的dxy,且内容就是x和y方向,需要变化的为1,不需要变化的为0。

此外,motion函数的dis参数为1表示展开,-1表示收缩。

def motion(e, dis):
    # 展开/收缩动画
    # dxy为动画方向,0为不变,1为变化
    if dis == 1:
        # 展开
        _width = width * (1-dxy[0])
        _height = height * (1-dxy[1])
        dwidth = width / 10 * dxy[0]
        dheight = height / 10 * dxy[1]
    else:
        # 收缩
        _width = width
        _height = height
        dwidth = -width / 10 * dxy[0]
        dheight = -height / 10 * dxy[1]
    for _ in range(10):
        time.sleep(0.01)
        _width += dwidth
        _height += dheight
        self.itemconfig(uid, width=_width, height=_height)
        self.update_idletasks()

完整代码函数

def add_flyout(self, fid, width:int=250, height:int=150, bind='<Button-1>', line='#dcdcdc', bg='#f9f9f9', anchor='n'):# 绘制一个浮出ui控件
    # 注意,默认布局在fid正上方
    def show(e):
        self.tag_unbind(fid, bind)# 避免接下来绑定self <button-1>事件时同步触发
        self.itemconfig(uid, state='normal')
        motion(None, 1)
        self.after(100, go_to_bind)# 避免直接触发控件点击事件
    def go_to_bind():
        self.bind('<Button-1>', hide)
    def hide(e):
        self.unbind('<Button-1>')
        self.tag_bind(fid, bind, show)
        motion(None, -1)
        self.itemconfig(uid, state='hidden')
    def motion(e, dis):
        # 展开/收缩动画
        # dxy为动画方向,0为不变,1为变化
        if dis == 1:
            # 展开
            _width = width * (1-dxy[0])
            _height = height * (1-dxy[1])
            dwidth = width / 10 * dxy[0]
            dheight = height / 10 * dxy[1]
        else:
            # 收缩
            _width = width
            _height = height
            dwidth = -width / 10 * dxy[0]
            dheight = -height / 10 * dxy[1]
        for _ in range(10):
            time.sleep(0.01)
            _width += dwidth
            _height += dheight
            self.itemconfig(uid, width=_width, height=_height)
            self.update_idletasks()
    ui = BasicTinUI(self, bg=bg, highlightbackground=line, highlightthickness=1, relief='flat')
    uixml = TinUIXml(ui)
    # 围绕fid进行布局
    bbox = self.bbox(fid)
    if anchor == 'nw':
        x = bbox[0] - 4
        y = bbox[1] - 4
        _anchor = 'se'
        dxy = (1, 1)
    elif anchor == 'n':
        x = (bbox[0] + bbox[2]) / 2
        y = bbox[1] - 4
        _anchor ='s'
        dxy = (0, 1)
    elif anchor == 'ne':
        x = bbox[2] + 4
        y = bbox[1] - 4
        _anchor = 'sw'
        dxy = (1, 1)
    elif anchor == 'e':
        x = bbox[2] + 4
        y = (bbox[1] + bbox[3]) / 2
        _anchor = 'w'
        dxy = (1, 0)
    elif anchor =='se':
        x = bbox[2] + 4
        y = bbox[3] + 4
        _anchor = 'nw'
        dxy = (1, 1)
    elif anchor =='s':
        x = (bbox[0] + bbox[2]) / 2
        y = bbox[3] + 4
        _anchor = 'n'
        dxy = (0, 1)
    elif anchor =='sw':
        x = bbox[0] - 4
        y = bbox[3] + 4
        _anchor = 'ne'
        dxy = (1, 1)
    elif anchor == 'w':
        x = bbox[0] - 4
        y = (bbox[1] + bbox[3]) / 2
        _anchor = 'e'
        dxy = (1, 0)
    else:# 默认为center
        x = (bbox[0] + bbox[2]) / 2
        y = (bbox[1] + bbox[3]) / 2
        _anchor = 'center'
        dxy = (1, 1)
    uid = self.create_window(x, y, width=width, height=height, window=ui, anchor=_anchor)
    self.itemconfig(uid, state='hidden')
    self.tag_bind(fid, bind, show)
    return ui, uixml, hide, uid

效果

测试代码

flylabel = b.add_label((1500,500),text='点击展开浮出UI')[-1]
_, flyxml, flyhide, _ = b.add_flyout(flylabel)
flyxml.funcs['flyhide']=flyhide
flyxml.loadxml('''<tinui><line><paragraph text='浮出UI'></paragraph></line>
               <line><paragraph text='add_flyout(fid, anchor="...")'></paragraph></line>
               <line><paragraph text='使用hide关闭'></paragraph></line>
<line><button2 text='关闭浮出UI控件' command="self.funcs['flyhide']"></button2>
</line></tinui>''')

最终效果

在这里插入图片描述


github项目

TinUI的github项目地址

pip下载

pip install tinui

🔆tkinter创新🔆

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SAP MM 记录一次SAP外协采购收货提示 这种物料的特殊库存 O 0100003359 14019002不存在的问题

根据采购订单收货&#xff0c;调用时 BAPI_GOODSMVT_CREATE时返回 { "TYPE":"E", "ID":"M7", "NUMBER":"076", "MESSAGE":"这种物料的特殊库存 O 0100003359 14019002不存在"…

noteboolm 使用笔记

今天心血来潮&#xff0c;想要体验下AInotebook&#xff0c;看看最新的软件能够做到什么程度。 于是来到了notebooklm&#xff0c;这是一个google推出的AI笔记本的网站&#xff0c;我想知道我们能在上面做一些怎么样有趣的事情&#xff01; 网址&#xff1a;https://notebookl…

【Pytest】生成html报告中,中文乱码问题解决方案

import pytestif __name__ "__main__":# 只运行 tests 目录下的测试用例&#xff0c;并生成 HTML 报告pytest.main([-v, -s, --htmlreport.html, tests])可以以上方式生成&#xff0c;也可以在pytest.ini中设置 [pytest] addopts --htmlreport.html --self-contai…

[STM32 - 野火] - - - 固件库学习笔记 - - -十二.基本定时器

一、定时器简介 STM32 中的定时器&#xff08;TIM&#xff0c;Timer&#xff09;是其最重要的外设之一&#xff0c;广泛用于时间管理、事件计数和控制等应用。 1.1 基本功能 定时功能&#xff1a;TIM定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中…

2025.1.26机器学习笔记:C-RNN-GAN文献阅读

2025.1.26周报 文献阅读题目信息摘要Abstract创新点网络架构实验结论缺点以及后续展望 总结 文献阅读 题目信息 题目&#xff1a; C-RNN-GAN: Continuous recurrent neural networks with adversarial training会议期刊&#xff1a; NIPS作者&#xff1a; Olof Mogren发表时间…

深度学习项目--基于LSTM的糖尿病预测探究(pytorch实现)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 LSTM模型一直是一个很经典的模型&#xff0c;一般用于序列数据预测&#xff0c;这个可以很好的挖掘数据上下文信息&#xff0c;本文将使用LSTM进行糖尿病…

【数据结构】_不带头非循环单向链表

目录 1. 链表的概念及结构 2. 链表的分类 3. 单链表的实现 3.1 SList.h头文件 3.2 SList.c源文件 3.3 Test_SList.c测试文件 关于线性表&#xff0c;已介绍顺序表&#xff0c;详见下文&#xff1a; 【数据结构】_顺序表-CSDN博客 本文介绍链表&#xff1b; 基于顺序表…

HippoRAG:受海马体启发的长时记忆模型,提升大语言模型的知识整合能力

论文地址&#xff1a;https://arxiv.org/pdf/2405.14831 1. 背景与挑战 1.1 哺乳动物大脑与长时记忆 进化优势: 哺乳动物的大脑进化出强大的长时记忆系统&#xff0c;能够存储大量关于世界的知识&#xff0c;并不断整合新信息&#xff0c;同时避免灾难性遗忘。知识整合能力: …

Juc22_什么是中断、interrupt、isInterrupted、interrupted方法源码解析、如何使用中断标识停止线程

目录 ①. 什么是中断 ②. 源码解读(中断的相关API) ③. 如何使用中断标识停止线程 ①. 什么是中断 ①. 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,所以,Thread.stop、Thread.suspend、Thread. resume都已经被废弃了 ②. 在Java中没有办法立即停止…

网络安全 | F5-Attack Signatures详解

关注&#xff1a;CodingTechWork 关于攻击签名 攻击签名是用于识别 Web 应用程序及其组件上攻击或攻击类型的规则或模式。安全策略将攻击签名中的模式与请求和响应的内容进行比较&#xff0c;以查找潜在的攻击。有些签名旨在保护特定的操作系统、Web 服务器、数据库、框架或应…

项目概述与规划 (I)

项目概述与规划 (I) JavaScript的学习已经接近尾声了&#xff0c;最后我们将通过一个项目来讲我们在JavaScript中学习到的所有都在这个项目中展现出来&#xff0c;这个项目的DEMO来自于Udemy中的课程&#xff0c;作者是Jonas Schmedtmann&#xff1b; 项目规划 项目步骤 用户…

RabbitMQ 架构分析

文章目录 前言一、RabbitMQ架构分析1、Broker2、Vhost3、Producer4、Messages5、Connections6、Channel7、Exchange7、Queue8、Consumer 二、消息路由机制1、Direct Exchange2、Topic Exchange3、Fanout Exchange4、Headers Exchange5、notice5.1、备用交换机&#xff08;Alter…

基于java线程池和EasyExcel实现数据异步导入

基于java线程池和EasyExcel实现数据异步导入 2.代码实现 2.1 controller层 PostMapping("import")public void importExcel(MultipartFile file) throws IOException {importService.importExcelAsync(file);}2.2 service层 Resource private SalariesListener sa…

微信阅读网站小程序的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

【吉林乡镇界】面图层shp格式arcgis数据乡镇名称和编码wgs84无偏移内容测评

标题中的“吉林省乡镇界面图层shp格式arcgis数据乡镇名称和编码wgs84无偏移”揭示了这是一个地理信息系统&#xff08;GIS&#xff09;相关的数据集&#xff0c;主要用于描绘吉林省的乡镇边界。这个数据集包含了一系列的文件&#xff0c;它们是ArcGIS软件能够识别和处理的Shape…

71.在 Vue 3 中使用 OpenLayers 实现按住 Shift 拖拽、旋转和缩放效果

前言 在前端开发中&#xff0c;地图功能是一个常见的需求。OpenLayers 是一个强大的开源地图库&#xff0c;支持多种地图源和交互操作。本文将介绍如何在 Vue 3 中集成 OpenLayers&#xff0c;并实现按住 Shift 键拖拽、旋转和缩放地图的效果。 实现效果 按住 Shift 键&#…

Python NumPy(3):创建数组(2)

1 NumPy 从已有的数组创建数组 1.1 numpy.asarray numpy.asarray 类似 numpy.array&#xff0c;但 numpy.asarray 参数只有三个&#xff0c;比 numpy.array 少两个。 numpy.asarray(a, dtype None, order None) 参数描述a任意形式的输入参数&#xff0c;可以是&#xff0c…

qml Dialog详解

1、概述 Dialog是QML&#xff08;Qt Modeling Language&#xff09;中用于显示对话框的组件&#xff0c;它提供了一个模态窗口&#xff0c;通常用于与用户进行重要交互&#xff0c;如确认操作、输入信息或显示警告等。Dialog组件具有灵活的布局和样式选项&#xff0c;可以轻松…

二维数组一

目录 输出数组的第k行数输出数组的第k列数输出数组的每一行的和输出数组的每列的平均值最高成绩各个科目成绩的平均分求最大梯形的面积入门靶心数奇偶统计 输出数组的第k行数 题目描述 输入一个二维数组&#xff0c;显示他的第k行的值。 输入 第一行 n&#xff0c;m两个整数&…

单片机内存管理剖析

一、概述 在单片机系统中&#xff0c;内存资源通常是有限的&#xff0c;因此高效的内存管理至关重要。合理地分配和使用内存可以提高系统的性能和稳定性&#xff0c;避免内存泄漏和碎片化问题。单片机的内存主要包括程序存储器&#xff08;如 Flash&#xff09;和数据存储器&a…