2012-05-11 40 views
5

Tôi đã viết một mô-đun ngắn có thể được chuyển qua một hình ảnh và chỉ cần tạo một cửa sổ Tkinter và hiển thị nó. Vấn đề tôi gặp phải là ngay cả khi tôi khởi tạo và gọi phương thức hiển thị hình ảnh trong một luồng riêng biệt, chương trình chính sẽ không tiếp tục cho đến khi cửa sổ Tkinter đóng lại.Chạy biểu mẫu Tkinter trong một chủ đề riêng biệt

Dưới đây là mô-đun của tôi:

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() 

Có vẻ như để làm việc tốt, ngoại trừ khi tôi gọi nó từ chương trình thử nghiệm của tôi như hình dưới đây, nó sẽ không có vẻ để cho phép chương trình thử nghiệm của tôi để tiếp tục, ngay cả khi bắt đầu trong một chủ đề khác.

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..." 

Tôi nghĩ rằng có lẽ vấn đề của tôi là tôi nên tạo một chủ đề mới trong các mô-đun riêng của mình, nhưng tôi đã muốn chỉ cần cố gắng và giữ nó đơn giản, như tôi mới để Python.

Dù sao, cảm ơn trước vì bất kỳ trợ giúp nào.

chỉnh sửa: Để rõ ràng, tôi chỉ đang cố tạo mô-đun sẽ hiển thị hình ảnh trong cửa sổ Tkinter, để tôi có thể sử dụng mô-đun này bất kỳ lúc nào tôi muốn hiển thị hình ảnh. Vấn đề mà tôi gặp phải là bất cứ khi nào một chương trình sử dụng mô-đun này, nó không thể tiếp tục cho đến khi cửa sổ Tkinter được đóng lại.

Trả lời

5

Từ nhận xét của bạn, có vẻ như bạn không cần GUI. Chỉ cần ghi hình ảnh vào đĩa và gọi một người xem bên ngoài.

Trên hầu hết các hệ thống chúng ta có thể để khởi động trình xem mặc định sử dụng một cái gì đó như thế này:

import subprocess 

subprocess.Popen("yourimage.png") 
2

Từ những gì tôi có thể nói, Tkinter không thích chơi trong các chủ đề khác. Xem bài đăng này ... I Need a little help with Python, Tkinter and threading

Công việc xung quanh là tạo một (có thể ẩn) thành chuỗi chính của bạn, tạo ra một chuỗi riêng biệt để mở hình ảnh, v.v ... và sử dụng hàng đợi được chia sẻ để gửi thư trở lại Tk chủ đề.

Bạn có cần sử dụng Tkinter cho dự án của mình không? Tôi thích Tkinter. Nó "nhanh và bẩn." - nhưng có (nhiều) trường hợp các bộ đồ họa GUI khác là cách để đi.

+1

Phần đầu tiên của câu trả lời là tốt, nhưng tôi không thể upvote vì lời khuyên để thử các bộ công cụ khác. Tkinter hoàn toàn phù hợp với loại câu hỏi này là về. –

10

Tkinter không phải là chủ đề an toàn, và sự đồng thuận chung là Tkinter không hoạt động trong một chủ đề không chính. Nếu bạn viết lại mã của mình để Tkinter chạy trong chuỗi chính, bạn có thể yêu cầu nhân viên của bạn chạy trong các chủ đề khác.

Thông báo trước chính là người lao động không thể tương tác với các tiện ích Tkinter. Họ sẽ phải ghi dữ liệu vào hàng đợi và luồng GUI chính của bạn sẽ phải thăm dò hàng đợi đó.

Nếu tất cả những gì bạn đang làm là hiển thị hình ảnh, có thể bạn không cần phải đọc luồng. Luồng chỉ hữu ích khi bạn có một quá trình chạy dài mà nếu không sẽ chặn GUI. Tkinter có thể dễ dàng xử lý hàng trăm hình ảnh và cửa sổ mà không làm đổ mồ hôi.

+0

Cảm ơn rất nhiều vì lời khuyên. Tôi đã nhận thấy rằng nếu tôi chạy self.mainloop() trong mô-đun người xem, như ví dụ trên, nó sẽ không bao giờ tiếp tục với chương trình thực sự của tôi cho đến khi cửa sổ đóng lại. Nó thực hiện điều tương tự nếu tôi đặt dòng này trong chương trình (ví dụ như view.mainloop()). Tôi đã nghĩ rằng việc đặt dòng này trong một sợi riêng biệt có thể giải quyết được vấn đề. Bạn đang nói rằng tôi sẽ có thể làm điều này mà không cần luồng, bạn có nghĩa là có một cách để hiển thị cửa sổ mà không có mainloop()? – ballsatballsdotballs

+0

@ballsdotballs: bạn cần phải gọi 'mainloop' nếu bạn định tạo GUI tương tác. Bởi bản chất của nó, bởi vì bạn đang chạy một vòng lặp sự kiện, bạn có thể không cần các chủ đề. Đúng là sau khi gọi 'mainloop'" nó sẽ không bao giờ tiếp tục với chương trình thực sự của bạn, nhưng đó là cách nó được thiết kế để hoạt động. Bạn thiết lập vòng lặp, sau đó chương trình của bạn chỉ phản hồi các sự kiện. 'mainloop' hầu như luôn là dòng mã cuối cùng trong logic khởi động ứng dụng của bạn. –

+0

Tôi nghĩ rằng vấn đề là, tôi chỉ đơn giản muốn viết một mô-đun hiển thị một hình ảnh. Tôi cần một cách để chương trình của tôi tiếp tục chạy sau khi sử dụng mô-đun này, thay vì chờ người dùng đóng hình ảnh. Bạn có nghĩa là không có cách nào để sử dụng Tkinter để làm điều này? – ballsatballsdotballs

3

Tôi đã cố gắng để chạy Tkinter từ một thread riêng biệt, không phải là một ý tưởng tốt, nó bị đóng băng. Có một giải pháp hoạt động. Chạy gui trong chủ đề chính và gửi các sự kiện tới gui chính. Đây là ví dụ tương tự, nó chỉ hiển thị một nhãn.

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") 
Các vấn đề liên quan