利用 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 的学习和使用过程中有所收获。如果有任何问题或建议,欢迎在评论区留言。

相关推荐
waterHBO19 分钟前
python 爬虫 selenium 笔记
爬虫·python·selenium
编程零零七1 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
AIAdvocate3 小时前
Pandas_数据结构详解
数据结构·python·pandas
小言从不摸鱼3 小时前
【AI大模型】ChatGPT模型原理介绍(下)
人工智能·python·深度学习·机器学习·自然语言处理·chatgpt
FreakStudio5 小时前
全网最适合入门的面向对象编程教程:50 Python函数方法与接口-接口和抽象基类
python·嵌入式·面向对象·电子diy
redcocal6 小时前
地平线秋招
python·嵌入式硬件·算法·fpga开发·求职招聘
artificiali7 小时前
Anaconda配置pytorch的基本操作
人工智能·pytorch·python
RaidenQ7 小时前
2024.9.13 Python与图像处理新国大EE5731课程大作业,索贝尔算子计算边缘,高斯核模糊边缘,Haar小波计算边缘
图像处理·python·算法·课程设计
花生了什么树~.7 小时前
python基础知识(六)--字典遍历、公共运算符、公共方法、函数、变量分类、参数分类、拆包、引用
开发语言·python
Trouvaille ~8 小时前
【Python篇】深度探索NumPy(下篇):从科学计算到机器学习的高效实战技巧
图像处理·python·机器学习·numpy·信号处理·时间序列分析·科学计算