WxPython -- 第五篇 -- 保存文件内容(事件处理)

上一章中我添加了一个保存文件内容的菜单选项,但遗憾的是当我点击 "保存" 选项时编辑器并不会真正地保存我的文件内容,他只是一个单纯的选项,不会执行任何的关于文件读写的操作。
今天,让我继续改造这个文本编辑器,使它可以保存我的文件内容。

如果忘记了上一章的内容,下面是上一章中的完整源码。

import wx

class MainWindow(wx.Frame):
    def __init__(self, parent, title, size=(600,400)):
        wx.Frame.__init__(self, parent=parent, title=title, size=size)

        # 文本编辑框
        self.text_control = wx.TextCtrl(self, style=wx.TE_MULTILINE)

        # 菜单
        file_menu = wx.Menu()
        file_menu_save = file_menu.Append(wx.ID_SAVE, '保存', '将会保存输入框中的内容')
        window_menu = wx.MenuBar()
        window_menu.Append(file_menu, '文件')
        self.SetMenuBar(window_menu)

        # 窗口状态栏
        self.CreateStatusBar()

        self.Show(True)

app = wx.App()
window = MainWindow(None, '文本编辑器')
app.MainLoop()

嗯...,复习完上一章的内容,别急着打开代码编辑器写代码,先了解事件处理的思想:GUI 应用程序的核心是对各种交互事件的处理程序。应用程序一般在完成建立图形界面 等初始化工作后都会进入一个事件循环(例如WxPython的 app.MainLoop() ),等待事件发生并触发相应的事件处理程序
我一直坚信学习是一个把复杂内容简化后存入脑子的过程,所以上面一段话我简化为:“我转动汽车的钥匙,汽车使用电瓶替我发动了汽车”

额外的提示:事件的概念。
事件!简单的理解,事件就是你的行为所触发的....额.....一些..东西。例如你点击了程序中的一个按钮,可以称为一个 “点击事件”

那我保存文件的过程可以是这样的:

  1. 我点击“保存”菜单选项
  2. WxPython为我调用一个方法,替我把文件内容保存到硬盘中

大概了解后,打开代码编辑器,开始为程序添加处理 “保存” 事件的功能。

import wx

class MainWindow(wx.Frame):
    def __init__(self, parent, title, size=(600,400)):
        wx.Frame.__init__(self, parent=parent, title=title, size=size)

        # 菜单
        file_menu = wx.Menu()
        file_menu_save = file_menu.Append(wx.ID_SAVE, '保存', '将会保存输入框中的内容')
        window_menu = wx.MenuBar()
        window_menu.Append(file_menu, '文件')
        self.SetMenuBar(window_menu)

        # 文本编辑框
        self.text_control = wx.TextCtrl(self, style=wx.TE_MULTILINE)

        # 窗口状态栏
        self.CreateStatusBar()

        # 新内容
        # 关联事件
        self.Bind(wx.EVT_MENU, self.save_file_content, file_menu_save)

        self.Show(True)

    # 新内容
    # 保存输入框架内容
    def save_file_content(self, event):
        print('保存文件')


app = wx.App()
window = MainWindow(None, '文本编辑器')
app.MainLoop()
代码解读

Bind() 方法
函数原型:Bind(event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY)
参数event(必须):指定发生的事件类型
参数handler(必须):指定事件发生后调用的事件处理方法
参数source(可选):事件发生者(或者说事件的来源)
参数id(可选):此参数使用wx.ID_ANY让Widgets自行选择
参数id2(可选):此参数使用wx.ID_ANY让Widgets自行选择

self.Bind(wx.EVT_MENU, self.save_file_content, file_menu_save)
参数(wx.EVT_MENU):指定事件类型为菜单事件
参数(self.save_file_content):指定处理事件的方法为save_file_content()
参数(file_menu_save):此参数为file_menu.Append(wx.ID_SAVE, '保存', '将会保存输入框中的内容') 返回的控件的句柄(或者说控件的标识)。

def save_file_content(self, event):
这是处理保存事件的方法,用于保存输入框内容到文件中
参数(event):发生的事件,事件处理方法已被WxPython写死,只能接收一个参数

现在我拥有了一个处理 “保存” 事件的方法: save_file_content(),当我点击菜单中的 “保存” 选项时就会调用此方法来处理我的事件。现在来测试下我们的劳动成功


点击 “保存” 选项时确实调用了 save_file_content() 来处理我保存事件,而 save_file_content() 的作用就是在控制台打印 保存文件

继续!,完善 save_file_content()

    def save_file_content(self, event):
        '''
        保存文件内容
        与菜单中的保存选项绑定
        '''
        self.dir_name = ''
        fd = wx.FileDialog(self, '把文件保存到何处', self.dir_name, '.txt', 'TEXT file(*.txt)|*.txt', wx.FD_SAVE)
        if fd.ShowModal() == wx.ID_OK:
            self.file_name = fd.GetFilename()
            self.dir_name = fd.GetDirectory()
            try:
                with open(os.path.join(self.dir_name, self.file_name), 'w', encoding='utf-8') as f:
                    text = self.text_control.GetValue()
                    f.write(text)
                    save_msg = wx.MessageDialog(self, '文件已保存', '提示')
            except FileNotFoundError:
                save_msg = wx.MessageDialog(self, '保存失败,无效的保存路径', '提示')    
        else:
            save_msg = wx.MessageDialog(self, '未选择保存路径', '错误')

        save_msg.ShowModal()
        save_msg.Destroy()

小提示:由于使用了os.path.join(),需要 导入os模块
现在save_file_content() 是一个完整的文件保存方法了。
需要注意的是,在完善过程中,我添加了两个新内容,分别是 “文件对话框” 与 “提示对话框,在此章节中,不必学习这两个新内容,但为了文章的可读性,我将会简单介绍下这两个新内容。

文件对话框
# 文件对话框
fd = wx.FileDialog(self, '把文件保存到何处', self.dir_name, '.txt', 'TEXT file(*.txt)|*.txt', wx.FD_SAVE)
# 显示文件对话框
fd.ShowModal()
# 获取文件名
file_name = fd.GetFilename()
# 获取文件所在的目录的路径
dir_name = fd.GetDirectory()

不知道“文件对话框”?,参考下图:
提示对话框
# 提示对话框
save_msg = wx.MessageDialog(self, '文件已保存', '提示')
# 显示对话框
save_msg.ShowModal()
# 销毁对话框
save_msg.Destroy()

不知道“提示对话框”?参考下图:

好的,介绍完新内容,进行新一轮测试,来结束今天的内容。

啊~~,完美。
最后附上完整的示例源码

import wx
import os

class MainWindow(wx.Frame):
    def __init__(self, parent, title, size=(600, 400)):
        wx.Frame.__init__(self, parent=parent, title=title, size=size)

        # 文本编辑框
        self.text_control = wx.TextCtrl(self, style=wx.TE_MULTILINE)

        # 菜单
        file_menu = wx.Menu()
        file_menu_save = file_menu.Append(wx.ID_SAVE, '保存', '保存文件内容')
        menu_bar = wx.MenuBar()
        menu_bar.Append(file_menu, '文件')
        self.SetMenuBar(menu_bar)

        # 状态栏
        self.CreateStatusBar()

        # 新内容
        # 新内容添加了事件处理功能
        # Bind()把事件与时间处理方法绑定
        self.Bind(wx.EVT_MENU, self.save_file, file_menu_save)

        self.Show()

    def save_file(self, event):
        '''
        保存文件内容
        与菜单中的保存选项绑定
        '''
        self.dir_name = ''
        fd = wx.FileDialog(self, '把文件保存到何处', self.dir_name, 
                '.txt', 'TEXT file(*.txt)|*.txt', wx.FD_SAVE)
        if fd.ShowModal() == wx.ID_OK:
            self.file_name = fd.GetFilename()
            self.dir_name = fd.GetDirectory()
            try:
                with open(os.path.join(self.dir_name, self.file_name), 'w', encoding='utf-8') as f:
                    text = self.text_control.GetValue()
                    f.write(text)
                    save_msg = wx.MessageDialog(self, '文件已保存', '提示')
            except FileNotFoundError:
                save_msg = wx.MessageDialog(self, '保存失败,无效的保存路径', '提示')    
        else:
            save_msg = wx.MessageDialog(self, '未选择保存路径', '错误')

        save_msg.ShowModal()
        save_msg.Destroy()


app = wx.App()
main_window = MainWindow(None, '文本编辑器')
app.MainLoop()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容