ChatGPT自动化编程:三分钟用Tkinter搞定计算器

本文结合ChatGPT和GitHub Copilot是一个Tkinter版的计算器程序。Tkinter是Python的内置GUI库,不需要单独安装。 计算器程序有很多种类,本节会实现一个基本的计算器程序,在窗口上包含0到9一共10个数字按钮,以及“+”、“-”、“*”、“=”、“.”和“=”一共6个按钮,加一起一共16个按钮,正好是4行4列。具体的样式可以参考系统自身带的计算机程序,如图1就是macOS带的计算器程序的主界面。计算器的功能主要是单击除了“=”按钮外的其他按钮,会将按钮文本追加到计算器上方的文本输入框中,点击“=”按钮,会动态计算文本输入框中的表达式,双击文本输入框,会清空文本。

图1 macOS 版计算器

根据前面的描述,可以总结出实现这个计算器的几个关键点: (1)布局:需要使用类似网格布局的功能实现按钮的行列布局。 (2)响应按钮单击动作:单击非“=”按钮,会将按钮文本追加到文本输入框中,点击“=”按钮,会动态计算文本输入框中的表达式。 (3)文本框响应双击动作:双击文本框,会清空文本框的内容。

由于计算器的业务逻辑比较复杂,尽管ChatGPT可以接收大量的输入文本,但如果编程任务过于复杂,ChatGPT可能只会实现一部分,或有遗漏,所以可以分步骤实现这个计算器程序。

具体实现步骤如下:

1. 实现计算器的界面

在这一步只实现计算器的界面,程序并不带任何业务逻辑。可以使用下面的内容向ChatGPT提问:

使用Python的tkinter实现一个程序,创建一个300 * 400的窗口,窗口分为两部分,上部分是一个文本输入框,其余部分都分给下部分。在下部分实现类似计算器按钮一样的网格布局。网格是4行4列。每一个单元格是一个按钮,从做到右,从上到下,按钮的文本分别是7、8、9、/、4、5、6、*、1、2、3、-、0、.、=、+。给出完整的实现代码和中文注释。

ChatGPT会给出下面的实现代码:

代码语言:javascript
复制
import tkinter as tk
from tkinter import Entry, Button

创建主窗口

root = tk.Tk()

设置窗口大小为 300x400

root.geometry("300x400")

创建一个文本输入框,放在窗口的上部分

entry = Entry(root, font=('Arial', 18))

让输入框占据窗口的上部分,columnspan设置为4,使其横跨4列

entry.grid(row=0, column=0, columnspan=4, sticky='nsew')

定义按钮的文本

buttons = [
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', '=', '+'
]

创建按钮,并使用网格布局放在窗口的下部分

初始化行和列的计数器

row = 1
col = 0

遍历按钮文本,创建对应的按钮

for button in buttons:
# 创建按钮并放置在相应的网格位置
Button(root, text=button, font=('Arial', 18)).grid(row=row, column=col, sticky='nsew')
# 更新列计数器
col += 1
# 当列计数器达到4时,重置为0,并且增加行计数器
if col == 4:
col = 0
row += 1

设置行和列的权重,使它们在窗口大小改变时能够按比例缩放

for i in range(5):
root.grid_rowconfigure(i, weight=1)
if i < 4:
root.grid_columnconfigure(i, weight=1)

启动主循环

root.mainloop()

由于生成的程序没有设置窗口的标题,所以可以在创建窗口代码的后面输入下面的注释,利用GitHub Copilot自动生成设置标题的代码,当然,如果对Tkinter很熟悉,也可以直接编写设置窗口标题的代码。

代码语言:javascript
复制
# 设置窗口标题

按Enter和Tab键,会自动生成下面的代码,其中“计算器”三个字也会自动生成,因为GitHub Copilot是支持上下文的,根据上下文的代码,GitHub Copilot已经推测出了当前的程序是一个计算器应用

代码语言:javascript
复制
root.title("计算器")

现在运行程序,效果如图2所示。

图2 计算器的界面

当窗口改变尺寸后,按钮和文本框也是自适应的。

2. 响应按钮单击动作

由于按钮是根据buttons数组动态添加的,所以需要在添加按钮的for循环中创建按钮代码后面添加如下注释:

代码语言:javascript
复制
# 除了”=“按钮外,点击其他按钮时,都会在输入框中追加按钮的文本,给出实现代码

当注释输入一部分时,GitHub Copilot会猜测注释下面的内容是什么,如果GitHub Copilot恰好猜对了,直接按Tab键生成注释即可。GitHub Copilot是根据上下文猜测的,所以在很多情况下,还是非常准的。 输入这行注释后,不断按Enter和Tab键,GitHub Copilot会生成下面的代码:

代码语言:javascript
复制
if button != '=':   
    # 定义按钮的点击事件
    def click(e):
        # 获取当前按钮的文本
        text = e.widget['text']
        # 在输入框中追加文本
        entry.insert('end', text)
    # 绑定按钮的点击事件
    Button(root, text=button, font=('Arial', 18)).bind('<Button-1>', click)

这段生成的代码总体上是正确的,但有点小问题,由于在for语句的开始部分已经创建了Button对象,并使用grid方法完成了网格布局。但这个Button对象并没有单独保存在变量中,导致了后面的代码无法再次使用这个Button对象,所以需要按如下方式手动改进一下:

代码语言:javascript
复制
for button in buttons:
    # 创建按钮并放置在相应的网格位置
    # 将Button对象单独放在一个变量中,以便在后面可以多次使用该Button对象
    b = Button(root, text=button, font=('Arial', 18))
    b.grid(row=row, column=col, sticky='nsew')
    # 除了”=“按钮外,点击其他按钮时,都会在输入框中追加按钮的文本,给出实现代码
    if button != '=':   
        # 定义按钮的点击事件
        def click(e):
            # 获取当前按钮的文本
            text = e.widget['text']
            # 在输入框中追加文本
            entry.insert('end', text)
        # 绑定按钮的点击事件
        b.bind('<Button-1>', click)

然后在生成代码的后面再次输入如下的注释:

代码语言:javascript
复制
# 点击”=“按钮时,计算输入框中的表达式的值,并将结果显示在输入框中,给出实现代码

不断按Enter和Tab键,GitHub Copilot会生成如下的代码:

代码语言:javascript
复制
else:
    # 定义按钮的点击事件
    def click(e):
        # 获取输入框中的表达式
        text = entry.get()
        # 计算表达式的值
        result = eval(text)
        # 清空输入框
        entry.delete(0, 'end')
        # 在输入框中显示结果
        entry.insert('end', result)
    # 绑定按钮的点击事件
    b.bind('<Button-1>', click)

GitHub Copilot的上下文检测相当给力,可以直接检测出需要加else。现在这一步已经实现完了,运行程序,然后点击数字和符号,并点击“=”按钮完成计算。图3是输入数字和符号的效果,图4是计算表达式后的效果。

图3 输入数字和符号

图4 计算表达式

3. 响应文本输入框的双击事件

双击文本输入框会清空文本输入框的文本,现在找到如下的代码:

代码语言:javascript
复制
entry.grid(row=0, column=0, columnspan=4, sticky='nsew')

在这行代码后面输入如下的注释:

代码语言:javascript
复制
# 双击文本输入框中的文本时,将文本清空,给出实现代码

不断按Enter和Tab键,会生成如下的代码:

代码语言:javascript
复制
def clear(e):   
    entry.delete(0, 'end')
entry.bind('<Double-Button-1>', clear)

现在运行程序,双击文本框,就会清空里面的内容。到现在为止,完美切快速地实现了这个计算器程序,如果对Tkinter、ChatGPT和GitHub Copilot比较熟悉的话,实现这些功能不会超过3分钟。如果要完全手工编写这些代码,就算30分钟,也不能保证做出来,就算做出来,也不能保证布局和业务逻辑一定是正确的。

- EOF -