使用wxWidgets为[图片转ascii的Pyton程序]编写图形界面

    (说明: 这是我2007年写在cublog(China Unix)上的博客,现在把它转到这里来.)

    上次写了一个图片转ascii的程序,由于没有图像界面,用起来难免不爽,所以就学习了一下wxwidgets GUI库,写了一个图形界面.

    一共建立两个类,主程序类 mainApp(wx.app),子类swindow(wx.Frame).主程序类很简单,就是在main函数里面实例化swindow类,然后显示出来就行了.

    子类比较复杂,所有功能都在里面,以下是swindow.py的代码:

    

import wx
import os
import Image

wildcard = "jpg file(*.jpg)|*.jpg|"     \
           "bmp file(*.bmp)|*.bmp|"     \
           "gif file(*.gif)|*.gif|"    \
           "All files (*.*)|*.*"
wildcard2 = "Text file(*.txt)|*.txt|"    \
           "All files (*.*)|*.*"
def create(parent):
    return Frame1(parent)
[wxID_FRAME1, wxID_FRAME1BUTTON1, wxID_FRAME1BUTTON2, wxID_FRAME1CHECKBOX1, 
 wxID_FRAME1STATICBITMAP1, wxID_FRAME1STATICBOX1, wxID_FRAME1STATICTEXT1, 
 wxID_FRAME1TEXTCTRL1, wxID_FRAME1TEXTWIDTH, 
] = [wx.NewId() for _init_ctrls in range(9)]

class swindow(wx.Frame):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
              pos=wx.Point(318, 225), size=wx.Size(640, 371),
              style=wx.DEFAULT_FRAME_STYLE | wx.ALWAYS_SHOW_SB | wx.STATIC_BORDER | wx.CLIP_CHILDREN | wx.FRAME_SHAPED | wx.CLOSE_BOX | wx.CAPTION | wx.MINIMIZE_BOX | wx.MINIMIZE,
              title='\xcd\xbc\xc6\xac\xd7\xaa\xbb\xaf\xce\xaaASCII')
        self.SetClientSize(wx.Size(632, 337))
        self.SetBackgroundColour(wx.Colour(128, 128, 255))
        self.SetToolTipString('')
        self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
        self.SetThemeEnabled(True)
        self.Bind(wx.EVT_CLOSE, self.OnFrame1Close)
        self.checkBox1 = wx.CheckBox(id=wxID_FRAME1CHECKBOX1,
              label='\xb6\xfe\xd6\xb5\xcd\xbc\xcf\xf1', name='checkBox1',
              parent=self, pos=wx.Point(416, 248), size=wx.Size(112, 22),
              style=0)
        self.checkBox1.SetValue(False)
        self.checkBox1.SetFont(wx.Font(11, wx.SWISS, wx.NORMAL, wx.NORMAL,
              False, '\xcb\xce\xcc\xe5'))
        self.staticBitmap1 = wx.StaticBitmap(id=wxID_FRAME1STATICBITMAP1,
              name='staticBitmap1', parent=self, pos=wx.Point(9, 10),
              size=wx.Size(208, 197), style=wx.STATIC_BORDER)
        self.staticBitmap1.SetHelpText('')
        self.staticBitmap1.SetLabel('')
        self.staticBitmap1.Show(True)
        self.staticBitmap1.SetAutoLayout(False)
        self.textCtrl1 = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL1, name='textCtrl1',
              parent=self, pos=wx.Point(224, 8), size=wx.Size(400, 200),
              style=wx.VSCROLL | wx.HSCROLL | wx.TE_LEFT|wx.TE_MULTILINE,
              value='')
        self.textCtrl1.SetFont(wx.Font(4, wx.SWISS, wx.NORMAL, wx.BOLD, False,
              'Courier New'))
        self.textCtrl1.SetEditable(True)
        self.textCtrl1.SetHelpText('')
        self.button1 = wx.Button(id=wxID_FRAME1BUTTON1,
              label='\xb4\xf2\xbf\xaa\xce\xc4\xbc\xfe', name='button1',
              parent=self, pos=wx.Point(240, 296), size=wx.Size(80, 24),
              style=0)
        self.button1.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL, False,
              'Tahoma'))
        self.button1.Bind(wx.EVT_LEFT_UP, self.OnButton1LeftUp)
        self.button2 = wx.Button(id=wxID_FRAME1BUTTON2,
              label='\xc9\xfa\xb3\xc9ASCII', name='button2', parent=self,
              pos=wx.Point(360, 296), size=wx.Size(80, 24), style=0)
        self.button2.SetFont(wx.Font(11, wx.SWISS, wx.NORMAL, wx.NORMAL, False,
              'Tahoma'))
        self.button2.Bind(wx.EVT_LEFT_UP, self.OnButton2LeftUp)
        self.staticBox1 = wx.StaticBox(id=wxID_FRAME1STATICBOX1, label='',
              name='staticBox1', parent=self, pos=wx.Point(144, 224),
              size=wx.Size(392, 100), style=0)

        self.textWidth = wx.TextCtrl(id=wxID_FRAME1TEXTWIDTH, name='textWidth',
              parent=self, pos=wx.Point(272, 248), size=wx.Size(72, 18),
              style=0, value='100')
        self.textWidth.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL,
              False, 'Courier New'))
        self.staticText1 = wx.StaticText(id=wxID_FRAME1STATICTEXT1,
              label='\xc3\xbf\xd0\xd0\xd7\xd6\xb7\xfb\xca\xfd:',
              name='staticText1', parent=self, pos=wx.Point(176, 248),
              size=wx.Size(83, 15), style=0)
        self.staticText1.SetFont(wx.Font(11, wx.SWISS, wx.NORMAL, wx.NORMAL,
              False, '\xcb\xce\xcc\xe5'))
        self.savefile = 'image.txt'
    def __init__(self, parent):
        self._init_ctrls(parent)
    def gray21(self,im):
        a,b = im.size
        for i in range(a):
            for j in range(b):
                if im.getpixel((i,j)) > 128:
                    im.putpixel((i,j),255)
                else:
                    im.putpixel((i,j),0)
        return im
    def image2ascii(self,imfile):
        table = "#8XOHLTI)i=+;:,. "
        im = Image.open(imfile)
        if im.mode != "L":
            im = im.convert("L")
        w = int(self.textWidth.GetValue())
        h = int(float(w) * float(im.size[1])/float(im.size[0]))
        im = im.resize((w,h))
        if self.checkBox1.GetValue():
            #im = im.convert('1')
            im  =self.gray21(im)
        f = open(self.savefile,'w+')
        a = im.size[0]
        b = im.size[1]
        for i in range(1,b,2):
            line = ''
            for j in range(a):
                    line += table[int((float(im.getpixel((j,i)))/256.0)*len(table))]
            line += "\n"
            f.write(line)
        f.close()
    def OnButton1LeftUp(self, event):
        dlg = wx.FileDialog(
            self, message="Please choose an image",
            defaultDir=os.getcwd(), 
            defaultFile="*.jpg",
            wildcard=wildcard,
            style=wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR
            )
        if dlg.ShowModal() == wx.ID_OK:
            self.imfile = dlg.GetPath()
            
            im = Image.open(self.imfile)
            im = im.resize((208, 197))
            im.save('temp.jpg','JPEG')
            self.staticBitmap1.SetBitmap(bitmap=wx.Bitmap('temp.jpg',wx.BITMAP_TYPE_JPEG))   
            dlg.Destroy() 
        event.Skip()
    def OnButton2LeftUp(self, event):
        dlg = wx.FileDialog(
            self, message="Save txt file as ...", defaultDir=os.getcwd(), 
            defaultFile="", wildcard=wildcard2 , style=wx.SAVE
            )
        if dlg.ShowModal() == wx.ID_OK:
            self.savefile = dlg.GetPath()
        dlg.Destroy()
        self.image2ascii('temp.jpg')
        f = open(self.savefile,'r')
        text = ''
        for x in f.readlines():
            text += x       
        self.textCtrl1.SetValue(text)
        f.close()
        event.Skip()
    def OnFrame1Close(self, event):
        if os.path.exists("temp.jpg"): 
            os.remove("temp.jpg")
        event.Skip()
     主要有几个关键:
    1,中间使用了temp.jpg作为临时文件,在程序结束的时候删除.因为pyimaging的Image(处理时用到)和wxwidgets的staticbitmap(显示时用到)不能直接转换,只能使用临时文件来连接这两个数据类型.
    2,显示文本的时候,只能用等宽字体才能有效果,否则这些字符会错位的.

wxwidgets的界面相当漂亮,程序的运行结果如下:
[已经编译成exe文件,只是有点大,大概7M,呵呵]


    关于wxpython的相关内容,请参见: wxwidgets    

    

你可能感兴趣的:(image,File,button,图形,wxPython,wildcard)