利用 Python 制作图片轮播应用

news2024/11/16 1:45:43

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

环境准备

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

pip install wxPython pypubsub
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 类来选择图片文件夹。以下是完整的代码:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1964246.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

http协议深度解析——网络时代的安全与效率(1)

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号:网络豆云计算学堂 座右铭:低头赶路,敬事如仪 个人主页: 网络豆的主页​​​​​ 目录 写在前面: 本章目的: …

【Python学习手册(第四版)】学习笔记11.1-赋值语句(分解赋值、序列赋值、解包等)及变量命名规则详解

个人总结难免疏漏,请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。 本文主要对赋值语句的各种形式做详解,以非常通俗易懂的语言、循序渐进的方式,分别对单个、元组及列表分解、序列赋值、序列解包、多重目标…

LinuxCentos中ELK日志分析系统的部署(详细教程8K字)附图片

🏡作者主页:点击! 🐧Linux基础知识(初学):点击! 🐧Linux高级管理防护和群集专栏:点击! 🔐Linux中firewalld防火墙:点击! ⏰️创作…

Android发布Library至mavenCentral遇到 Received status code 401

一、由于我的AppUpdate 库最新的版本还是去年发布的,所以想着发布一个版本,可没想到什么都没有改动的情况下竟然返回401;检查了半天发现用户名和密码也没有错,百思不得解! 二、最后没想到竟然是sonatype那边改了&#…

常见的Markdown编辑器推荐!

工欲善其事,必先利其器。一款好用的 Markdown 编辑器能极大地提高我们的写作体验,本篇博客就来介绍一些好用的编辑器。 ‍ ‍ Markdown 编辑器的分类 根据 Markdown 编辑器的使用环境,可以简单分为四类: 在线编辑器&#xff…

类和对象(中 )C++

默认成员函数就是用户不显示实现,编译器会自动实现的成员函数叫做默认成员函数。一个类,我们在不写的情况下,编译器会自动实现6个默认成员函数,需要注意,最重要的是前4个,其次就是C11以后还会增加两个默认成…

SpringBoot 优雅实现超大文件上传

​ 博客主页: 南来_北往 系列专栏:Spring Boot实战 前言 文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传&…

hadoop学习笔记2-hdfs

3.HDFS 3.1HDFS两类节点 namenode:名称节点datanode:数据节点 1.namenode 1)namenode用来存储元数据,接收客户端的读写请求,namenode的元数据会分别保存在磁盘和内存中,保存到内存是为了快速查询数据信…

一文让你学会python:面向对象

面向对象编程(OOP) 一.类与实例 1.类: 是对现实世界描述的一种类型,是抽象的,是实例的模板,类名采用大驼峰,定义方式为 class 类名: pass 。 2.实例: 根据类创建的具体对象&…

昇思25天学习打卡营第25天 | Pix2Pix实现图像转换

Pix2Pix实现图像转换 Pix2Pix概述 Pix2Pix是一种基于条件生成对抗网络(cGAN, Condition Generative Adversarial Networks)的图像转换模型,由Phillip Isola等人在2017年提出。它能够将语义/标签图像转换为真实图片、灰度图转换为彩色图、航空…

永劫无间:排位赛游戏攻略大全!VMOS云手机辅助攻略!

在《永劫无间》中,排位赛和金乌玩法是提升实力和展示技巧的绝佳途径。以下是详细的攻略建议,帮助玩家在游戏中取得更好的成绩。 排位赛 英雄们齐聚“聚窟洲”,为争夺“不朽面具”展开激烈的战斗。排位赛是玩家展示实力的重要平台&#xff0c…

六方云笔试总结

1. (1)题目 外部变量,指的是处于函数外部的全局静态变量,所以选c (2)知识点 1. static (1)函数外部的全局变量 当一个变量在函数外部定义并使用static关键字修饰时,这…

函数的学习(二)

1.函数嵌套 在C语言中,函数的嵌套是指在一个函数内部调用另一个函数。通过函数的嵌套,可以将程序的功能细化,提高代码的可读性和可维护性。函数的嵌套可以是直接嵌套,也可以是间接嵌套。 直接嵌套是指一个函数直接在另一个函数内…

华彩38载 同心筑未来—中华财险客户节盛大启幕!

活动主题:华彩38载 同心筑未来—中华财险客户节金融知识有奖问答 活动时间:2024年7月26日至9月15日 参与方式:① 微信搜索并关注公众号“中华财险宁波分公司”进入答题活动页面,点击“开始答题”即可开始答题;②规定…

ComfyUI-MuseTalk部署依赖mmcv

ComfyUI-MuseTalk部署依赖mmcv ComfyUI-MuseTalk是MuseTalk基于ComfyUI的自定义节点插件。MMPose 是一款基于 PyTorch 的“人体姿态”分析的开源工具箱,是 OpenMMLab 项目的成员之一。OpenMMLab 团队致力于构建了深度学习时代最具影响力的开源计算机视觉算法系统&am…

【C++标准库】介绍及使用string类

string 一.string类介绍二.string类的静态成员变量三.string类的常用接口1.构造函数(constructor)2.析构函数(destructor)3.运算符重载(operator)1.operator2.operator[]3.operator4.operator 4.string的四…

SecureCrt设置豆沙绿

绿豆沙色能有效的减轻长时间用电脑的用眼疲劳! 色调:85,饱和度:123,亮度:205;RGB颜色红:199,绿:237,蓝:204; 十六进制颜色…

3步阐述搜索框做了什么事情

搜索功能是几乎每个产品的通用标配功能,一个看似简单的搜索框背后,其实隐含了大量的设计思考和技术壁垒。本文将从三个部分阐述,为何搜索框并不简单。 本文将从搜索场景的思考、基于步骤的搜索设计以及搜索数据的追踪3个部分,对产…

今日arXiv最热大模型论文:北京大学最新综述:视觉大模型中的漏洞与攻防对抗

近年来,视觉语言大模型(LVLM)在文本转图像、视觉问答等任务中大放异彩,背后离不开海量数据、强大算力和复杂参数的支撑。 但是!大模型看似庞大的身躯背后却有一颗脆弱的“心脏”,极易受到攻击。攻击者可以…

史上最全,网工必考证书大盘点,竟然有20多个?

最近很多朋友来咨询,作为网工能考什么证书?证书那么多要怎么选择?哪个性价比高、哪个回报大等等等等的问题。 不难看出,大家最近这个想要学习和提升的势头很猛,毕竟现在这个环境下,属实是不好过了&#xff…