【问题标题】:How can I make a Tkinter GUI that auto fills certain entries如何制作自动填充某些条目的 Tkinter GUI
【发布时间】:2020-06-18 16:06:47
【问题描述】:

我正在尝试使用 Tkinter 制作一个允许您输入 URL 或 ID 的 GUI。

示例网址:https://www.fanfiction.net/s/10030860/1/The-Final-Battle 示例 ID:10030860

如您所见,ID 嵌入在 URL 中。我想要两个条目,一个用于输入 URL,另一个用于输入 ID。如果用户填写 URL 框,则会自动生成 ID。 (如果我将示例 URL 放在 URL 输入框中,我希望自动生成 ID 框中的示例 ID,反之亦然)如果用户填写 ID 框,则自动生成 URL。

更多例子:(括号是假装输入框)

URL: [https://www.fanfiction.net/s/10030860/1/The-Final-Battle] <-- If I fill this in
ID:  [10030860] <-- Python fills this in for me
URL: [https://www.fanfiction.net/s/10030860/1/The-Final-Battle] <-- Python fills this in for me
ID:  [10030860] <-- If I fill this in

到目前为止,这是我的代码:

import tkinter as tk
from tkinter import ttk

# Define a function to autofill in the URL and ID entries
def autofill_id_url():
    fanfic_url.set("https://www.fanfiction.net/s/" + fanfic_id.get() + "/1/")
    root.after(100, autofill_id_url)

# Root window
root = tk.Tk()

# Define the labeled frame where we input stuff
input_frame = tk.LabelFrame(master=root, text="Input")
input_frame.grid(row=0, column=0, padx=1, pady=1, rowspan=2, sticky=tk.NS)

# Label for entering URL
ttk.Label(master=input_frame, text="URL:").grid(row=0, column=0, padx=1, pady=1)
# Entry field for URL
fanfic_url = tk.StringVar()
url_entry = ttk.Entry(master=input_frame, textvariable=fanfic_url)
url_entry.grid(row=0, column=1, padx=1, pady=1)

# Label for entering ID
ttk.Label(master=input_frame, text="ID:").grid(row=1, column=0, padx=1, pady=1)
# Entry field for ID
fanfic_id = tk.StringVar()
id_entry = ttk.Entry(master=input_frame, textvariable=fanfic_id)
id_entry.grid(row=1, column=1, padx=1, pady=1)

# Start callback functions
autofill_id_url()

# Start GUI event loop
root.mainloop()

我有填写ID时的部分,URL是自动生成的。但是我不知道如何做到这一点,当您填写 URL 框时,您会得到为您填写的 ID 框。

提前致谢。

【问题讨论】:

    标签: python user-interface tkinter user-input


    【解决方案1】:

    您可以使用StringVartrace_variable 方法进行自动填充。 下面的代码会这样做,但这只是入门的基本代码,因为它需要更多的工作才能完美地实现自动填充。

    after_ids = {}
    
    def get_url(id_):
        """returns url from id."""
        url = 'https://www.fanfiction.net/s/{}/1/The-Final-Battle'
        return url.format(id_)
    
    def get_id(url):
        """returns id from the url."""
        l = url.split('/')
        return l[4] if len(l) > 4 else ''
    
    def autofill_entry(mode, dalay=1000):
        """Auto-fills Url/ID."""
        for v in after_ids.values():
            root.after_cancel(v)
        if mode == 'url':  
            id_ = get_id(fanfic_url.get())
            after_ids[0] = root.after(dalay, lambda: fanfic_id.set(id_))
        elif mode == 'id':
            url = get_url(fanfic_id.get())
            after_ids[1] = root.after(dalay, lambda: fanfic_url.set(url))
    

    现在将函数 autofill_entry 分配给入口小部件 StringVars。

    fanfic_url.trace_variable('w', lambda *a: autofill_entry('url'))
    fanfic_id.trace_variable('w', lambda *a: autofill_entry('id'))
    

    另外,我建议你使用from urllib.parse import urlparse, parse_qs 加入 URL 并从 URL 中获取 id。

    【讨论】:

    • 虽然可以,但我不建议使用代码[root.after_cancel(v) for v in after_ids.values()]。不必为了减少代码行数而增加内存使用量。
    • 是的,它们都可以工作。您的代码创建了一个列表但没有将其分配给变量。当python评估此代码时,它会浪费不必要的内存开销。(不是一个大问题,但我认为这不是一个好习惯)。
    • @Unsigned_Arduino:默认情况下,变量跟踪方法将 3 个参数传递给回调函数,因此 *a 参数将采用 trace_variable 传递的所有这 3 个参数。您可以阅读此 page 并向下滚动到代码以了解这 3 个参数。
    • 您可以阅读 answer 上的 lambda 函数作为 Tkinter 中的命令以获得更好的理解。
    • @Unsigned_Arduino: 是的,但由于我们没有使用这些参数,所以我决定为两条轨迹创建一个自动填充函数,并使用 lambda 定义参数的差异mode.
    【解决方案2】:

    最好在输入框中按下 Enter 键时自动填充,而不是使用.after()

    baseurl = 'https://www.fanfiction.net/s/'
    
    def autofill_url_id(_):
        try:
            # extract the id from the url
            url = fanfic_url.get().strip()
            if url.startswith(baseurl):
                id = url.split('/')[4]
                fanfic_id.set(id)
        except IndexError:
            print('failed to extract id from the url')
    
    def autofill_id_url(_):
        id = fanfic_id.get().strip()
        if id:
            fanfic_url.set(baseurl+id+'/1/')
    ...
    # Start callback functions
    #autofill_id_url()
    url_entry.bind('<Return>', autofill_url_id)
    id_entry.bind('<Return>', autofill_id_url)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-12
      • 2020-09-14
      • 1970-01-01
      • 2020-09-28
      • 2023-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多