Use python tkinter to get user input from text area

问渠哪得清如许 白云深处有人家

  • cat gui.py
from __future__ import annotations

import sys
import tkinter as tk


class TkGui:
    @classmethod
    def input(cls, prompt: str = "", label_btn_text: tuple[str, str] | None = None) -> str:
        self = cls(prompt, label_btn_text)
        self.root.mainloop()
        return str(self)

    def __str__(self) -> str:
        return self.text_content

    @property
    def text_content(self) -> str:
        return self._text_content

    def __init__(
        self, title: str | None = None, label_btn_text: tuple[str, str] | None = None
    ) -> None:
        self.root = tk.Tk()
        if title:
            self.root.title(title)
        self.text_area = tk.Text(self.root, height=50, width=180)
        if label_btn_text:
            self.pack_label_button(*label_btn_text)
        self.text_area.pack(padx=10, pady=2)
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
        self._text_content = ""

    def on_closing(self) -> None:
        self._text_content = self.text_area.get("1.0", tk.END)
        self.root.destroy()

    def pack_label_button(self, label_text: str, btn_text: str) -> None:
        frame = tk.Frame(self.root)
        frame.pack(pady=0)
        label = tk.Label(frame, text=label_text)
        label.pack(side=tk.LEFT, padx=5)
        btn = tk.Button(frame, text=btn_text, command=self.on_closing)
        btn.pack(side=tk.LEFT, padx=5)


def main() -> None:
    if not sys.argv[1:]:
        text = TkGui.input()
    elif not sys.argv[2:]:
        text = TkGui.input(sys.argv[1])
    elif not sys.argv[3:]:
        text = TkGui.input(label_btn_text=(sys.argv[1], sys.argv[2]))
    else:
        text = TkGui.input(sys.argv[1], label_btn_text=(sys.argv[2], sys.argv[3]))
    print("text:", text)


if __name__ == "__main__":
    main()
  • python3.14 gui.py 这是标题 提示框文本 确认
    image

代码丢给DeepSeek,叫她优化一下,结果变成这样了:

from __future__ import annotations

import sys
import tkinter as tk


class NotepadGui(tk.Tk):
    """一个简单的文本输入GUI应用,支持自定义标题和按钮标签"""

    def __init__(
        self, title: str | None = None, label_btn_text: tuple[str, str] | None = None
    ) -> None:
        """初始化GUI

        Args:
            title: 窗口标题
            label_btn_text: 包含标签文本和按钮文本的元组
        """
        super().__init__()
        self._text_content = ""
        self._setup_ui(title, label_btn_text)

    def _setup_ui(self, title: str | None, label_btn_text: tuple[str, str] | None) -> None:
        """设置用户界面"""
        if title:
            self.title(title)

        self.text_area = tk.Text(self, height=30, width=100, wrap=tk.WORD)
        self.text_area.pack(padx=10, pady=10, expand=True, fill=tk.BOTH)

        if label_btn_text:
            self._add_label_button(*label_btn_text)

        self.protocol("WM_DELETE_WINDOW", self._on_closing)
        self.bind("<Escape>", lambda e: self._on_closing())

    def _add_label_button(self, label_text: str, btn_text: str) -> None:
        """添加标签和按钮"""
        control_frame = tk.Frame(self)
        control_frame.pack(pady=(0, 10))

        tk.Label(control_frame, text=label_text).pack(side=tk.LEFT, padx=5)
        tk.Button(control_frame, text=btn_text, command=self._on_closing, padx=10).pack(
            side=tk.LEFT, padx=5
        )

    def _on_closing(self) -> None:
        """窗口关闭时的处理"""
        self._text_content = self.text_area.get("1.0", tk.END).strip()
        self.destroy()

    @classmethod
    def input(cls, prompt: str = "", label_btn_text: tuple[str, str] | None = None) -> str:
        """类方法提供简洁的输入接口

        Args:
            prompt: 窗口标题
            label_btn_text: 标签和按钮文本

        Returns:
            用户输入的文本内容
        """
        instance = cls(prompt, label_btn_text)
        instance.mainloop()
        return str(instance)

    def __str__(self) -> str:
        """返回文本内容"""
        return self.text_content

    @property
    def text_content(self) -> str:
        """文本内容属性"""
        return self._text_content


def parse_args(args: list[str]) -> tuple[str, tuple[str, str] | None]:
    """解析命令行参数"""
    if not args:
        return "", None
    if len(args) == 1:
        return args[0], None
    if len(args) == 2:
        return "", (args[0], args[1])
    return args[0], (args[1], args[2])


def main() -> None:
    """主函数"""
    title, label_btn_text = parse_args(sys.argv[1:])
    text = NotepadGui.input(title, label_btn_text)
    print("用户输入:", text)


if __name__ == "__main__":
    main()

优化结果还行吧,至少加了很多注释,有时候最烦的就是写注释。。。

审视了一下,把代码重构成Python3.10以上专用的:

import tkinter as tk


class NotepadGui(tk.Tk):
    """一个简单的文本输入GUI应用,支持自定义标题和按钮标签"""

    @classmethod
    def input(
        cls, prompt: str = "", label_btn_text: tuple[str, str] | None = None
    ) -> str:
        """类方法提供简洁的输入接口

        Args:
            prompt: 窗口标题
            label_btn_text: 标签和按钮文本

        Returns:
            用户输入的文本内容
        """
        instance = cls(prompt, label_btn_text)
        instance.mainloop()
        return str(instance)

    def __str__(self) -> str:
        """返回文本框内容"""
        return self.text_content

    @property
    def text_content(self) -> str:
        # Use property to make it readonly
        return self._text_content

    def __init__(
        self, title: str | None = None, label_btn_text: tuple[str, str] | None = None
    ) -> None:
        """初始化GUI

        Args:
            title: 窗口标题
            label_btn_text: 包含标签文本和按钮文本的元组
        """
        super().__init__()
        self._text_content = ""
        self._setup_ui(title, label_btn_text)

    def _setup_ui(
        self, title: str | None, label_btn_text: tuple[str, str] | None
    ) -> None:
        """设置用户界面"""
        if title:
            self.title(title)

        self.text_area = tk.Text(self, height=30, width=100, wrap=tk.WORD)
        if label_btn_text:
            self._add_label_button(*label_btn_text)
        self.text_area.pack(padx=10, pady=10, expand=True, fill=tk.BOTH)

    def _add_label_button(self, label_text: str, btn_text: str) -> None:
        """添加标签和按钮"""
        frame = tk.Frame(self)
        frame.pack(pady=(0, 10))

        tk.Label(frame, text=label_text).pack(side=tk.LEFT, padx=5)
        tk.Button(frame, text=btn_text, command=self.destroy, padx=10).pack(
            side=tk.LEFT, padx=5
        )

    def destroy(self) -> None:
        self._text_content = self.text_area.get("1.0", tk.END).strip()
        return super().destroy()


def parse_args(args: list[str]) -> tuple[str, tuple[str, str] | None]:
    """解析命令行参数"""
    match len(args):
        case 0:
            return "", None
        case 1:
            return args[0], None
        case 2:
            return "", (args[0], args[1])
        case _:
            return args[0], (args[1], args[2])


def main() -> None:
    import sys

    title, label_btn_text = parse_args(sys.argv[1:])
    text = NotepadGui.input(title, label_btn_text)
    print("用户输入:", text)


if __name__ == "__main__":
    main()
posted @ 2025-08-08 23:17  waketzheng  阅读(13)  评论(0)    收藏  举报