利用 Python 制作图片轮播应用

在这篇博客中,我将向大家展示如何使用 xPython 创建一个图片轮播应用。这个应用能够从指定文件夹中加载图片,定时轮播,并提供按钮来保存当前图片到收藏夹或仅轮播收藏夹中的图片。我们还将实现退出按钮和全屏显示的功能。

C:\pythoncode\new\pictureinfoldershow.py

环境准备

首先,我们需要安装 wxPython 和 pypubsub:

bash 复制代码
pip install wxPython pypubsub
python 复制代码
import wx
import os
import glob
import random
import xml.etree.ElementTree as ET
from pubsub import pub

FAVORITE_FILE = 'favorite.xml'

class PhotoFrame(wx.Frame):
    def __init__(self, parent, title):
        super(PhotoFrame, self).__init__(parent, title=title, size=(800, 600))
        self.Bind(wx.EVT_CLOSE, self.on_close)
        self.Bind(wx.EVT_KEY_DOWN, self.on_key_down)
        
        self.panel = wx.Panel(self)
        self.imageCtrl = wx.StaticBitmap(self.panel)
        
        # Button Panel
        btn_panel = wx.Panel(self.panel)
        btn_exit = wx.Button(btn_panel, label="退出")
        btn_fav = wx.Button(btn_panel, label="保存当前文件到收藏夹")
        btn_show_fav = wx.Button(btn_panel, label="轮播收藏夹照片")

        btn_exit.Bind(wx.EVT_BUTTON, self.on_exit_button)
        btn_fav.Bind(wx.EVT_BUTTON, self.on_fav_button)
        btn_show_fav.Bind(wx.EVT_BUTTON, self.on_show_fav_button)

        btn_sizer = wx.BoxSizer(wx.VERTICAL)
        btn_sizer.Add(btn_exit, 0, wx.ALL, 5)
        btn_sizer.Add(btn_fav, 0, wx.ALL, 5)
        btn_sizer.Add(btn_show_fav, 0, wx.ALL, 5)
        btn_panel.SetSizer(btn_sizer)
        
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add(self.imageCtrl, 1, wx.EXPAND | wx.ALL, 5)
        hbox.Add(btn_panel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
        
        self.panel.SetSizer(hbox)
        
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
        
        pub.subscribe(self.on_folder_selected, "folder_selected")
        pub.subscribe(self.on_favorites_selected, "favorites_selected")
        
        self.ShowFullScreen(True)
        self.Centre()
        
    def on_close(self, event):
        self.timer.Stop()
        self.Destroy()
        
    def on_key_down(self, event):
        keycode = event.GetKeyCode()
        if keycode == wx.WXK_ESCAPE:
            self.Close()
        event.Skip()
        
    def on_exit_button(self, event):
        self.Close()
        
    def on_fav_button(self, event):
        self.save_to_favorites()
        
    def on_show_fav_button(self, event):
        self.show_favorites()
        
    def on_timer(self, event):
        if hasattr(self, 'photos') and self.photos:
            photo = random.choice(self.photos)
            self.show_photo(photo)
        
    def on_folder_selected(self, folder):
        self.photos = glob.glob(os.path.join(folder, "*.jpg")) + \
                      glob.glob(os.path.join(folder, "*.png")) + \
                      glob.glob(os.path.join(folder, "*.jpeg"))
        if self.photos:
            self.timer.Start(5000)
        
    def on_favorites_selected(self):
        self.photos = self.load_favorites()
        if self.photos:
            self.timer.Start(5000)
        
    def show_photo(self, photo):
        self.current_photo = photo
        image = wx.Image(photo, wx.BITMAP_TYPE_ANY)
        screenWidth, screenHeight = self.GetSize()
        imgWidth, imgHeight = image.GetSize()
        
        # 等比例缩放
        aspectRatio = imgWidth / imgHeight
        if screenWidth / screenHeight > aspectRatio:
            newHeight = screenHeight
            newWidth = screenHeight * aspectRatio
        else:
            newWidth = screenWidth
            newHeight = screenWidth / aspectRatio
        
        image = image.Scale(int(newWidth), int(newHeight), wx.IMAGE_QUALITY_HIGH)
        self.imageCtrl.SetBitmap(wx.Bitmap(image))
        self.Layout()
        
    def save_to_favorites(self):
        if not hasattr(self, 'current_photo'):
            return
        root = ET.Element("favorites")
        if os.path.exists(FAVORITE_FILE):
            tree = ET.parse(FAVORITE_FILE)
            root = tree.getroot()
        new_entry = ET.SubElement(root, "photo")
        new_entry.text = self.current_photo
        tree = ET.ElementTree(root)
        tree.write(FAVORITE_FILE, encoding='utf-8', xml_declaration=True)
        
    def load_favorites(self):
        if not os.path.exists(FAVORITE_FILE):
            return []
        tree = ET.parse(FAVORITE_FILE)
        root = tree.getroot()
        return [child.text for child in root.findall('photo')]
        
    def show_favorites(self):
        pub.sendMessage("favorites_selected")

class FolderSelectorFrame(wx.Frame):
    def __init__(self, parent, title):
        super(FolderSelectorFrame, self).__init__(parent, title=title, size=(400, 200))
        panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        
        self.folderPicker = wx.DirPickerCtrl(panel, message="选择照片文件夹")
        vbox.Add(self.folderPicker, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
        
        btn = wx.Button(panel, label="开始轮播")
        vbox.Add(btn, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=10)
        btn.Bind(wx.EVT_BUTTON, self.on_start_slideshow)
        
        panel.SetSizer(vbox)
        
        self.Centre()
        self.Show()
        
    def on_start_slideshow(self, event):
        folder = self.folderPicker.GetPath()
        pub.sendMessage("folder_selected", folder=folder)
        self.Close()
        
class MyApp(wx.App):
    def OnInit(self):
        self.selectorFrame = FolderSelectorFrame(None, title="选择文件夹")
        self.photoFrame = PhotoFrame(None, title="照片轮播")
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()
代码实现

我们将实现一个 PhotoFrame 类来展示图片,以及一个 FolderSelectorFrame 类来选择图片文件夹。以下是完整的代码:

python 复制代码
import wx
import os
import glob
import random
import xml.etree.ElementTree as ET
from pubsub import pub

FAVORITE_FILE = 'favorite.xml'

class PhotoFrame(wx.Frame):
    def __init__(self, parent, title):
        super(PhotoFrame, self).__init__(parent, title=title, size=(800, 600))
        self.Bind(wx.EVT_CLOSE, self.on_close)
        self.Bind(wx.EVT_KEY_DOWN, self.on_key_down)
        
        self.panel = wx.Panel(self)
        self.imageCtrl = wx.StaticBitmap(self.panel)
        
        # Button Panel
        btn_panel = wx.Panel(self.panel)
        btn_exit = wx.Button(btn_panel, label="退出")
        btn_fav = wx.Button(btn_panel, label="保存当前文件到收藏夹")
        btn_show_fav = wx.Button(btn_panel, label="轮播收藏夹照片")

        btn_exit.Bind(wx.EVT_BUTTON, self.on_exit_button)
        btn_fav.Bind(wx.EVT_BUTTON, self.on_fav_button)
        btn_show_fav.Bind(wx.EVT_BUTTON, self.on_show_fav_button)

        btn_sizer = wx.BoxSizer(wx.VERTICAL)
        btn_sizer.Add(btn_exit, 0, wx.ALL, 5)
        btn_sizer.Add(btn_fav, 0, wx.ALL, 5)
        btn_sizer.Add(btn_show_fav, 0, wx.ALL, 5)
        btn_panel.SetSizer(btn_sizer)
        
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add(self.imageCtrl, 1, wx.EXPAND | wx.ALL, 5)
        hbox.Add(btn_panel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
        
        self.panel.SetSizer(hbox)
        
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
        
        pub.subscribe(self.on_folder_selected, "folder_selected")
        pub.subscribe(self.on_favorites_selected, "favorites_selected")
        
        self.ShowFullScreen(True)
        self.Centre()
        
    def on_close(self, event):
        self.timer.Stop()
        self.Destroy()
        
    def on_key_down(self, event):
        keycode = event.GetKeyCode()
        if keycode == wx.WXK_ESCAPE:
            self.Close()
        event.Skip()
        
    def on_exit_button(self, event):
        self.Close()
        
    def on_fav_button(self, event):
        self.save_to_favorites()
        
    def on_show_fav_button(self, event):
        self.show_favorites()
        
    def on_timer(self, event):
        if hasattr(self, 'photos') and self.photos:
            photo = random.choice(self.photos)
            self.show_photo(photo)
        
    def on_folder_selected(self, folder):
        self.photos = glob.glob(os.path.join(folder, "*.jpg")) + \
                      glob.glob(os.path.join(folder, "*.png")) + \
                      glob.glob(os.path.join(folder, "*.jpeg"))
        if self.photos:
            self.timer.Start(5000)
        
    def on_favorites_selected(self):
        self.photos = self.load_favorites()
        if self.photos:
            self.timer.Start(5000)
        
    def show_photo(self, photo):
        self.current_photo = photo
        image = wx.Image(photo, wx.BITMAP_TYPE_ANY)
        screenWidth, screenHeight = self.GetSize()
        imgWidth, imgHeight = image.GetSize()
        
        # 等比例缩放
        aspectRatio = imgWidth / imgHeight
        if screenWidth / screenHeight > aspectRatio:
            newHeight = screenHeight
            newWidth = screenHeight * aspectRatio
        else:
            newWidth = screenWidth
            newHeight = screenWidth / aspectRatio
        
        image = image.Scale(int(newWidth), int(newHeight), wx.IMAGE_QUALITY_HIGH)
        self.imageCtrl.SetBitmap(wx.Bitmap(image))
        self.Layout()
        
    def save_to_favorites(self):
        if not hasattr(self, 'current_photo'):
            return
        root = ET.Element("favorites")
        if os.path.exists(FAVORITE_FILE):
            tree = ET.parse(FAVORITE_FILE)
            root = tree.getroot()
        new_entry = ET.SubElement(root, "photo")
        new_entry.text = self.current_photo
        tree = ET.ElementTree(root)
        tree.write(FAVORITE_FILE, encoding='utf-8', xml_declaration=True)
        
    def load_favorites(self):
        if not os.path.exists(FAVORITE_FILE):
            return []
        tree = ET.parse(FAVORITE_FILE)
        root = tree.getroot()
        return [child.text for child in root.findall('photo')]
        
    def show_favorites(self):
        pub.sendMessage("favorites_selected")

class FolderSelectorFrame(wx.Frame):
    def __init__(self, parent, title):
        super(FolderSelectorFrame, self).__init__(parent, title=title, size=(400, 200))
        panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        
        self.folderPicker = wx.DirPickerCtrl(panel, message="选择照片文件夹")
        vbox.Add(self.folderPicker, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
        
        btn = wx.Button(panel, label="开始轮播")
        vbox.Add(btn, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=10)
        btn.Bind(wx.EVT_BUTTON, self.on_start_slideshow)
        
        panel.SetSizer(vbox)
        
        self.Centre()
        self.Show()
        
    def on_start_slideshow(self, event):
        folder = self.folderPicker.GetPath()
        pub.sendMessage("folder_selected", folder=folder)
        self.Close()
        
class MyApp(wx.App):
    def OnInit(self):
        self.selectorFrame = FolderSelectorFrame(None, title="选择文件夹")
        self.photoFrame = PhotoFrame(None, title="照片轮播")
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

功能实现

  1. 选择文件夹:用户可以选择一个包含图片的文件夹,应用将自动开始轮播。
  2. 定时轮播:每隔 5 秒钟,应用会自动切换到下一张图片。
  3. 全屏显示:应用启动时自动全屏显示图片。
  4. 退出功能:按下 ESC 键或点击"退出"按钮可以退出程序。
  5. 保存到收藏夹 :点击"保存当前文件到收藏夹"按钮,将当前显示的图片路径保存到 favorite.xml 文件。
  6. 轮播收藏夹图片 :点击"轮播收藏夹照片"按钮,仅轮播 favorite.xml 中保存的图片。

结果如下


总结

本文介绍了如何使用 wxPython 创建一个功能齐全的图片轮播应用。通过 wxPython 的强大功能和灵活的布局管理,我们能够轻松实现图片显示、定时切换、按钮交互和文件操作等功能。希望这篇博客能为你提供一些帮助,让你在 wxPython 的学习和使用过程中有所收获。如果有任何问题或建议,欢迎在评论区留言。

相关推荐
郭庆汝5 小时前
pytorch、torchvision与python版本对应关系
人工智能·pytorch·python
思则变8 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
漫谈网络9 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
try2find10 小时前
安装llama-cpp-python踩坑记
开发语言·python·llama
博观而约取11 小时前
Django ORM 1. 创建模型(Model)
数据库·python·django
精灵vector13 小时前
构建专家级SQL Agent交互
python·aigc·ai编程
Zonda要好好学习13 小时前
Python入门Day2
开发语言·python
Vertira13 小时前
pdf 合并 python实现(已解决)
前端·python·pdf
太凉13 小时前
Python之 sorted() 函数的基本语法
python
项目題供诗13 小时前
黑马python(二十四)
开发语言·python