2009-05-01 7 views
5

Tôi gặp vấn đề với các chủ đề trong pygtk. Ứng dụng của tôi bao gồm một chương trình tải ảnh xuống từ internet và sau đó hiển thị nó bằng pygtk. Vấn đề là để làm điều này và giữ cho GUI đáp ứng, tôi cần sử dụng các luồng.Cách làm việc với các chủ đề trong pygtk

Vì vậy, tôi đã nhận được một cuộc gọi lại sau khi người dùng nhấp vào nút "Tải xuống hình ảnh" và tôi gọi phương thức để tải xuống các ảnh nằm trong cùng một lớp đó.

thread.start_new_thread (self.images_download, (đường dẫn, các trang)

này sẽ không làm việc. Cách duy nhất tôi nhận được chương trình của tôi để có được vào các chủ đề là bằng cách sử dụng

gtk.threads_init ()

Trước khi bắt đầu bất kỳ chủ đề. Bây giờ nó tải về các hình ảnh nhưng GUI vẫn không phản hồi. tôi googled này và tôi đã cố gắng đưa gtk.threads_enter và gtk.threads_leave xung quanh các chủ đề nhưng nó chỉ không hoạt động.

Trả lời

12

Câu hỏi của bạn hơi mơ hồ, và không có tham chiếu đến mã thực sự của bạn, thật khó để suy đoán những gì bạn đang làm sai.

Vì vậy, tôi sẽ cung cấp cho bạn một số gợi ý để đọc, sau đó suy đoán một cách dữ dội dựa trên trải nghiệm.

Trước hết, bạn có vẻ nghĩ rằng bạn chỉ có thể giữ GUI đáp ứng bằng cách sử dụng chuỗi. Đây không phải là sự thật. Bạn cũng có thể viết mã của mình một cách không đồng bộ và thực hiện mọi thứ trong một ứng dụng đơn luồng. Twisted được xây dựng trên mô hình lập trình này. Gần đây tôi đã made a blog post giải thích cách tôi tạo một giao diện nhiệm vụ không đồng bộ, và ví dụ các trình chạy cho cả CLI và GTK +. Bạn có thể xem các ví dụ đó để xem cách các tác vụ có thể được triển khai không đồng bộ và giao diện người dùng vẫn được cập nhật.

Thứ hai, nếu bạn thích sử dụng các chủ đề vì lý do nào đó, bạn sẽ cần phải hiểu mô hình luồng GTK + một chút.

Bạn nên bắt đầu bằng cách đọc The PyGTK FAQ entry on the subject và bạn cũng có thể tìm thấy this blog post cũng dễ hiểu.

Hiện tại, để đầu cơ. Tôi đoán rằng bạn đang cố cập nhật giao diện người dùng GTK của mình từ chuỗi và không xử lý khóa đúng cách. Nếu đây là trường hợp, bạn nên tắt ngay bây giờ trì hoãn tất cả các cập nhật giao diện người dùng mà bạn muốn thực hiện từ chủ đề đến chuỗi chính bằng cách sử dụng gobject.idle_add() Bằng cách này, tất cả các cuộc gọi giao diện người dùng sẽ được thực hiện từ chuỗi chính. Nó là một mô hình tinh thần dễ dàng hơn để theo dõi trong lập trình của bạn.

Khi bạn cảm thấy bạn thực sự hiểu được những luồng và các mô hình khóa, bạn có thể xem xét cập nhật giao diện người dùng từ chủ đề của bạn, nhưng nó dễ dàng để bỏ lỡ một threads_enter()/threads_leave()

+0

+1: Không sử dụng chủ đề, chỉ cần sử dụng I/O không đồng bộ. – nosklo

1

Bạn có thể sử dụng gtk.gdk. threads_init() để cho phép bất kỳ chủ đề nào sửa đổi giao diện người dùng bằng khóa gtk.gdk.threads_enter() và gtk.gdk.theads_leave(), nhưng vấn đề với điều này là không hoạt động tốt trên các cửa sổ. Tôi đã thử nghiệm nó trên Linux và thực hiện khá tốt, nhưng tôi không có may mắn làm điều này để làm việc trên win32.

=== Sửa ===

Tôi đã được xem về vấn đề này, bạn có thể tận dụng các gobject.io_add_watch để kiểm tra xem có cái gì đó trong ổ cắm của bạn, lấy nó và sau đó cập nhật các GUI.kiểm tra bài đăng của tôi về điều này: Sockets (and some other files) and PyGTK without threads.