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です。これに最も近いのは、画像ソース(ファイルまたはデータ)を取得し、2つの画像が同じかどうかをチェックすることです(おそらくハッシュによって)。 tkinter.PhotoImageではありません。__eq__を実装しているため、2つの画像を比較して同等のデータを得ることはできません。ここで(ほとんど)問題を解決する最後の例は次のとおり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

ように同じ方法でPhotoImageimageオーバーラッパーでない、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_、それはラッパーなので問題ではないので、 'image'もそのように初期化することができます。バイトから来た場合は、 'data'が等しいかどうかチェックしてください!また、どのソースから初期化されたかを即座に判断できます。 – CommonSense

+0

@Coal_しかし、同じファイルを別のパスで初期化することができます。もしそうなら、それは問題です。しかし、@PM 2Ringは、 'tkinterは画像処理ライブラリではないと述べたので、' PhotoImage'や 'image'のペアがあっても、この場合はそれほどできません。 – CommonSense

関連する問題