002.02 Tkinter 图形接口之文本范例

主题: 002.02 Tkinter图形接口之文本范例

建檔日期: 2019/08/26
更新日期: None
语言: Python 3.7.4, tkinter 8.6
系统: Win10 Ver. 10.0.17763 繁体中文版(TW)

002.02 Tkinter图形接口之文本范例

范例以tkinter建立程序, 供用户建立文本档案, 在过程中记录下用户输入中文字的关连性, 随后提供中文输入协助的快捷键, 对输入比较的人可以起到有效的协助. 主要用到的部件有Tk(), Frame(), Button(), Label()以及Text(), 还有按键及鼠标事件处理; 另外还有档案对话filedialog及讯息框messagebox的使用.

程序接口

002.02 Tkinter图形接口之文本范例

'''
使用Tkinter的Text部件, 建立一个简单的文本编辑器, 主要的功能为:

[1] 系统会按用户输的中文字, 记录下用户输入的第二个中文字的使用情形, 下次
    再输入这个字, 会提供前十二个最常使用的下一个字, 供用户以F1~F12按键直接输入.
[2] 用户可以读入以前的文本档案, 直接学习, 建立自己的字典
[3] 这个辅助输入的字典, 是专为个人使用, 不是一般通用的字典, 一般来说, 个人常用
    的词汇大都在几百字, 对输入较慢的人, 可以起到很大的作用.

'''
from tkinter.filedialog import *
from tkinter import *
from tkinter import messagebox

def enter(event):   # 鼠标进入对象, 背景改为黑色
    event.widget.config(bg='black')

def leave(event):   # 鼠标离间对象, 背景改为原背景色
    event.widget.config(bg=gnd)

def open_new_file():
    '''
    开启文本文件, 格式以utf-8, utf-16, GB18030来读取
    '''
    # 开启档案对话框
    filename = filedialog.askopenfilename(title = "选择档案",
        filetypes = (("文本文件","*.txt"),("所有档案","*.*")))
    new_text = None
    # 开启档案, 试以utf-8, utf-16及GB18030来开启, 无法开启则颢示错误
    if filename != "":
        print(filename)
        try:
            print('utf-8')
            new_f = open(filename, 'rt', encoding = 'utf-8')
            new_text = new_f.read()
        except UnicodeDecodeError as e:
            try:
                print('utf-8 Failed')
                new_f = open(filename, 'rt', encoding = 'utf-16')
                new_text = new_f.read()
            except UnicodeDecodeError as e:
                try:
                    print('utf-16 Failed')
                    new_f = open(filename, 'rt', encoding = 'GB18030')
                    new_text = new_f.read()
                except UnicodeDecodeError as e:
                    print('GB18030 Failed')
                    pass
        # 档案读入, 显示在TEXT部件中
        if new_text != None:
            print(new_f)
            print(new_text)
            main_widget.t1.delete('1.0', END)
            main_widget.t1.insert(END, new_text)
            main_widget.t1.edit_modified(False)
        else:
            messagebox.showinfo(title='档案开启错误', message='文本文件格式无法读取或档案有问题')

def save_new_file():
    # 开启存档对话框
    filename = filedialog.asksaveasfilename(title = "储存档案",
        filetypes = (("文本文件","*.txt"),("所有档案","*.*")))
    if filename != "":
        if filename[-4:].lower() != '.txt':
            filename = filename + '.txt'
        new_f = open(filename, 'wt', encoding = decoder)
        new_f.write(main_widget.t1.get('1.0',END))
        new_f.close()

def end_job():
    # 字典存盘, 下次可再使用
    if dictionary != {}:
        datafile = open(dictionary_file, 'wt', encoding=decoder)
        datafile.write(str(dictionary))
        datafile.close()
    root.destroy()
    exit()

def learn_dictionary():
    # 读入的档案内容, 分析内容, 加入字典中
    txt = main_widget.t1.get('1.0',END)
    for i in range(len(txt))[1:]:
        pre_char = txt[i-1]
        new_char = txt[i]
        add_dictionary(pre_char, new_char)

def cmd(i):
    # 按钮处理程序
    if i == 0:      # 开启档案
        if main_widget.t1.edit_modified():
            answer = messagebox.askquestion ('开启档案',
                '内容已修改, 是否舍弃, 另开新档 ?',icon = 'warning')
            if answer == 'yes':
                open_new_file()
        else:
            open_new_file()

    elif i == 1:    # 存入档案
        save_new_file()

    elif i == 2:    # 学习本文中的内容
        learn_dictionary()

    elif i == 3:    # 结束离开
        if main_widget.t1.edit_modified():
            answer = messagebox.askquestion ('离开编辑',
                '内容已修改, 是否舍弃离开 ?',icon = 'warning')
            if answer == 'yes':
                end_job()
        else:
            end_job()

def new_button(f, string, column, row):
    # 建立功能按钮
    obj = Button(f, text=string, font=font, width=len(string)*2, height=1, bg=gnd,
            fg='white', bd=0, activebackground=gnd, command = lambda i = column: cmd(i))
    obj.bind('<Enter>', enter)
    obj.bind('<Leave>', leave)
    obj.pack(side=LEFT)
    return obj

def new_label(f, string, column, row):
    # 建立F1~F12的标签
    obj = Label(f, text=string, font=font, width=len(string), height=1, bg=gnd,
            fg=l_gnd, bd=0, activebackground=gnd)
    obj.pack(side=LEFT)
    return obj

def read_dictionary():
    # 读入已有的字典, 格式为{}空字典, {'字':{'字':次数, ....}, ....}
    dic_f = open(dictionary_file, 'rt', encoding = decoder)
    a = dic_f.read()
    dictionary = eval(a)
    dic_f.close()
    return dictionary

def write_dictionary():
    # 字典写入档案
    dic_f = open(dictionary_file, 'wt', encoding = decoder)
    dic_f.write(str(dictionary))
    return dictionary

def find_char(char):
    # 取该字的下一个最常用字清单, 共十二个, 没有补全格空格
    char_dic = dictionary[char].items()
    rev_list = [[v[1], v[0]] for v in char_dic]
    rev_list.sort(reverse=True)
    word_list = [v[1] for v in rev_list]
    if len(word_list)<12:
        for i in range(12-len(word_list)):
            word_list.append(' ')
        else:
            word_list = word_list[:12]
    return word_list

def find_key(char):
    # 取得对应的常用字列表, 不在字典中, 则给十二个全格空格
    if char not in dictionary:
        word_list = [' ' for i in range(12)]
    else:
        word_list = find_char(char)
    return word_list

def update_char(char):
    # 显示十二个常用字的内容
    word_list = find_key(char)
    for i in range(len(key_list)):
        main_widget.key[i].config(text=word_list[i])

def add_dictionary(pre_char, new_char):
    '''
    检查是不是中文字 ?
        是中文字, 前一个字也是中文字的话
            是新字, 则加入字典
            不是新字, 该字的次数加1
    '''
    if '\u4e00' <= pre_char <= '\u9fa5':
        if '\u4e00' <= new_char <= '\u9fa5':
            if pre_char in dictionary:
                if new_char in dictionary[pre_char]:
                    dictionary[pre_char][new_char] += 1
                else:
                    dictionary[pre_char][new_char] = 1
            else:
                dictionary[pre_char] = {new_char:1}

def key_action(event):

    if 112<=event.keycode<=123: # 检查是不是F1~F12按键
        insert_char = main_widget.key[event.keycode-112]['text']
        if insert_char != ' ':
            main_widget.t1.insert(INSERT,insert_char)
            update_char(insert_char)
    else:                       # 按输入字, F1~F12内容更新
        char = event.widget.get("%s-1c" % INSERT, INSERT)
        update_char(char)
    # 检查前一字, 与现在的字, 字典更新处理
    pre_char = event.widget.get("%s-2c" % INSERT, "%s-1c" % INSERT)
    new_char = event.widget.get("%s-1c" % INSERT, INSERT)
    add_dictionary(pre_char, new_char)

class main_window():
    '''
    主窗口建立显示
    Frame1放四个功能键(save, write, analysis, exit)
    Frame2放十二个标签(F1 ~ F12)
    Frame3放一个文本再加一个垂直滚动条
    '''
    def __init__(self):

        menu_b = []
        self.f_all = Frame(root, bg=gnd, padx=pad, pady=pad)
        self.f_all.pack()
        self.f1 = Frame(self.f_all, bg=gnd)
        self.f1.pack(side=TOP)
        for i in range(len(menu)):
            menu_b.append(new_button(self.f1, menu[i], i, 0))

        self.f2 = Frame(self.f_all, bg=gnd)
        self.f2.pack(side=TOP)
        self.key=[]
        for i in range(len(key_list)):
            new_label(self.f2, key_list[i], i*2, 1)
            self.key.append(new_button(self.f2, word_list[i], i*2, 1))

        self.f3 = Frame(self.f_all, bg=gnd)
        self.f3.pack(side=TOP)
        self.t1 = Text(self.f3, font=font, fg='white', bg=l_gnd, width=80,
            height=20, padx=pad, pady=pad)
        self.t1.pack(side=LEFT, fill=Y)
        self.s1 = Scrollbar(self.f3)
        self.s1.pack(side=RIGHT, fill=Y)
        self.s1.config(command=self.t1.yview)
        self.t1.config(yscrollcommand=self.s1.set)

        # 按键放开处理
        self.t1.bind('<KeyRelease>', key_action)

font_size = 20
font = ('微软黑体', font_size, 'bold')
pad = 10
gnd = 'gray20'
l_gnd = 'gray40'
title = '辅助输入编辑器 V1.0'
decoder = "utf-8-sig"
key_list = ["F1 ","F2 ","F3 ","F4 ","F5 ","F6 ", "F7 ","F8 ","F9 ","F10","F11","F12"]
dictionary_file = 'dictionary.txt'  # 字典文件名
menu = ('开启档案', '储存档案', '学习内容', '离开编辑')

dictionary = read_dictionary()          # 读入字典
word_list = [" " for i in range(12)]   # F1 ~ F12 空白内容

root = Tk()
root.title(title)
root.resizable(False, False)
main_widget = main_window()             # 建立程序窗口内容

root.mainloop()

# dictionary.txt 新檔自建內容為空字典 {}
# dictionary.txt 已有的內容示範
{'中': {'文': 2, '有': 2, '运': 2, '一': 1, '避': 1, '诞': 1, '类': 1, '繁': 1, '的': 5, '出': 3, '所': 1, '集': 1, '讨': 1, '和': 1}, '文': {'维': 1, '件': 11, '本': 9, '献': 3, '单': 1, '档': 1, '语': 1, '化': 1, '字': 1}, '维': {'基': 27, '图': 1, '护': 3}, '基': {'百': 8, '金': 6, '数': 3, '教': 4, '于': 14, '本': 2, '共': 3, '语': 2, '学': 2, '社': 1, '媒': 3}, '百': {'科': 9, '上': 1}, '科': {'条': 1, '全': 1, '书': 5, '学': 9, '技': 1, '的': 1, '标': 1, '免': 1}, '条': {'目': 4, '件': 4, '款': 3}, '目': {'协': 1, '录': 2, '的': 4, '标': 1, '讨': 1, '中': 1}, '协': {'作': 1, '调': 1, '议': 5, '程': 1}, '作': {'计': 1, '系': 7, '为': 11, '简': 1, '者': 1, '变': 1, '业': 2, '用': 2, '的': 1, '是': 2, '对': 1, '配': 1}, '计': {'划': 4, '者': 1, '哲': 4, '算': 16, '的': 9, '工': 1, '任': 1, '为': 1, '师': 1, '目': 1, '时': 1, '允': 1, '有': 1, '社': 1, '框': 1, '主': 1}, '划': {'专': 1, '分': 1, '例': 1, '线': 6, '中': 1}, '专': {'页': 1, '门': 4, '业': 1}, '页': {'已': 1, '设': 2, '技': 1, '面': 4}, '已': {'建': 1, '在': 1, '决': 1, '时': 1, '经': 7, '无': 1, '正': 1}, .......... }
本作品采用《CC 协议》,转载必须注明作者和本文链接
Jason Yang
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!