最近在做项目需要用到WXPython做一个界面读取图片,所以就写了一个简单的图片浏览器的界面。
一个简单的图片浏览器的例子:
在wxpython 中最简单的展示图片的方式是使用wx.StaticBitmap类展示图片。在这个例子中,我们在初始化的时候,界面上有图片的位置,所以我们使用的是wx.EmptyImage去生成一个空白的图片。最后,我们需要缩放图片。下面是一下代码:
import os
import wx
class PhotoCtrl(wx.App):
def __init__(self, redirect=False, filename=None):
wx.App.__init__(self, redirect, filename)
self.frame = wx.Frame(None, title='Photo Control')
self.panel = wx.Panel(self.frame)
self.PhotoMaxSize = 240
self.createWidgets()
self.frame.Show()
def createWidgets(self):
instructions = 'Browse for an image'
img = wx.EmptyImage(240,240)
self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY,
wx.BitmapFromImage(img))
instructLbl = wx.StaticText(self.panel, label=instructions)
self.photoTxt = wx.TextCtrl(self.panel, size=(200,-1))
browseBtn = wx.Button(self.panel, label='Browse')
browseBtn.Bind(wx.EVT_BUTTON, self.onBrowse)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY),
0, wx.ALL|wx.EXPAND, 5)
self.mainSizer.Add(instructLbl, 0, wx.ALL, 5)
self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
self.sizer.Add(self.photoTxt, 0, wx.ALL, 5)
self.sizer.Add(browseBtn, 0, wx.ALL, 5)
self.mainSizer.Add(self.sizer, 0, wx.ALL, 5)
self.panel.SetSizer(self.mainSizer)
self.mainSizer.Fit(self.frame)
self.panel.Layout()
def onBrowse(self, event):
"""
Browse for file
"""
wildcard = "JPEG files (*.jpg)|*.jpg"
dialog = wx.FileDialog(None, "Choose a file",
wildcard=wildcard,
style=wx.OPEN)
if dialog.ShowModal() == wx.ID_OK:
self.photoTxt.SetValue(dialog.GetPath())
dialog.Destroy()
self.onView()
def onView(self):
filepath = self.photoTxt.GetValue()
img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)
# scale the image, preserving the aspect ratio
W = img.GetWidth()
H = img.GetHeight()
if W > H:
NewW = self.PhotoMaxSize
NewH = self.PhotoMaxSize * H / W
else:
NewH = self.PhotoMaxSize
NewW = self.PhotoMaxSize * W / H
img = img.Scale(NewW,NewH)
self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))
self.panel.Refresh()
if __name__ == '__main__':
app = PhotoCtrl()
app.MainLoop()
import glob
import wx
from wx.lib.pubsub import Publisher
########################################################################
class ViewerFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Image Viewer")
panel = ViewerPanel(self)
self.folderPath = ""
Publisher().subscribe(self.resizeFrame, ("resize"))
self.initToolbar()
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(panel, 1, wx.EXPAND)
self.SetSizer(self.sizer)
self.Show()
self.sizer.Fit(self)
self.Center()
#----------------------------------------------------------------------
def initToolbar(self):
"""
Initialize the toolbar
"""
self.toolbar = self.CreateToolBar()
self.toolbar.SetToolBitmapSize((16,16))
open_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, (16,16))
openTool = self.toolbar.AddSimpleTool(wx.ID_ANY, open_ico, "Open", "Open an Image Directory")
self.Bind(wx.EVT_MENU, self.onOpenDirectory, openTool)
self.toolbar.Realize()
#----------------------------------------------------------------------
def onOpenDirectory(self, event):
"""
Opens a DirDialog to allow the user to open a folder with pictures
"""
dlg = wx.DirDialog(self, "Choose a directory",
style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
self.folderPath = dlg.GetPath()
print self.folderPath
picPaths = glob.glob(self.folderPath + "\\*.jpg")
print picPaths
Publisher().sendMessage("update images", picPaths)
#----------------------------------------------------------------------
def resizeFrame(self, msg):
""""""
self.sizer.Fit(self)
一个视图版面:
import wx
from wx.lib.pubsub import Publisher
########################################################################
class ViewerPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
width, height = wx.DisplaySize()
self.picPaths = []
self.currentPicture = 0
self.totalPictures = 0
self.photoMaxSize = height - 200
Publisher().subscribe(self.updateImages, ("update images"))
self.slideTimer = wx.Timer(None)
self.slideTimer.Bind(wx.EVT_TIMER, self.update)
self.layout()
#----------------------------------------------------------------------
def layout(self):
"""
Layout the widgets on the panel
"""
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
img = wx.EmptyImage(self.photoMaxSize,self.photoMaxSize)
self.imageCtrl = wx.StaticBitmap(self, wx.ID_ANY,
wx.BitmapFromImage(img))
self.mainSizer.Add(self.imageCtrl, 0, wx.ALL|wx.CENTER, 5)
self.imageLabel = wx.StaticText(self, label="")
self.mainSizer.Add(self.imageLabel, 0, wx.ALL|wx.CENTER, 5)
btnData = [("Previous", btnSizer, self.onPrevious),
("Slide Show", btnSizer, self.onSlideShow),
("Next", btnSizer, self.onNext)]
for data in btnData:
label, sizer, handler = data
self.btnBuilder(label, sizer, handler)
self.mainSizer.Add(btnSizer, 0, wx.CENTER)
self.SetSizer(self.mainSizer)
#----------------------------------------------------------------------
def btnBuilder(self, label, sizer, handler):
"""
Builds a button, binds it to an event handler and adds it to a sizer
"""
btn = wx.Button(self, label=label)
btn.Bind(wx.EVT_BUTTON, handler)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
#----------------------------------------------------------------------
def loadImage(self, image):
""""""
image_name = os.path.basename(image)
img = wx.Image(image, wx.BITMAP_TYPE_ANY)
# scale the image, preserving the aspect ratio
W = img.GetWidth()
H = img.GetHeight()
if W > H:
NewW = self.photoMaxSize
NewH = self.photoMaxSize * H / W
else:
NewH = self.photoMaxSize
NewW = self.photoMaxSize * W / H
img = img.Scale(NewW,NewH)
self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))
self.imageLabel.SetLabel(image_name)
self.Refresh()
Publisher().sendMessage("resize", "")
#----------------------------------------------------------------------
def nextPicture(self):
"""
Loads the next picture in the directory
"""
if self.currentPicture == self.totalPictures-1:
self.currentPicture = 0
else:
self.currentPicture += 1
self.loadImage(self.picPaths[self.currentPicture])
#----------------------------------------------------------------------
def previousPicture(self):
"""
Displays the previous picture in the directory
"""
if self.currentPicture == 0:
self.currentPicture = self.totalPictures - 1
else:
self.currentPicture -= 1
self.loadImage(self.picPaths[self.currentPicture])
#----------------------------------------------------------------------
def update(self, event):
"""
Called when the slideTimer's timer event fires. Loads the next
picture from the folder by calling th nextPicture method
"""
self.nextPicture()
#----------------------------------------------------------------------
def updateImages(self, msg):
"""
Updates the picPaths list to contain the current folder's images
"""
self.picPaths = msg.data
self.totalPictures = len(self.picPaths)
self.loadImage(self.picPaths[0])
#----------------------------------------------------------------------
def onNext(self, event):
"""
Calls the nextPicture method
"""
self.nextPicture()
#----------------------------------------------------------------------
def onPrevious(self, event):
"""
Calls the previousPicture method
"""
self.previousPicture()
#----------------------------------------------------------------------
def onSlideShow(self, event):
"""
Starts and stops the slideshow
"""
btn = event.GetEventObject()
label = btn.GetLabel()
if label == "Slide Show":
self.slideTimer.Start(3000)
btn.SetLabel("Stop")
else:
self.slideTimer.Stop()
btn.SetLabel("Slide Show")
原文章:Creating a Simple Photo Viewer with wxPython