2017-12-07 4 views
1

인스턴스에서 tkinter.PhotoImage 개체를 가져 오는 방법이 있습니까? 나는 부분적으로 만족스러운 답을 가지고 this question,이 알고,하지만 난 정말 PhotoImage 개체를 얻을 필요가 :tkinter 레이블에서 PhotoImage 개체 얻기

>>> import tkinter as tk 
>>> 
>>> root = tk.Tk() 
>>> 
>>> image1 = tk.PhotoImage(file="img.gif") 
>>> image2 = tk.PhotoImage(file="img.gif") 
>>> 
>>> label = tk.Label(root, image=image1) 
>>> label._image_ref = image1 
>>> label.cget("image") == image2 
False 

아마도 나를 pyimage 문자열에서 이미지 개체를 얻을 수있는 기능이 있습니까를? 나는. 하나는 label.cget("image")에서 가져 왔습니까?


대답은 apparantly입니다. 가장 가까운 것은 이미지 원본 (파일 또는 데이터)을 가져오고 두 이미지가 동일한 지 여부를 확인하는 것입니다 (아마도 해싱으로). tkinter.PhotoImage이 아니며__eq__을 구현하므로 동일한 데이터에 대해 두 이미지를 비교할 수 없습니다. tkinter으로

import hashlib 
import os 
import tkinter as tk 

_BUFFER_SIZE = 65536 


def _read_buffered(filename): 
    """Read bytes from a file, in chunks. 
    Arguments: 
    - filename: str: The name of the file to read from. 
    Returns: 
    - bytes: The file's contents. 
    """ 
    contents = [] 
    with open(filename, "rb") as fd: 
     while True: 
      chunk = fd.read(_BUFFER_SIZE) 
      if not chunk: 
       break 
      contents.append(chunk) 
     return bytes().join(contents) 


def displays_image(image_file, widget): 
    """Check whether or not 'widget' displays 'image_file'. 
    Reading an entire image from a file is computationally expensive! 
    Note that this function will always return False if 'widget' is not mapped. 
    This doesn't work for images that were initialized from bytes. 
    Arguments: 
    - image_file: str: The path to an image file. 
    - widget: tk.Widget: A tkinter widget capable of displaying images. 
    Returns: 
    - bool: True if the image is being displayed, else False. 
    """ 
    expected_hash = hashlib.sha256(_read_buffered(image_file)).hexdigest() 
    if widget.winfo_ismapped(): 
     widget_file = widget.winfo_toplevel().call(
      widget.cget("image"), "cget", "-file" 
     ) 
     if os.path.getsize(widget_file) != os.path.getsize(image_file): 
      # Size differs, the contents can never be the same. 
      return False 
     image_hash = hashlib.sha256(
      _read_buffered(widget_file) 
     ).hexdigest() 
     if image_hash == expected_hash: 
      return True 
     return False 
+1

:

하지만 여전히, 당신은 TK의 명령을 실행할 수 있습니다 모두 PhotoImageimage 비슷한 구조를 가지고 있기 때문에, 당신의 최선의 방법은 다음과 같이 될 것이다 'label._image_ref'로 저장 했습니까? 따라서 링크 된 응답은'label._image_ref.cget ('file')'처럼 적용됩니다. 그러나 부분적으로 만족스러운 것이라고 주장하는 이유는 무엇입니까? 'image1 == image2' ('PhotoImage'에는'__eq__' 메소드가 없습니다)와 같은 점에서, 평등은 항상'False'가됩니다. – CommonSense

+0

실물 크기의 GUI 테스트 라이브러리를 작성 중이며 현재 이미지가 표시되는지 여부를 확인하는 방법이 필요합니다. 나는 사람들이 이미지에 대한 언급을 계속한다고 가정 할 수 없다. 'PhotoImage''__eq__' 구현이 시각적 유사성을 처리하지 않는 이유는 모르지만 다른 문제입니다. –

+1

'PhotoImage' 객체는'__eq__' 메서드를 정의하지 않으므로 기본값을 상속합니다. 즉,'image1 == image2'를 수행하는 것이'image1 is image2'와 동일하므로 False를 반환합니다. 동일한 이미지 데이터를 포함하더라도 동일한 객체가 아닙니다. –

답변

1

그렇게 image에 대한 래퍼가 같은 방식으로 PhotoImage을 수행, tk에 대한 래퍼입니다 : 여기에 문제 (대부분) 해결하는 마지막 예제입니다. 그리고 뒤로 이동하여 image에서 PhotoImage을 만들 수는 없습니다.

import tkinter as tk 

root = tk.Tk() 

image1 = tk.PhotoImage(file="img.gif") 
image2 = tk.PhotoImage(file="img.gif") 

label = tk.Label(root, image=image1) 
label._image_ref = image1 

foo = root.call(label.cget('image'), 'cget', '-file') 
bar = image2['file'] 
print('1st image:\t%s\n2nd image:\t%s\nEqual:\t%r' % (foo, bar, foo == bar)) 
+0

내가 어디에서 왔는지 알 겠어.이런 식으로 구현한다면 아마도 파일을 열고 데이터를 해시하여 내용이 동일하게 유지되는지 확인할 수 있습니다. 그리고 다시 말하지만, 이것은 꽤 깨지기 쉬운 해결책입니다 (특히'PhotoImage '가 이미지 바이트에서 초기화 될 수 있기 때문에). 내가 더 좋은 해결책을 찾을 수 없다면 나는 이것으로 갈 것이다. 감사. –

+1

@Coal_, 래퍼 (wrapper)이기 때문에 문제가되지 않으므로'image'도 그 방식으로 초기화 될 수 있습니다. 바이트에서 오는 경우 '데이터'평등을 확인하십시오! 또한 초기화 된 소스에서 즉시 결정할 수 있습니다! – CommonSense

+0

@Coal_ 그러나 다른 경로로 같은 파일을 초기화 할 수 있습니다. 그렇다면 문제가 있습니다. 그러나 @PM 2Ring이'tkinter는 이미지 처리 라이브러리가 아니므로'PhotoImage' 나'image'의 쌍을 가지고 있더라도이 경우에는별로 할 수 없다고 말했습니다. – CommonSense

관련 문제