【问题标题】:Simple way to display thumbnails using wxPython使用 wxPython 显示缩略图的简单方法
【发布时间】:2014-03-16 23:12:21
【问题描述】:

我正在寻找一个使用 wxPython 显示缩略图的简单解决方案。这与创建缩略图无关。我有一个缩略图目录,想在屏幕上显示它们。我故意不使用(面板、框架、窗口、滚动窗口)之类的术语,因为我对各种解决方案持开放态度。

另请注意,我发现了多个显示单个图像的示例,因此引用任何此类解决方案都对我没有帮助。解决办法一定是在wx中同时显示多张图片。

似乎我想做的是在 ThumbnailCtrl 中完成,但 Andrea 的代码很复杂,我找不到显示到屏幕的部分。我确实在 Mark Lutz 的 Programming Python 书中找到了一个简单的解决方案,但是虽然他的 viewer_thumbs.py 示例确实具有我正在寻找的简单性,但它是使用 Tkinter 完成的。

所以请任何 wx 解决方案将不胜感激。

编辑:我正在添加一个指向可以找到 Mark Lutz 工作 Tkinter 代码的地方的链接。谁能想到一个 wx 等价物?

http://codeidol.com/community/python/viewing-and-processing-images-with-pil/17565/#part-33

【问题讨论】:

  • 我几乎有了解决方案,只是在调整代码。基本上将涉及动态创建sizer。当我解决了错误时,我会发布。如果有人有理由说明此解决方案不实用,请发表评论。

标签: python wxpython wxwidgets


【解决方案1】:

我建议使用 ThumbNailCtrl 小部件:http://wxpython.org/Phoenix/docs/html/lib.agw.thumbnailctrl.html。 wxPython 演示中有一个很好的例子。或者您可以使用文档中的这个。请注意,ThumbNailCtrl 需要安装 Python Imaging Library。

import os

import wx
import wx.lib.agw.thumbnailctrl as TC

class MyFrame(wx.Frame):

    def __init__(self, parent):

        wx.Frame.__init__(self, parent, -1, "ThumbnailCtrl Demo")

        panel = wx.Panel(self)

        sizer = wx.BoxSizer(wx.VERTICAL)

        thumbnail = TC.ThumbnailCtrl(panel, imagehandler=TC.NativeImageHandler)
        sizer.Add(thumbnail, 1, wx.EXPAND | wx.ALL, 10)

        thumbnail.ShowDir(os.getcwd())
        panel.SetSizer(sizer)


# our normal wxApp-derived class, as usual

app = wx.App(0)

frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()

app.MainLoop()

只需更改 thumbnail.ShowDir(os.getcwd()) 行,使其指向您计算机上的正确文件夹。

我还在这里写了一篇查看照片的文章:http://www.blog.pythonlibrary.org/2010/03/26/creating-a-simple-photo-viewer-with-wxpython/ 不过它不使用缩略图。

【讨论】:

  • 感谢您的回复。我目前正在成功使用 Thumbnailctrl 小部件,如果需要,我将继续使用它。它只是比我需要的“更多”,并希望找到更基本的东西。我也看过你关于查看图像的文章。我已经参考它几个月了,从那个教程中学到了很多!再次感谢!
【解决方案2】:

不确定我是否应该回答我自己的问题,但我确实找到了解决问题的方法,我想分享。我使用的是 wx 2.8 版。我发现在 2.9 和 3.0 中添加了一个名为 WrapSizer 的小部件。一旦我将我的 wx 版本更新到 3.0,这使得解决方案变得非常简单。这是重要的代码 sn-ps。

    self.PhotoMaxWidth = 100
    self.PhotoMaxHeight = 100

    self.GroupOfThumbnailsSizer = wx.WrapSizer()      

    self.CreateThumbNails(len(ListOfPhotots),ListOfPhotots)

    self.GroupOfThumbnailsSizer.SetSizeHints(self.whateverPanel) 
    self.whateverPanel.SetSizer(self.GroupOfThumbnailsSizer)

    self.whateverPanel.Layout()


def CreateThumbNails(self, n, ListOfFiles):
    thumbnails = []
    backgroundcolor = "white"

    for i in range(n):

        ThumbnailSizer = wx.BoxSizer(wx.VERTICAL)
        self.GroupOfThumbnailsSizer.Add(ThumbnailSizer, 0, 0, 0)
        thumbnails.append(ThumbnailSizer)

    for thumbnailcounter, thumbsizer in enumerate(thumbnails):

        image = Image.open(ListOfFiles[thumbnailcounter])

        image = self.ResizeAndCenterImage(image, self.PhotoMaxWidth, self.PhotoMaxHeight, backgroundcolor)

        img = self.pil_to_image(image)

        thumb= wx.StaticBitmap(self.timelinePanel, wx.ID_ANY, wx.BitmapFromImage(img))

        thumbsizer.Add(thumb, 0, wx.ALL, 5)

    return

def pil_to_image(self, pil, alpha=True):
    """ Method will convert PIL Image to wx.Image """
    if alpha:
        image = apply( wx.EmptyImage, pil.size )
        image.SetData( pil.convert( "RGB").tostring() )
        image.SetAlphaData(pil.convert("RGBA").tostring()[3::4])
    else:
        image = wx.EmptyImage(pil.size[0], pil.size[1])
        new_image = pil.convert('RGB')
        data = new_image.tostring()
        image.SetData(data)
    return image

def ResizeAndCenterImage(self, image, NewWidth, NewHeight, backgroundcolor):
    width_ratio = NewWidth / float(image.size[0])
    temp_height = int(image.size[1] * width_ratio)
    if temp_height < NewHeight:
        img2 = image.resize((NewWidth, temp_height), Image.ANTIALIAS)
    else:
        height_ratio = NewHeight / float(image.size[1])
        temp_width = int(image.size[0] * height_ratio)
        img2 = image.resize((temp_width, NewHeight), Image.ANTIALIAS)

    background = Image.new("RGB", (NewWidth, NewHeight), backgroundcolor)
    masterwidth = background.size[0]
    masterheight = background.size[1]
    subwidth = img2.size[0]
    subheight = img2.size[1]
    mastercenterwidth = masterwidth // 2
    mastercenterheight = masterheight // 2
    subcenterwidth = subwidth // 2
    subcenterheight = subheight // 2
    insertpointwidth = mastercenterwidth - subcenterwidth
    insertpointheight = mastercenterheight - subcenterheight
    background.paste(img2, (insertpointwidth, insertpointheight))

    return background

我从另一个 stackoverflow 帖子中获得了 pil_to_image 部分,并编写了 ResizeAndCenterImage 部分以使我的所有缩略图大小相同,同时保持纵横比不变且不进行任何裁剪。如果您愿意,可以一起跳过调整大小和中心呼叫。

【讨论】:

    【解决方案3】:

    我只会在框架内将它们显示为 wx.Image。

    http://www.wxpython.org/docs/api/wx.Image-class.html

    来自类:“一个独立于平台的图像类。图像可以从数据中创建,或者使用wx.Bitmap.ConvertToImage,或者从各种格式的文件中加载。函数可以设置和获取图像位,因此它可以用于基本的图像处理。”

    似乎它应该能够做你想做的事,除非我错过了什么。

    【讨论】:

    • 感谢您的回复。你能给我一个多张图片的代码示例吗?如果我只显示一张图像,我知道如何将其显示为 wx.image。目录中的图片数量未知,我不知道如何同时显示所有图片。
    猜你喜欢
    • 1970-01-01
    • 2012-11-18
    • 2015-09-13
    • 2011-10-04
    • 2010-09-06
    • 2014-03-23
    • 2017-08-29
    • 2011-05-05
    • 2018-01-08
    相关资源
    最近更新 更多