tkinter的实战-小工具

一、tkinter基础语法

tkinter是一个Python中的GUI库,用于创建用户界面。以下是部分常用的tkinter语法:

  1. 导入模块:import tkinter

  2. 创建主窗口:root = tkinter.Tk()

  3. 设置主窗口标题:root.title("窗口标题")

  4. 设置主窗口大小:root.geometry("宽x高")

  5. 添加标签:tkinter.Label(父容器, text="标签文本")

  6. 添加按钮:tkinter.Button(父容器, text="按钮文本", command=按钮响应函数)

  7. 绑定事件:组件.bind(事件类型, 响应函数)

  8. 显示窗口及运行事件循环:root.mainloop()

注:其中父容器可以是主窗口或其他容器组件。响应函数可以是定义好的函数名,也可以是lambda函数。

以上只是一部分常用的tkinter语法,更多内容还需参考官方文档或教程。

二、入门教程

写一个类,其可以输入一个名称,然后点击搜索,下方有一些文件提示框用于展示文件列表,在最低位置,有一个一键处理按钮

以下是一个可以实现上述功能的类的简单实现:

import tkinter as tk
import os

class FileSearcher:
    def __init__(self, master):
        self.master = master

        # 在窗口顶部添加一个输入框和一个搜索按钮
        self.search_entry = tk.Entry(master, width=40)
        self.search_button = tk.Button(master, text='搜索', command=self.search_files)

        # 在窗口中间添加一个滚动条,用于文件列表展示
        self.file_scrollbar = tk.Scrollbar(master)
        self.file_scrollbar.pack(side='right', fill='y')
        self.file_listbox = tk.Listbox(master, width=60, yscrollcommand=self.file_scrollbar.set)
        self.file_scrollbar.config(command=self.file_listbox.yview)

        # 在窗口底部添加一个处理按钮
        self.process_button = tk.Button(master, text='一键处理', command=self.process_files)

        # 设置窗口布局
        self.search_entry.pack(side='left')
        self.search_button.pack(side='left')
        self.file_listbox.pack(side='top', padx=10, pady=10)
        self.process_button.pack(side='bottom', pady=10)

    def search_files(self):
        # 获取搜索关键字
        search_text = self.search_entry.get()

        # 清空文件列表
        self.file_listbox.delete(0, 'end')

        # 搜索指定目录下的文件,并将文件名添加到列表框中
        for filename in os.listdir('.'):
            if search_text in filename:
                self.file_listbox.insert('end', filename)

    def process_files(self):
        # 在这里写一键处理文件的代码
        pass

然后可以在程序中实例化这个类,把窗口作为参数传入:

if __name__ == '__main__':
    root = tk.Tk()
    app = FileSearcher(root)
    root.mainloop()

这样就可以运行程序,看到一个带有搜索框、文件列表框和一键处理按钮的界面了。

三、持续优化

为了美化界面,我们可以使用 ttk 模块中的一些部件,它们提供了更好看的外观和更好的交互效果。

以下是一个美化后的 FileSearcher 类:

import tkinter as tk
from tkinter import ttk
import os

class FileSearcher:
    def __init__(self, master):
        self.master = master

        # 在窗口顶部添加一个输入框和一个搜索按钮
        self.search_frame = ttk.Frame(master)
        self.search_frame.pack(fill='x', padx=10, pady=(10, 0))
        self.search_entry = ttk.Entry(self.search_frame, width=40)
        self.search_button = ttk.Button(self.search_frame, text='搜索', command=self.search_files)
        self.search_entry.pack(side='left', padx=(0, 10))
        self.search_button.pack(side='left')

        # 在窗口中间添加一个滚动条,用于文件列表展示
        self.file_frame = ttk.Frame(master)
        self.file_frame.pack(fill='both', padx=10, pady=10, expand=True)
        self.file_scrollbar = ttk.Scrollbar(self.file_frame)
        self.file_scrollbar.pack(side='right', fill='y')
        self.file_listbox = tk.Listbox(self.file_frame, width=60, yscrollcommand=self.file_scrollbar.set)
        self.file_listbox.pack(side='left', fill='both', expand=True)
        self.file_scrollbar.config(command=self.file_listbox.yview)

        # 在窗口底部添加一个处理按钮
        self.process_button = ttk.Button(master, text='一键处理', command=self.process_files)
        self.process_button.pack(side='bottom', pady=10)

    def search_files(self):
        # 获取搜索关键字
        search_text = self.search_entry.get()

        # 清空文件列表
        self.file_listbox.delete(0, 'end')

        # 搜索指定目录下的文件,并将文件名添加到列表框中
        for filename in os.listdir('.'):
            if search_text in filename:
                self.file_listbox.insert('end', filename)

    def process_files(self):
        # 在这里写一键处理文件的代码
        pass

我们使用了 ttk 模块中的 FrameEntryButtonScrollbar 部件来代替了原来的部件,从而实现了美化的效果。

运行程序后,界面应该更漂亮了。

四、功能补充与完善

4.1 根据执行结果显示的状态栏,可以显示完成 / 搜索失败

为了添加一个状态栏,我们可以使用 ttk.Label 部件。该部件可以用于在窗口中添加文本标签,我们可以使用它来展示处理的状态。

以下是一个添加了状态栏的 FileSearcher 类:

import tkinter as tk
from tkinter import ttk
import os

class FileSearcher:
    def __init__(self, master):
        self.master = master

        # 在窗口顶部添加一个输入框和一个搜索按钮
        self.search_frame = ttk.Frame(master)
        self.search_frame.pack(fill='x', padx=10, pady=(10, 0))
        self.search_entry = ttk.Entry(self.search_frame, width=40)
        self.search_button = ttk.Button(self.search_frame, text='搜索', command=self.search_files)
        self.search_entry.pack(side='left', padx=(0, 10))
        self.search_button.pack(side='left')

        # 在窗口中间添加一个滚动条,用于文件列表展示
        self.file_frame = ttk.Frame(master)
        self.file_frame.pack(fill='both', padx=10, pady=10, expand=True)
        self.file_scrollbar = ttk.Scrollbar(self.file_frame)
        self.file_scrollbar.pack(side='right', fill='y')
        self.file_listbox = tk.Listbox(self.file_frame, width=60, yscrollcommand=self.file_scrollbar.set)
        self.file_listbox.pack(side='left', fill='both', expand=True)
        self.file_scrollbar.config(command=self.file_listbox.yview)

        # 在窗口底部添加一个处理按钮和一个状态栏
        self.status_label = ttk.Label(master, text='未开始搜索')
        self.status_label.pack(side='bottom', pady=(0, 10))
        self.process_button = ttk.Button(master, text='一键处理', command=self.process_files)
        self.process_button.pack(side='bottom', pady=10)

    def search_files(self):
        # 获取搜索关键字
        search_text = self.search_entry.get()

        # 清空文件列表
        self.file_listbox.delete(0, 'end')

        # 搜索指定目录下的文件,并将文件名添加到列表框中
        for filename in os.listdir('.'):
            if search_text in filename:
                self.file_listbox.insert('end', filename)

        # 更新状态栏的文本
        if self.file_listbox.size() > 0:
            self.status_label.config(text='搜索完成')
        else:
            self.status_label.config(text='搜索失败')

    def process_files(self):
        # 在这里写一键处理文件的代码
        pass

我们添加了一个名为 status_label 的新标签部件,并在搜索和处理函数中更新了它的文本。在搜索完成时,我们设置 status_label 的文本为“搜索完成”,否则设置为“搜索失败”。

运行程序后,应该能看到新的状态栏。

4.2 tkinter中的文件列表如何实现点击打开其文件

要在tkinter中实现文件列表的点击打开文件功能,可以为 Listbox 部件绑定双击事件,然后在事件处理程序中打开所选文件。

以下是一个示例程序,展示如何实现点击文件列表中的文件打开该文件:

import tkinter as tk
from tkinter import ttk
import os

class FileOpener:
    def __init__(self, master):
        self.master = master

        # 在窗口中间添加一个滚动条和文件列表框
        self.file_frame = ttk.Frame(master)
        self.file_frame.pack(fill='both', padx=10, pady=10, expand=True)
        self.file_scrollbar = ttk.Scrollbar(self.file_frame)
        self.file_scrollbar.pack(side='right', fill='y')
        self.file_listbox = tk.Listbox(self.file_frame, width=60, yscrollcommand=self.file_scrollbar.set)
        self.file_listbox.pack(side='left', fill='both', expand=True)
        self.file_scrollbar.config(command=self.file_listbox.yview)

        # 为文件列表框绑定双击事件
        self.file_listbox.bind('<Double-Button-1>', self.open_file)

        # 填充文件列表框
        self.fill_file_list()

    def fill_file_list(self):
        # 获取当前目录下的所有文件名
        files = os.listdir('.')

        # 将文件名添加到文件列表框中
        for filename in files:
            self.file_listbox.insert('end', filename)

    def open_file(self, event):
        # 获取双击的文件名
        selected_file = self.file_listbox.get(self.file_listbox.curselection())

        # 打开文件
        os.startfile(selected_file)

我们创建了一个名为 FileOpener 的类,其中包含一个 Listbox 部件用于展示文件列表,并在该部件上绑定了双击事件。当用户双击文件列表中的文件时,open_file 方法将被调用,并打开所选文件。

open_file 方法中,我们使用 os.startfile() 函数打开了所选文件。这里使用 os.startfile() 是因为它是一个跨平台的函数,在 Windows、Linux 和 macOS 上都能正常工作。

要使用示例程序,只需创建一个 Tk 对象,然后创建 FileOpener 对象即可。运行程序后,您应该能够在窗口中看到当前目录下的所有文件,并且可以双击其中一个文件来打开它。

4.2.2 需要增加识别其是否已打开此文件,已打开的不需要重复打开

要在tkinter中实现打开文件时检查文件是否已打开,可以借助 platform 模块获取当前运行的操作系统。在Windows系统上,可以使用 ctypes 模块来枚举所有正在运行的句柄,并检查文件是否已在其中打开,而在Linux和macOS上则需要使用其他方法。

以下是一个示例程序,展示如何在Windows系统上使用 ctypes 模块来检查文件是否已打开:

import tkinter as tk
from tkinter import ttk
import os
import platform
import ctypes
import ctypes.wintypes


class FileOpener:
    def __init__(self, master):
        self.master = master

        # 在窗口中间添加一个滚动条和文件列表框
        self.file_frame = ttk.Frame(master)
        self.file_frame.pack(fill='both', padx=10, pady=10, expand=True)

        self.file_scrollbar = ttk.Scrollbar(self.file_frame)
        self.file_scrollbar.pack(side='right', fill='y')

        self.file_listbox = tk.Listbox(self.file_frame, width=60, yscrollcommand=self.file_scrollbar.set)
        self.file_listbox.pack(side='left', fill='both', expand=True)

        # 为文件列表框绑定双击事件
        self.file_listbox.bind('<Double-Button-1>', self.open_file)

        # 填充文件列表框
        self.fill_file_list()

    def fill_file_list(self):
        # 获取当前目录下的所有文件名
        files = os.listdir('.')

        # 将文件名添加到文件列表框中
        for filename in files:
            self.file_listbox.insert('end', filename)

    def open_file(self, event):
        # 获取双击的文件名
        selected_file = self.file_listbox.get(self.file_listbox.curselection())

        # 检查文件是否已打开
        if self.is_file_open(selected_file):
            print('文件已打开')
        else:
            # 打开文件
            os.startfile(selected_file)

    def is_file_open(self, filename):
        if platform.system() == 'Windows':
            # Windows系统使用ctypes来枚举所有打开的句柄
            kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
            kernel32.CreateToolhelp32Snapshot.argtypes = [ctypes.wintypes.DWORD, ctypes.wintypes.DWORD]
            kernel32.CreateToolhelp32Snapshot.restype = ctypes.wintypes.HANDLE
            kernel32.Process32FirstW.argtypes = [ctypes.wintypes.HANDLE, ctypes.POINTER(ctypes.wintypes.PROCESSENTRY32W)]
            kernel32.Process32FirstW.restype = ctypes.wintypes.BOOL
            kernel32.Process32NextW.argtypes = [ctypes.wintypes.HANDLE, ctypes.POINTER(ctypes.wintypes.PROCESSENTRY32W)]
            kernel32.Process32NextW.restype = ctypes.wintypes.BOOL
            kernel32.CloseHandle.argtypes = [ctypes.wintypes.HANDLE]
            kernel32.CloseHandle.restype = ctypes.wintypes.BOOL

            handle = kernel32.CreateToolhelp32Snapshot(ctypes.c_ulong(0x2), ctypes.c_ulong(0))
            if handle == ctypes.c_ulong(-1).value:
                error = kernel32.GetLastError()
                raise Exception(f'CreateToolhelp32Snapshot failed: {error}')

            try:
                pe = ctypes.wintypes.PROCESSENTRY32W()
                pe.dwSize = ctypes.sizeof(pe)

                if kernel32.Process32FirstW(handle, ctypes.byref(pe)):
                    while True:
                        if filename.lower() in pe.szExeFile.decode('utf-8').lower():
                            return True

                        if not kernel32.Process32NextW(handle, ctypes.byref(pe)):
                            break
                else:
                    error = kernel32.GetLastError()
                    if error != 0x18:  # ERROR_NO_MORE_FILES
                        raise Exception(f'Process32First failed: {error}')
            finally:
                kernel32.CloseHandle(handle)

        return False

我们在 FileOpener 类中添加了一个名为 is_file_open 的方法,该方法使用 ctypes 模块在Windows系统上枚举所有打开的句柄,并检查文件是否在其中打开。如果文件已经打开,则返回True,否则返回False。

open_file 方法中,我们在打开文件之前首先调用 is_file_open 方法来检查文件是否已打开。如果文件已打开,我们输出一条消息表示文件已经打开,否则我们使用 os.startfile 打开文件。

请注意,此方法只适用于Windows系统,并且需要管理员权限才能枚举所有打开的句柄。在Linux和macOS上,可以使用其他方法来检查文件是否已打开。

4.3 一键关闭功能及退出时自动关闭所有文档功能

如果您想在单击Qt窗口的关闭按钮时关闭所有已打开的文档,可以通过以下方式实现:

1.创建一个应用程序类,继承QApplication, 在__init__方法中创建一个列表self.processes,用于跟踪所有打开的进程。并且在exec_()方法中设置关闭事件处理程序self.closeEvent

class MyApp(QApplication):
 
    def __init__(self, argv):
        super().__init__(argv)
        self.processes = []
 
    def closeEvent(self, event):
        for process in self.processes:
            process.kill()

2.创建一个主窗口类,继承QMainWindow。在__init__方法中创建一个列表self.file_list,用于显示所有可用的 PDF 文件,并在该列表中添加itemDoubleClicked信号的处理程序self.open_pdf

class MainWindow(QMainWindow):
 
    def __init__(self):
        super().__init__()
        self.file_list = QListWidget(self)
        self.setCentralWidget(self.file_list)
        self.file_list.itemDoubleClicked.connect(self.open_pdf)

3.在self.open_pdf方法中,使用subprocess.Popen打开所选文件,并将返回的进程对象添加到self.processes列表中。

    def open_pdf(self, item):
        file = item.text()
        process = subprocess.Popen(["open", "path/to/pdf/files/" + file])
        self.app.processes.append(process)

4.在 main 方法中创建QApplication对象和MainWindow对象,并设置应用程序图标、窗口标题和窗口大小。最后显示主窗口。

if __name__ == '__main__':
    app = MyApp(sys.argv)
    main_window = MainWindow()
    main_window.setWindowIcon(QIcon('path/to/icon.png'))
    main_window.setWindowTitle('My PDF Viewer')
    main_window.setGeometry(100, 100, 800, 600)
    main_window.show()
    sys.exit(app.exec_())

当用户单击主窗口的关闭按钮时,closeEvent方法会迭代self.processes列表并关闭所有打开的进程。这将在后台关闭所有 PDF 文件,同时关闭主窗口。

ok! 今天内容tkinter的实例展示就运行完毕!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值