Kivy tutorial 004: Making the GUI do stuff, binding to events

news2024/11/24 19:39:24

Kivy tutorial 004: Making the GUI do stuff, binding to events – Kivy Blog

Central themes: Events and Kivy properties
中心主题:事件和kivy属性

We left the last tutorial with a calculator app GUI with some nice automatic behaviour, but which doesn’t actually do anything. Let’s change that; it’s time to learn about binding events.
上次导师课我们留下了一个有着一些不错的自动行为的计算机GUI,但是这真是啥也不干。让我们改变它,是时候了解绑定事件了。

To refresh, the basic calculator GUI code was as follows. If you modified it to experiment, feel free to continue with your modified code, and try to change the instructions to fit your modifications:
为了重新刷新,基本的计算机GUI代码像下面一样。如果你修改它来体验,随意继续修改你的代码,并且试着改变结构来达到你的修改。

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label


class YourApp(App):
    def build(self):
        root_widget = BoxLayout(orientation='vertical')

        output_label = Label(size_hint_y=1)

        button_symbols = ('1', '2', '3', '+',
                          '4', '5', '6', '-',
                          '7', '8', '9', '.',
                          '0', '*', '/', '=')

        button_grid = GridLayout(cols=4, size_hint_y=2)
        for symbol in button_symbols:
            button_grid.add_widget(Button(text=symbol))

        clear_button = Button(text='clear', size_hint_y=None,
                              height=100)

        root_widget.add_widget(output_label)
        root_widget.add_widget(button_grid)
        root_widget.add_widget(clear_button)

        return root_widget


YourApp().run()

Note

This tutorial introduces some major new Kivy concepts. I recommend working through it even if you don’t entirely follow what’s going on, then going back to modify components and see how things change.
这节导师课介绍一些主要的kivy概念。 我建议克服它尽管你没有整个的跟随事态的进行,然后返回修改部件并且看看事如何改变的。

The plan now is that every one of these buttons should add their symbol to the Label at the top, except ‘=’ which should evaluate the code and display the result. This is obviously an extremely basic calculator, but the point here is to showcase some Kivy basics - if you’d like to improve the interface, go ahead with trying to do so along the way.
现在的计划是每个按钮应该增加他们的符号到标签的上面, 除了=号应该求值并且展示结果。这是一个极其明显的基础的计算机,但是这的关键点是展示一些kivy的基本要素-如果你想来提升界面,继续沿着这种方式继续尝试。

To make the buttons do something, we must bind to their events. This is a generic Kivy concept; whenever you want one thing to trigger another, you look for an event to bind to. Some widgets such as Button have events indicating they have been clicked on, and every Kivy property (such as all those used to customise Widgets so far) has an associated event when it changes.
为了让按钮做点事,我们必须bind绑定给它们的事件。这是一个通用kivy概念,当你像一个事引发另一个事的时候,你寻找一个事件来帮i的那个。一些组件例如Button按钮有些事件表明它们已经被点击了,并且每个kivy属性(例如所有的这些都是被用来自定义组件)有一个关联事件当它改变时。

Let’s start with a simple binding example: 让我们开始一个简单地bind绑定案例:

def print_button_text(self, instance):
    print(instance.text)
for button in button_grid.children[1:]:  # note use of the
                                         # `children` property
    button.bind(on_press=print_button_text)

# we could also have used `button.bind(on_press=lambda instance: print(instance.text))`

If you run the code now, and click on any of the buttons, you should see its text printed in the console (but not in the Kivy GUI).
如果你现在运行代码,并且点击任何按钮,你应该看见它的text信息在console控制台中打印出来(不是在KIVY的GUI中)

The key concept here is the bind method, which you can use with any Widget, as well as several other Kivy objects (discussed in later tutorials). This takes any number of keyword arguments, each specifying an event name and a function to call; in this case the event name is on_press, and the function to be called is our new print_button_text`. The ``bind` method makes sure that whenever on_press occurs, the function is called. It automatically receives a single argument, the binded widget instance.
这儿的主要概念是绑定方法, 你可以同任何组件使用绑定方法,和好几个个其他的kivy对象(之后的导师课会有涉及)。这携带任何关键字的元素,每个关键字元素特别说明一个event事件名字和一个功能来召唤;在情况下,event事件名字是 on_press, 并且  被使唤的功能是 我们的print_button_text。  bind 方法确保当 on_press出现时,功能被使唤。 它自动地接收一个单一的变量,这变量时被绑定的组件实例。

Also note that we’ve iterated over button_grid.children[1:]`. The ``children` property is available on any Widget, and holds a list of all the widgets added to it, in reverse order. In this case, we use [1:] to skip the first element, ‘=’, as we want to use this to evaluate the result.
也请注意我们已经和button_grid.children[1:]互动了。  子类属性在任何组件中都适用,并且包含了一个所有组件添加其中的list列表,这列表是反序的。在这种情况下,我们使用[1:] 来跳过第一个元素, '='向我们想的一样使用这玩意来求结果的值。

Note

Button also has an on_release event that is called when the user releases a click or touch. You can find more information in the Button documentation.
按钮也有一个on_release事件,当一个用户松开一个点击或者触摸 这on_release事件被使唤。你可以发现更多的信息在 Button文档中。

This binding idea is very normal in Kivy, and you’ll quickly get used to seeing it used in different ways, including some introduced later in these tutorials. The kv markup language, also introduced later, has special syntax designed to make it even simpler and clearer.
在kivy 绑定想法非常常见,并且你可以快速地习惯来看它在不同的方式中使用。在之后的导师课中会有介绍。 kv 标记语言, 也在之后被介绍, 有特殊地语法被设计来让代码更简单和更清晰。

Anyway, all this does so far is print some text when the event occurs, but we want to update the GUI. Let’s change the bound function to achieve that:
无论如何,所有干的这些当目前为止是,当事件出现时打印了一些文本,但是我们想要更新GUI。 让我们改变被捆绑的功能来实现它:

def print_button_text(instance):
    output_label.text += instance.text

Run the code again. Now when you press the buttons, you should see the text appear at the top of the screen, as in the screenshot below:
再次运行代码。现在当你按按钮,你应该看到文本出现在屏幕地商法,像下面截图一样:

Calculator text after number input

At this point, a new problem presents itself; the font size of the label is kind of small. We can use another event to have it update automatically in response to the label’s height:
在这时,一个新的问题它自己出现了;标签地大小有点小了。我们可以使用另一个事件来让它自动地更新来响应标签的高度:

def resize_label_text(label, new_height):
    label.font_size = 0.5*label.height
output_label.bind(height=resize_label_text)

Note that the event here is named height. This works because the Label has a Kivy property named height (as do all Widgets, see the documentation, and all Kivy properties can be bound to as an event of the same name, called when the property changes. In this case, you can now resize the window, which causes the layouts in the Widget tree to automatically resize their children, which in turn causes resize_label_text to automatically be called.
注意现在这地事件被命名为高度。 这行, 因为Label标签有一个kivy属性被叫做height高度(所有的组件都这么干,看文档, 所有的kivy属性可以被绑定作为一个这相同名字的事件,当属性改变时被叫唤。在这种情况下,你现在可以重新定义窗口的大小,这也导致了布局里的组件树自动地定义它的子类大小,这也相继地导致  resize_label_text 自动地被使唤。

We’ll use one final binding to make the calculator interface actually work; when the ‘=’ button is pressed, we can evaluate the entire label text as python code, and display the result.
我们将使用一个最终的绑定来使计算机界面真实起效;当= 号按钮被按下时,我们可以求出整个label标签里的值作为python代码,并且展示结果。

Note

Using eval as a calculator like this is in general a terrible idea, used here only to avoid dwelling on the details rather than the Kivy principles.

像这样使用eval求值  作为计算器通常是一个糟糕的想法,这里使用它只是为了避免纠缠于细节而不是Kivy原则。

def evaluate_result(instance):
    try:
        output_label.text = str(eval(output_label.text))
    except SyntaxError:
        output_label.text = 'Python syntax error!'
button_grid.children[0].bind(on_press=evaluate_result)
# Remember, button_grid.children[0] is the '=' button

Further, we can make the ‘clear’ button clear the label, so that you can start a new calculation:

另一方面我们使 clear按钮清空label 标签,因此可以开始一个新的计算:

def clear_label(instance):
    output_label.text = ''
clear_button.bind(on_press=clear_label)

With this all in place, run the app again and…the calculator works! Every button now does something, either adding its symbol to the output label, evaluating the label’s text as python code, or clearing the result. You should be seeing something like the image below:

这些就绪以后,再次运行app... 计算机运行了!  现在每个按钮干了些事,要么添加他的符号给输出标签, 求作为python代码的标签文本值, 或者清空结果。 你应该看像下面图片一样的事儿:

Output for calculator app with number input

These core event binding concepts are central to working with Kivy widgets, and come up in many different ways. Don’t worry if you don’t remember all the details straight away, such as the way all properties have events you can bind to, or the specific syntax; you can look all this up in the documentation as linked throughout and indexed on the Kivy website. Later tutorials also follow on to help cement this knowledge.
这些代码绑定概念是kivy组件的核心,并且以不同的方式出现。 如果你不能立即记得所有的细节,例如所有的属性都可以由你绑定的事件, 或者特殊的语法; 你可以在文档中查询这所有的全部,就像在文中超链接所示。等会导师课跟随着帮助加强知识。

Full code

your_filename.py:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label


class YourApp(App):
    def build(self):
        root_widget = BoxLayout(orientation='vertical')

        output_label = Label(size_hint_y=1)

        button_symbols = ('1', '2', '3', '+',
                          '4', '5', '6', '-',
                          '7', '8', '9', '.',
                          '0', '*', '/', '=')

        button_grid = GridLayout(cols=4, size_hint_y=2)
        for symbol in button_symbols:
            button_grid.add_widget(Button(text=symbol))

        clear_button = Button(text='clear', size_hint_y=None,
                              height=100)

        def print_button_text(instance):
            output_label.text += instance.text
        for button in button_grid.children[1:]:  # note use of the
                                             # `children` property
            button.bind(on_press=print_button_text)

        def resize_label_text(label, new_height):
            label.font_size = 0.5*label.height
        output_label.bind(height=resize_label_text)

        def evaluate_result(instance):
            try:
                output_label.text = str(eval(output_label.text))
            except SyntaxError:
                output_label.text = 'Python syntax error!'
        button_grid.children[0].bind(on_press=evaluate_result)

        def clear_label(instance):
            output_label.text = ''
        clear_button.bind(on_press=clear_label)

        root_widget.add_widget(output_label)
        root_widget.add_widget(button_grid)
        root_widget.add_widget(clear_button)

        return root_widget


YourApp().run()

eval

Python eval() 函数 | 菜鸟教程

困惑: button_grid.children[0].bind(on_press=evaluate_result),为啥用这布局中的第一个元素绑定str后的eval后的值呢?为啥不是第二个值呢?

我溜达了半天,人家文中说的很明白,children这玩意与生俱来,并且是in reverse order!反序!

也就是说,根据咱添加按钮的顺序,button_grid.children[0]是什么呢?

我1开始在代码中添加了

print(button_grid.children)

结果是

[<kivy.uix.button.Button object at 0x00000163EA850510>, <kivy.uix.button.Button object at 0x00000163EA850200>, <kivy.uix.button.Button object at 0x00000163EA810EB0>, <kivy.uix.button.Button object at 0x00000163EA810BA0>, <kivy.uix.button.Button object at 0x00000163EA810890>, <kivy.uix.button.Button object at 0x00000163EA810580>, <kivy.uix.button.Button object at 0x00000163EA810270>, <kivy.uix.button.Button object at 0x00000163EA7D4F20>, <kivy.uix.button.Button object at 0x00000163EA7D4C10>, <kivy.uix.button.Button object at 0x00000163EA7D4900>, <kivy.uix.button.Button object at 0x00000163EA7D45F0>, <kivy.uix.button.Button object at 0x00000163EA7D42E0>, <kivy.uix.button.Button object at 0x00000163E01DBF90>, <kivy.uix.button.Button object at 0x00000163E01DBC80>, <kivy.uix.button.Button object at 0x00000163E01DB970>, <kivy.uix.button.Button object at 0x00000163E01DB5F0>]

这谁能看懂,也不知道咋处理,那反序的话不就是咱最后添加的按钮,  =号嘛

人家把算好的结果绑定给 等于号=怎么了? 不就是绑定给=等于号吗? XDD

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Cloud - 开发环境搭建

1、JDK环境安装 1、下载jdk17&#xff1a;下载地址&#xff0c;在下图中红色框部分进行下载 2、双击安装&#xff0c;基本都是下一步直到完成。 3、设置系统环境变量&#xff1a;参考 4、设置JAVA_HOME环境变量 5、在PATH中添加%JAVA_HOME%/bin 6、在命令行中执行&#xff1a;j…

大厂薪资福利篇第五弹:小红书

欢迎来到绝命Coding&#xff01; 今天继续更新大家最关心的 大厂薪资福利系列&#xff01; 为什么计算机学子对大厂趋之若鹜呢&#xff1f;最直接的原因就是高薪资的吸引力。 • 但是薪资可不是简单的数字哦&#xff0c;里面还是有很多“学问”的。 • 很多同学对大厂薪资只有一…

嵌入式C语言中常见寄存器的控制方法

使用C语言对寄存器赋值时,常常需要用到C语言的位操作方法。 把寄存器某位清零 假设a代表寄存器,且其中本来已有值。如果要把其中某一位清零且其它位不变,代码如下。 //定义一个变量 a = 1001 1111 b (二进制数)unsigned char a = 0x9f;//对 bit2 清零a &= ~(1<<…

YOLO系列改进

yolo核心思想&#xff1a;把目标检测转变成一个回归问题。将整个图像作为网络的输入&#xff0c;仅仅经过一个神经网络&#xff0c;得到边界框的位置及其所属的类别。 YOLOv1 CVPR2016 输出7730的张量表示2个框的5个参数和20个种类。leaky ReLU&#xff0c;leaky并不会让负数…

深度学习入门2—— 神经网络的组成和3层神经网络的实现

由上一章结尾&#xff0c;我们知道神经网络的一个重要性质是它可以自动地从数据中学习到合适的权重参数。接下来会介绍神经网络的概要&#xff0c;然后再结合手写数字识别案例进行介绍。 1.神经网络概要 1.1从感知机到神经网 我们可以用图来表示神经网络&#xff0c;我们把最…

【Docker】容器

目录 1. 容器启动 2. 容器启动/重启/停止 3. 进入容器 4. 容器查询 5. docker 镜像的构建 方式一&#xff1a;docker 容器 commit 方式二&#xff1a;Dockerfile 定制镜像 1. 容器启动 docker run –it/-d –p/P –name imageID/name 2. 容器启动/重启/停止 docker sta…

MySQL索引优化解决方案--索引失效(3)

索引失效情况 最佳左前缀法则&#xff1a;如果索引了多列&#xff0c;要遵循最左前缀法则&#xff0c;指的是查询从索引的最左前列开始并且不跳过索引中的列。不在索引列上做任何计算、函数操作&#xff0c;会导致索引失效而转向全表扫描存储引擎不能使用索引中范围条件右边的…

文华6幅图指标公式大全-多空精准买卖点提示指标源码

文华6幅图指标公式大全-多空精准买卖点提示指标源码&#xff1a; HH: HHV ( HIGH ,1)/5 HHV ( HIGH ,2)/5 HHV ( HIGH ,2)/5 HHV ( HIGH ,5)/5 HHV ( HIGH ,8)/5; LL: LLV ( LOW ,1)/5 LLV ( LOW ,2)/5 LLV ( LOW ,2)/5 LLV ( LOW ,5)/5 LLV ( LOW ,8)/5; H1: IFELSE ( H &l…

西门子840dsl机床仿真软件配置opcua说明

需要的安装包如下&#xff0c;可在百度网盘中下载 主软件包&#xff1a;sinutrain-v4.7-ed4&#xff08;也可在官网中下载最新版本&#xff09; 用户文件&#xff1a;UserDataBase 授权sinutrain&#xff1a;Sim_EKB_Install_2021_06_22 链接&#xff1a;https://pan.baidu.c…

【传拓研学】传承文化瑰宝,领略千年韵味

非遗薪火&#xff0c;传承中华文明 文化繁荣&#xff0c;共筑美好未来 在这风云变幻的时代&#xff0c;我们始终怀揣着对历史与文化的敬仰之情。今日&#xff0c;我们隆重向您推荐一项极具意义的活动——传拓研学活动。 传拓是我国一项古老的传统技艺&#xff0c;非遗物质文…

REST API 中的 HTTP 请求参数

当我们在谈论现代 Web 开发时&#xff0c;REST API (Representational State Transfer Application Programming Interface) 扮演着至关重要的角色。它允许不同的系统以一种简洁且高效的方式进行通信。HTTP 请求参数是控制此通信流程中数据如何被发送和接收的重要组成部分。 H…

【Apache Doris】周FAQ集锦:第 8 期

【Apache Doris】周FAQ集锦&#xff1a;第 8 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户和…

杂记 | 搭建反向代理防止OpenAI API被封禁(对于此次收到邮件提示7月9日后将被屏蔽的解决参考)

文章目录 重要声明&#xff08;免责&#xff09;01 OpenAI封禁API的情况02 解决方案及原理2.1 原因分析2.2 解决方案2.3 步骤概述 03 操作步骤3.1 购买一个海外服务器3.2 申请一个域名3.3 将域名指向代理服务器3.4 在代理服务器上安装nginx3.5 配置反向代理 重要声明&#xff0…

IDEA启动报错:Abnormal build process termination...

一、问题描述 因为项目需要&#xff0c;同时打开了两个idea&#xff0c;突然发现一个启动的时候报错&#xff0c;有点莫名其妙&#xff0c;刚还好好的&#xff0c;为啥就不能用了&#xff0c;一顿百度找方法&#xff0c;试了各种方法&#xff0c;像重新安装jdk、重启系统发现都…

Linux源码阅读笔记04-实时调度类及SMP和NUMA

Linux进程分类 实时进程普通进程 如果系统中有一个实时进程并且可执行&#xff0c;调度器总是会选择他&#xff0c;除非有另外一个优先级高的实时进程。SCHED_FIFO&#xff1a;没有时间片&#xff0c;被调度器选择之后&#xff0c;可以运行任意长的时间。SCHED_RR&#xff1a;有…

轻松学AI绘画:PS AI插件,小白的入门秘籍

各位AIGC创意爱好者们&#xff0c;你们是否对AI绘画充满好奇&#xff0c;却又对那些复杂的国外软件感到望而却步&#xff1f;别急&#xff0c;今天我要为大家介绍一款适合新手的国产PS AI插件——StartAI&#xff0c;它将为你的创作之路带来无限可能&#xff01; StartAI&…

SSLyze:一款快速高效的SSLTLS扫描工具

关于SSLyze SSLyze是一款快速高效且功能强大的SSL/TLS扫描工具&#xff0c;同时它也是一个Python库。 SSLyze在与目标服务器连接成功之后&#xff0c;可以对目标目标服务器的SSL/TLS配置进行扫描和分析&#xff0c;并确保其使用健壮的加密设置&#xff0c;包括证书、密码套件和…

会议等级地址

1.https://www.cnblogs.com/bnuvincent/p/6809353.html 2. 会议之眼地址 https://www.conferenceeye.cn/home/submission/1 3. 学术之家https://www.xueshu.com/sci/41975/

cpp入门(命名空间,输入输出与缺省参数)

目录 cpp关键字 命名空间 命名空间的使用 1.加名称及作用域限定符 2.使用using将命名空间中某个成员引入 3.展开命名空间 注意 输入输出 缺省参数 cpp关键字 命名空间 定义命名空间&#xff0c;需要使用到namespace关键字&#xff0c;后面跟命名空间的名字&#xff0c…

IIC学习笔记(立创STMF4开发板)

目录 #I2C涉及相关知识 #I2C相关介绍 欢迎指正&#xff0c;希望对你&#xff0c;有所帮助&#xff01;&#xff01;&#xff01; 个人学习笔记&#xff0c;参考文献&#xff0c;链接最后&#xff01;&#xff01;&#xff01; #I2C涉及相关知识 SDA串行数据线&#xff1a; Ser…