IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python-tkinter实现Text文本框显示行数 -> 正文阅读

[Python知识库]Python-tkinter实现Text文本框显示行数

最近在使用tkinter制作一个文字编辑器,然后花了好久时间终于研究了一个像pycharm那样显示文字行数的效果,如图所示:
请添加图片描述
直接放源代码,然后再详细说明

from tkinter import *
from tkinter import scrolledtext
from threading import Thread, RLock


class Main(Tk):
    def __init__(self):
        super().__init__()
        self.thread_lock = RLock()
        self.txt = ""
        self._main()

    def _main(self):
        self.resizable(True, True)
        self.geometry("800x600")
        self.edit_frame = Canvas(self, height=600, width=800,
                                 bg="white", highlightthickness=0)
        self.edit_frame.pack()
        self.line_text = Text(self.edit_frame, width=7, height=600, spacing3=5,
                              bg="#DCDCDC", bd=0, font=("等线等线 (Light)", 14), takefocus=0, state="disabled",
                              cursor="arrow")
        self.line_text.pack(side="left", expand="no")
        self.update()
        self.edit_text = scrolledtext.ScrolledText(self.edit_frame, height=1, wrap="none", spacing3=5,
                                                   width=self.winfo_width() - self.line_text.winfo_width(), bg="white",
                                                   bd=0, font=("等线等线 (Light)", 14), undo=True, insertwidth=1)
        self.edit_text.vbar.configure(command=self.scroll)
        self.edit_text.pack(side="left", fill="both")
        self.line_text.bind("<MouseWheel>", self.wheel)
        self.edit_text.bind("<MouseWheel>", self.wheel)
        self.edit_text.bind("<Control-v>", lambda e: self.get_txt_thread())
        self.edit_text.bind("<Control-V>", lambda e: self.get_txt_thread())
        self.edit_text.bind("<Key>", lambda e: self.get_txt_thread())
        self.show_line()

    def wheel(self, event):
        self.line_text.yview_scroll(int(-1 * (event.delta / 120)), "units")
        self.edit_text.yview_scroll(int(-1 * (event.delta / 120)), "units")
        return "break"

    def scroll(self, *xy):
        self.line_text.yview(*xy)
        self.edit_text.yview(*xy)

    def get_txt_thread(self):
        Thread(target=self.get_txt).start()

    def get_txt(self):
        self.thread_lock.acquire()
        if self.txt != self.edit_text.get("1.0", "end")[:-1]:
            self.txt = self.edit_text.get("1.0", "end")[:-1]
            self.show_line()
        else:
            self.thread_lock.release()

    def show_line(self):
        sb_pos = self.edit_text.vbar.get()
        self.line_text.configure(state="normal")
        self.line_text.delete("1.0", "end")
        txt_arr = self.txt.split("\n")
        if len(txt_arr) == 1:
            self.line_text.insert("1.1", " 1")
        else:
            for i in range(1, len(txt_arr) + 1):
                self.line_text.insert("end", " " + str(i))
                if i != len(txt_arr):
                    self.line_text.insert("end", "\n")
        if len(sb_pos) == 4:
            self.line_text.yview_moveto(0.0)
        elif len(sb_pos) == 2:
            self.line_text.yview_moveto(sb_pos[0])
            self.edit_text.yview_moveto(sb_pos[0])
        self.line_text.configure(state="disabled")
        try:
            self.thread_lock.release()
        except RuntimeError:
            pass


if __name__ == "__main__":
    run = Main()
    run.mainloop()

先讲下主体思路(有点儿硬核):
首先在_main()函数里创建了两个Text,一个用于显示行数(line_text),一个用于打字(edit_text)。
每在edit_text中每输入字符,就获取文本框里的内容(因为get()获取Text内容得到的字符串末尾自动回加上一个\n,所以用[:-1]截取到倒二个字符),然后用字符串split函数将"\n"回车分隔开,这时候得到列表长度就是有多少行。
然后用循环往line_text添加数字以显示行数。

细节方面(实现的关键!!):
1.我将line_text的cursor参数改为"arrow",为了让鼠标移上去是正常状态而不是输入状态。将takefocus设为0,防止line_text获得焦点。将state设为"disabled",在往里添加数字时再设为"normal",防止在line_text中误输入。

2.可以发现我用edit.text绑定了一个Key的键盘事件,执行的函数为get_txt_thread(),开启self.get_txt函数的线程,而不是将执行直接设置为self.get_txt(),那是因为我发现输入在执行事件后,意思就是当一个键按下时,先执行了键盘绑定的事件,再向文本框里输入东西,假设我先按下了1再按下2,文本框里是显示出了12,但实际获取的Text里的东西只有1,因此我就用多线程的方法硬核地让执行事件和输入同步执行,这样就能在每次输入时正确得到文本框里的内容了

3.光加一个多线程还不够,在执行线程里的代码前要加上线程锁,执行结束后再解开,这样让线程按顺序执行是为了防止用输入法一次性输入多个字符时造成line_text公用而显示错误

4.要实现滚轮同时控制line_text和edit_text,我运用了这篇文章提供的思路: tkinter实现一个滚动条同时控制两个部件

5.将edit_text也绑定键盘按下ctrl+v,这样在粘贴文字的时候也会触发一次show_line

那么这篇文章就到介绍这里,觉得不错的就给个一键三连吧!

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:38:10  更:2021-09-22 14:39:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 6:06:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计