8

画像を渡すことができ、Tkinter ウィンドウを作成して表示するだけの短いモジュールを作成しました。私が抱えている問題は、別のスレッドで画像を表示するメソッドをインスタンス化して呼び出しても、Tkinter ウィンドウが閉じられるまでメイン プログラムが続行されないことです。

これが私のモジュールです:

import Image, ImageTk
import Tkinter


class Viewer(Tkinter.Tk):
    def __init__(self,parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def initialize(self):
        self.grid()

    def show(self,img):
        self.to_display = ImageTk.PhotoImage(img)
        self.label_image = Tkinter.Label(self,image=self.to_display)
        self.label_image.grid(column = 0, row = 0, sticky = "NSEW")
        self.mainloop()

以下のようなテストプログラムから呼び出す場合を除いて、正常に動作するようです。別のスレッドで開始した場合でも、テストプログラムを続行できないようです。

import Image
from viewer import Viewer
import threading

def showimage(im):
    view = Viewer(None)
    view.show(im)

if __name__ == "__main__":
    im = Image.open("gaben.jpg")
    t = threading.Thread(showimage(im))
    t.start()
    print "Program keeps going..."

おそらく私の問題は、モジュール自体内に新しいスレッドを作成する必要があることだと思いますが、Python は初めてなので、シンプルに保ちたいと思っていました。

とにかく、助けてくれてありがとう。

編集: わかりやすくするために、画像を表示したいときにいつでもこのモジュールを使用できるように、Tkinter ウィンドウに画像を表示するモジュールを作成しようとしています。私が抱えている問題は、プログラムがこのモジュールを使用するたびに、Tkinter ウィンドウが閉じられるまで再開できないことです。

4

4 に答える 4

18

Tkinter はスレッド セーフではなく、Tkinter は非メイン スレッドでは機能しないというのが一般的なコンセンサスです。Tkinter がメイン スレッドで実行されるようにコードを書き直すと、ワーカーを他のスレッドで実行できます。

主な注意点は、ワーカーが Tkinter ウィジェットと対話できないことです。データをキューに書き込む必要があり、メインの GUI スレッドがそのキューをポーリングする必要があります。

画像を表示するだけなら、おそらくスレッド化はまったく必要ありません。スレッド化は、そうでなければ GUI をブロックする長時間実行プロセスがある場合にのみ役立ちます。Tkinter は、汗をかくことなく、何百もの画像とウィンドウを簡単に処理できます。

于 2012-05-11T18:28:01.463 に答える
5

あなたのコメントから、GUI はまったく必要ないように思えます。イメージをディスクに書き込み、外部ビューアーを呼び出すだけです。

ほとんどのシステムでは、次のような方法でデフォルトのビューアを起動できるはずです:

import subprocess 

subprocess.Popen("yourimage.png")
于 2013-01-23T14:50:51.977 に答える
3

私が知る限り、Tkinter は他のスレッドで遊ぶのが好きではありません。この投稿を参照してください... Python、Tkinter、およびスレッド化について少し助けが必要です

回避策は、メイン スレッドに (おそらく非表示の) トップレベルを作成し、別のスレッドを生成して画像を開くなどです。共有キューを使用してメッセージを Tk スレッドに送り返します。

プロジェクトで Tkinter を使用する必要がありますか? 私はTkinterが好きです。それは「速くて汚い」です。- しかし、他の GUI キットが適している (多くの) ケースがあります。

于 2012-05-11T18:22:38.190 に答える
2

別のスレッドから tkinter を実行しようとしましたが、良い考えではありません。フリーズします。うまくいった解決策が1つあります。メイン スレッドで gui を実行し、イベントをメイン gui に送信します。これは同様の例で、ラベルを表示するだけです。

import Tkinter as t
global root;
root = t.Tk()
root.title("Control center")
root.mainloop()

def new_window(*args):
    global root
    print "new window"
    window = t.Toplevel(root)
    label = t.Label(window, text="my new window")
    label.pack(side="top", fill="both", padx=10, pady=10)
    window.mainloop()

root.bind("<<newwin>>",new_window)

#this can be run in another thread
root.event_generate("<<newwin>>",when="tail")
于 2014-03-22T19:12:53.360 に答える