wxPython制作一个简单APP

656 阅读4分钟

欢迎订阅公众号 数据分析那些事儿

前言

Python的GUI开发有很多的第三方库,wxPython、Qt和Gtk+等等。关于他们的对比网络上有很多的文章,在易用性、跨平台、稳定性等方面都有详细的比较,本文就不再赘述了。但是有一个共识是,如果你只是做一个非商业化的窗口程序,那么wxPython对于新手来说是一个非常好的选择。

wxPython函数传递机制

不同于Qt,wxWidgets是一个事件驱动的,对于触发的事件,需要给它挂上相应的事件处理函数。wxPytong函数的形式是这样的:

wx.Frame.Bind(self, event, handler, source=None, id=-1, id2=-1)  

在一般使用时,我们基本上只会给定event、handler和source,event是事件的名称,handler是处理函数,source是事件的发生者,比如一个Button1被单击而发生了EVT_BUTTON事件,如果我们用self.OnButton1()来处理,会这么写:

self.Bind(wx.EVT_BUTTON, self.OnButton1, self.Button1)  

这里self是一个Frame(wxPython中的窗体这样的东西),而Button1是放在这个Frame下面的一个Button,self.OnButton1就是事件处理函数。而wxPython定死了事件处理函数的形式:

def handler(self,event):
    ...  

事件处理函数只能接受两个参数,一个还是self。event是那个发生的事件。

学习记录APP

先看个效果

代码

#-*- coding: utf-8 -*-

import wx
import sys, os
from openpyxl import Workbook
from openpyxl import load_workbook

APP_TITLE = u'学习记录APP'
DEST_FILENAME = '学习汇总.xlsx'

class mainFrame(wx.Frame):
    '''程序主窗口类,继承自wx.Frame'''

    f = open("study.txt","r")
    ls_blank = [None]*11

    def __init__(self, parent):
        '''构造函数'''
        
        wx.Frame.__init__(self, parent, -1, APP_TITLE)
        self.SetBackgroundColour(wx.Colour(224, 224, 224))
        self.SetSize((800, 600))
        self.Center()

        BaseX=40
        BaseY=70
        BaseSize=150
        wx.StaticText(self, -1, u'编号', pos=(BaseX, BaseY), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'姓名', pos=(BaseX, BaseY+30), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'内容1',pos=(BaseX, BaseY+60), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'内容2',pos=(BaseX, BaseY+90), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'内容3',pos=(BaseX, BaseY+120), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'内容4',pos=(BaseX, BaseY+150), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'内容5',pos=(BaseX, BaseY+180), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'内容6',pos=(BaseX, BaseY+210), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'内容7',pos=(BaseX, BaseY+240), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'内容8',pos=(BaseX, BaseY+270), size=(BaseSize, -1), style=wx.ALIGN_LEFT)
        wx.StaticText(self, -1, u'内容9',pos=(BaseX, BaseY+300), size=(BaseSize, -1), style=wx.ALIGN_LEFT)

        self.tip = wx.StaticText(self, -1, u'请点击下一条学习!', pos=(145, 20), size=(500, -1), style=wx.ALIGN_CENTER)
        
        self.tc1 = wx.TextCtrl(self, -1, '', pos=(250, BaseY), size=(300, -1), name='TC01', style=wx.TE_CENTER)
        self.tc2 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+30), size=(300, -1), name='TC02', style=wx.TE_CENTER)
        self.tc3 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+60), size=(300, -1), name='TC03', style=wx.TE_CENTER)
        self.tc4 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+90), size=(300, -1), name='TC04', style=wx.TE_CENTER)
        self.tc5 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+120), size=(300, -1), name='TC05', style=wx.TE_CENTER)
        self.tc6 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+150), size=(300, -1), name='TC06', style=wx.TE_CENTER)
        self.tc7 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+180), size=(300, -1), name='TC07', style=wx.TE_CENTER)
        self.tc8 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+210), size=(300, -1), name='TC08', style=wx.TE_CENTER)
        self.tc9 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+240), size=(300, -1), name='TC09', style=wx.TE_CENTER)
        self.tc10 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+270), size=(300, -1), name='TC10', style=wx.TE_CENTER)
        self.tc11 = wx.TextCtrl(self, -1, '', pos=(250, BaseY+300), size=(500, 150), name='TC11', style=wx.TE_CENTER)

        btn_next = wx.Button(self, -1, u'下一条', pos=(650, 20), size=(100, 25))
        btn_save = wx.Button(self, -1, u'保存', pos=(650, 80), size=(100, 25))
        
        # 控件事件
        self.tc1.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc2.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc3.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc4.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc5.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc6.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc7.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc8.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc9.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc10.Bind(wx.EVT_TEXT, self.EvtText)
        self.tc11.Bind(wx.EVT_TEXT, self.EvtText)
        self.Bind(wx.EVT_BUTTON, self.DisNext, btn_next)
        self.Bind(wx.EVT_BUTTON, self.SaveInfo, btn_save)
       
        # 系统事件
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Bind(wx.EVT_SIZE, self.On_size)
        
    def EvtText(self, evt):
        '''输入框事件函数'''
        obj = evt.GetEventObject()
        objName = obj.GetName()
        text = evt.GetString()
        
        if objName == 'TC01':
            self.ls_blank[0] = text
        elif objName == 'TC02':
            self.ls_blank[1] = text
        elif objName == 'TC03':
            self.ls_blank[2] = text
        elif objName == 'TC04':
            self.ls_blank[3] = text
        elif objName == 'TC05':
            self.ls_blank[4] = text            
        elif objName == 'TC06':
            self.ls_blank[5] = text
        elif objName == 'TC07':
            self.ls_blank[6] = text
        elif objName == 'TC08':
            self.ls_blank[7] = text
        elif objName == 'TC09':
            self.ls_blank[8] = text
        elif objName == 'TC10':
            self.ls_blank[9] = text
        elif objName == 'TC11':
            self.ls_blank[10] = text        


    def On_size(self, evt):
        '''改变窗口大小事件函数'''
        
        self.Refresh()
        evt.Skip() 
    
    def OnClose(self, evt):
        '''关闭窗口事件函数'''
        
        dlg = wx.MessageDialog(None, u'确定要关闭本窗口?', u'操作提示', wx.YES_NO | wx.ICON_QUESTION)
        if(dlg.ShowModal() == wx.ID_YES):
            self.Destroy()
    
    def DisNext(self, evt):
        '''下一条触发事件函数'''
        '''读出一条'''
        line = self.f.readline()
        if line:
            self.tip.SetLabel(line)
        else:
            self.tip.SetLabel(u'已经学完!!!')
              
    def SaveInfo(self, evt):
        '''保存事件函数'''
        '''读取目的表格'''
        wb = Workbook()
        ws = wb.active

        for i in range(len(self.ls_blank)):
            _ = ws.cell(column=i+1, row=1, value=self.ls_blank[i])
        wb.save(filename = DEST_FILENAME)

        dlg = wx.MessageDialog(None, u'保存成功!')
        if(dlg.ShowModal() == wx.ID_YES):
            self.Destroy()
        
class mainApp(wx.App):
    def OnInit(self):
        self.SetAppName(APP_TITLE)
        self.Frame = mainFrame(None)
        self.Frame.Show()
        return True

if __name__ == "__main__":
    app = mainApp()
    app.MainLoop()