Как я могу закрыть изображение, показанное пользователю с помощью библиотеки изображений Python?

У меня есть несколько изображений, которые я хотел бы показать пользователю с помощью Python. Пользователь должен ввести некоторое описание, а затем должно быть показано следующее изображение.

Это мой код:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, glob
from PIL import Image

path = '/home/moose/my/path/'
for infile in glob.glob( os.path.join(path, '*.png') ):
    im = Image.open(infile)
    im.show()
    value = raw_input("Description: ")
    # store and do some other stuff. Now the image-window should get closed

Это работает, но пользователь должен сам закрыть изображение. Могу ли я заставить python закрыть изображение после ввода описания?

Мне не нужен ПИЛ. Если у вас есть другая идея с другой библиотекой/bash-программой (с подпроцессом), тоже подойдет.


person Martin Thoma    schedule 17.07.2011    source источник


Ответы (3)


Метод show «в основном предназначен для целей отладки» и порождает внешний процесс, для которого вы не получаете дескриптор, поэтому вы не можете убить его должным образом.

С PIL вы можете использовать один из его модулей графического интерфейса, например ImageTk, ImageQt или ImageWin.

В противном случае просто вручную создайте средство просмотра изображений из Python с модулем subprocess:

for infile in glob.glob( os.path.join(path, '*.png')):
    viewer = subprocess.Popen(['some_viewer', infile])
    viewer.terminate()
    viewer.kill()  # make sure the viewer is gone; not needed on Windows
person Fred Foo    schedule 17.07.2011
comment
Привет larsmans, это именно то, что я искал. Не могли бы вы внести Popen в список (добавив [])? Без него не работает. Также спасибо за упоминание ImageTk и ImageQt, я посмотрю на них. - person Martin Thoma; 18.07.2011
comment
@moose: да, забыл [], извини. - person Fred Foo; 18.07.2011
comment
как бы я использовал предварительный просмотр на OSX как some_viewer? - person eye_mew; 25.07.2015
comment
ссылки на документацию не работают - person ijuneja; 24.05.2019

psutil может получить pid процесса display, созданного im.show(), и убить процесс с этим pid в любой операционной системе. :

import time

import psutil
from PIL import Image

# open and show image
im = Image.open('myImageFile.jpg')
im.show()

# display image for 10 seconds
time.sleep(10)

# hide image
for proc in psutil.process_iter():
    if proc.name() == "display":
        proc.kill()
person Bengt    schedule 05.07.2013
comment
@IDelgado psutil должен работать под OS X. Опишите свою проблему в системе отслеживания ошибок. - person Bengt; 23.11.2014
comment
@Bengt После proc.name метода, чтобы вы могли называть его как proc.name(), и только тогда он будет работать. Пожалуйста, исправьте это, и вы, и вы получите голосование. - person Geeocode; 27.07.2015
comment
@IDelgado см. предыдущий комментарий. - person Geeocode; 27.07.2015
comment
@GyörgySolymosi @IDelgadoДа, в новых версиях psutil proc.name — это метод, а не строковое свойство. Если кто-то проверяет свойство имени, сценарий завершается безрезультатно, потому что они выглядят примерно так: <bound method Process.name of <psutil.Process(pid=14358,name='display') at 19774288>> Спасибо, что указали на это, я обновил свой ответ. Надеюсь, в будущем об это никто не споткнется. - person Bengt; 27.07.2015

Я изменил этот рецепт, прежде чем сделать некоторую работу с изображениями в Python. Он использует Tkinter, поэтому не требует никаких модулей, кроме PIL.

'''This will simply go through each file in the current directory and
try to display it. If the file is not an image then it will be skipped.
Click on the image display window to go to the next image.

Noah Spurrier 2007'''
import os, sys
import Tkinter
import Image, ImageTk

def button_click_exit_mainloop (event):
    event.widget.quit() # this will cause mainloop to unblock.

root = Tkinter.Tk()
root.bind("<Button>", button_click_exit_mainloop)
root.geometry('+%d+%d' % (100,100))
dirlist = os.listdir('.')
old_label_image = None
for f in dirlist:
    try:
        image1 = Image.open(f)
        root.geometry('%dx%d' % (image1.size[0],image1.size[1]))
        tkpi = ImageTk.PhotoImage(image1)
        label_image = Tkinter.Label(root, image=tkpi)
        label_image.place(x=0,y=0,width=image1.size[0],height=image1.size[1])
        root.title(f)
        if old_label_image is not None:
            old_label_image.destroy()
        old_label_image = label_image
        root.mainloop() # wait until user clicks the window
    except Exception, e:
        # This is used to skip anything not an image.
        # Warning, this will hide other errors as well.
        pass
person Nick T    schedule 18.07.2011
comment
Это требует ImageTK. Но я только что нашел правильный пакет Ubuntu: sudo apt-get install python-imaging-tk. Я что-то упустил или пользователь не может внести свой вклад? Я хотел закрыть текущее окно и открыть следующее (или просто открыть следующее в текущем окне) без какого-либо другого взаимодействия с пользователем, кроме написания описания (завершение с помощью ввода). - person Martin Thoma; 18.07.2011
comment
ImageTK должен поставляться с PIL... Вы можете изменить окно и добавить текстовое поле и кнопку, если хотите. Мой Tkinter очень старый, обычно я использую wx. - person Nick T; 18.07.2011