python - 使用 pygtk 如何制作简单的全屏幻灯片放映

标签 python pygtk slideshow fullscreen

使用 pygtk 如何制作全屏幻灯片放映,循环浏览目录中的所有图像,每 x 秒切换一次

最佳答案

我过去写过完全相同的东西。然后我就把它删除了。此版本使用准备好的代码在缩放时曝光图像。它取自Jack Valmadre’s Blog

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Taken and customed from Jack Valmadre's Blog:
# http://jackvalmadre.wordpress.com/2008/09/21/resizable-image-control/
#
# Put together and created the time switching by Izidor Matusov <<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="80e9fae9e4eff2aeede1f4f5f3eff6c0e7ede1e9ecaee3efed" rel="noreferrer noopener nofollow">[email protected]</a>>

import os

import pygtk
pygtk.require('2.0')
import gtk
import glib

def is_image(filename):
    """ File is image if it has a common suffix and it is a regular file """

    if not os.path.isfile(filename):
        return False

    for suffix in ['.jpg', '.png', '.bmp']:
        if filename.lower().endswith(suffix):
            return True

    return False

def resizeToFit(image, frame, aspect=True, enlarge=False):
    """Resizes a rectangle to fit within another.

    Parameters:
    image -- A tuple of the original dimensions (width, height).
    frame -- A tuple of the target dimensions (width, height).
    aspect -- Maintain aspect ratio?
    enlarge -- Allow image to be scaled up?

    """
    if aspect:
        return scaleToFit(image, frame, enlarge)
    else:
        return stretchToFit(image, frame, enlarge)

def scaleToFit(image, frame, enlarge=False):
    image_width, image_height = image
    frame_width, frame_height = frame
    image_aspect = float(image_width) / image_height
    frame_aspect = float(frame_width) / frame_height
    # Determine maximum width/height (prevent up-scaling).
    if not enlarge:
        max_width = min(frame_width, image_width)
        max_height = min(frame_height, image_height)
    else:
        max_width = frame_width
        max_height = frame_height
    # Frame is wider than image.
    if frame_aspect > image_aspect:
        height = max_height
        width = int(height * image_aspect)
    # Frame is taller than image.
    else:
        width = max_width
        height = int(width / image_aspect)
    return (width, height)

def stretchToFit(image, frame, enlarge=False):
    image_width, image_height = image
    frame_width, frame_height = frame
    # Stop image from being blown up.
    if not enlarge:
        width = min(frame_width, image_width)
        height = min(frame_height, image_height)
    else:
        width = frame_width
        height = frame_height
    return (width, height)


class ResizableImage(gtk.DrawingArea):

    def __init__(self, aspect=True, enlarge=False,
            interp=gtk.gdk.INTERP_NEAREST, backcolor=None, max=(1600,1200)):
        """Construct a ResizableImage control.

        Parameters:
        aspect -- Maintain aspect ratio?
        enlarge -- Allow image to be scaled up?
        interp -- Method of interpolation to be used.
        backcolor -- Tuple (R, G, B) with values ranging from 0 to 1,
            or None for transparent.
        max -- Max dimensions for internal image (width, height).

        """
        super(ResizableImage, self).__init__()
        self.pixbuf = None
        self.aspect = aspect
        self.enlarge = enlarge
        self.interp = interp
        self.backcolor = backcolor
        self.max = max
        self.connect('expose_event', self.expose)
        self.connect('realize', self.on_realize)

    def on_realize(self, widget):
        if self.backcolor is None:
            color = gtk.gdk.Color()
        else:
            color = gtk.gdk.Color(*self.backcolor)

        self.window.set_background(color)

    def expose(self, widget, event):
        # Load Cairo drawing context.
        self.context = self.window.cairo_create()
        # Set a clip region.
        self.context.rectangle(
            event.area.x, event.area.y,
            event.area.width, event.area.height)
        self.context.clip()
        # Render image.
        self.draw(self.context)
        return False

    def draw(self, context):
        # Get dimensions.
        rect = self.get_allocation()
        x, y = rect.x, rect.y
        # Remove parent offset, if any.
        parent = self.get_parent()
        if parent:
            offset = parent.get_allocation()
            x -= offset.x
            y -= offset.y
        # Fill background color.
        if self.backcolor:
            context.rectangle(x, y, rect.width, rect.height)
            context.set_source_rgb(*self.backcolor)
            context.fill_preserve()
        # Check if there is an image.
        if not self.pixbuf:
            return
        width, height = resizeToFit(
            (self.pixbuf.get_width(), self.pixbuf.get_height()),
            (rect.width, rect.height),
            self.aspect,
            self.enlarge)
        x = x + (rect.width - width) / 2
        y = y + (rect.height - height) / 2
        context.set_source_pixbuf(
            self.pixbuf.scale_simple(width, height, self.interp), x, y)
        context.paint()

    def set_from_pixbuf(self, pixbuf):
        width, height = pixbuf.get_width(), pixbuf.get_height()
        # Limit size of internal pixbuf to increase speed.
        if not self.max or (width < self.max[0] and height < self.max[1]):
            self.pixbuf = pixbuf
        else:
            width, height = resizeToFit((width, height), self.max)
            self.pixbuf = pixbuf.scale_simple(
                width, height,
                gtk.gdk.INTERP_BILINEAR)
        self.invalidate()

    def set_from_file(self, filename):
        self.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(filename))

    def invalidate(self):
        self.queue_draw()

class DemoGtk:

    SECONDS_BETWEEN_PICTURES = 3
    FULLSCREEN = True
    WALK_INSTEAD_LISTDIR = True

    def __init__(self):
        self.window = gtk.Window()
        self.window.connect('destroy', gtk.main_quit)
        self.window.set_title('Slideshow')

        self.image = ResizableImage( True, True, gtk.gdk.INTERP_BILINEAR)
        self.image.show()
        self.window.add(self.image)

        self.load_file_list()

        self.window.show_all()

        if self.FULLSCREEN:
            self.window.fullscreen()

        glib.timeout_add_seconds(self.SECONDS_BETWEEN_PICTURES, self.on_tick)
        self.display()

    def load_file_list(self):
        """ Find all images """
        self.files = []
        self.index = 0

        if self.WALK_INSTEAD_LISTDIR:
            for directory, sub_directories, files in os.walk('.'):
                for filename in files:
                    if is_image(filename):
                        filepath = os.path.join(directory, filename)
                        self.files.append(filepath)
        else:
            for filename in os.listdir('.'):
                if is_image(filename):
                    self.files.append(filename)

        print "Images:", self.files

    def display(self):
        """ Sent a request to change picture if it is possible """
        if 0 <= self.index < len(self.files):
            self.image.set_from_file(self.files[self.index])
            return True
        else:
            return False

    def on_tick(self):
        """ Skip to another picture.

        If this picture is last, go to the first one. """
        self.index += 1
        if self.index >= len(self.files):
            self.index = 0

        return self.display()

if __name__ == "__main__":
    gui = DemoGtk()
    gtk.main()

# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

关于python - 使用 pygtk 如何制作简单的全屏幻灯片放映,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6450170/

相关文章:

xml - 使 gtk 小部件填充父窗口

javascript - 如何一一创建文本并返回修复拼写

javascript - 如何在完成具有 6 个 slider 图像的 1 个循环后停止 cb 幻灯片

python - 计算范围内所有 n 个数的四面体编号,将其存储在列表中并返回

python - IPython 找不到 Shell.IPShell 类

python - 优化Python代码

python - 编写 Python GTK+ 应用程序的 'good practice' 方法是什么?

python - python中错误处理的问题

python - 当标签文本使用 pango 标记时无法设置标签对齐方式

jquery - 非常简单的图像 slider /幻灯片,带有左右按钮。没有自动播放