K's Diary


このページは、たわいのない日々のウワゴトを綴るページです。
なんてツマラナソウナページなんだ(笑)

一応、内容毎にタイトルの色を変えています。
緑色はlinuxに関する話題、 黄色はコンピュータゲームに関する話題、 水色はその他の話題になっています。
なお、スタイルシートに対応していないブラウザでは、 色は変わりませんのであしからず。


過去の日記

全てのトピックを表示


'10/6/28

■ GTK+のスレッド処理 その2

前回の続き。

Windowsだったらメッセージキューに入れれば、スレッド間の通信も問題がないだろう。
というわけで、こんな感じはどうかな。

00001 #include <gtk/gtk.h>
00002 #ifdef G_OS_WIN32
00003 # include "gdk/gdkwin32.h"
00004 # include <windows.h>
00005 # define WINDOW_TO_NATIVE(w) GDK_WINDOW_HWND(w)
00006 #else
00007 # include "gdk/gdkx.h"
00008 # include <unistd.h>
00009 # define WINDOW_TO_NATIVE(w) GDK_WINDOW_XID(w)
00010 #endif
00011
00012 gpointer thread_func(gpointer data)
00013 {
00014 GdkEvent *ev;
00015 GdkEventClient *client_ev;
00016
00017 g_print("start sleep.\n");
00018 #ifdef G_OS_WIN32
00019 Sleep(3000);
00020 #else
00021 sleep(3);
00022 #endif
00023 g_print("end sleep.\n");
00024
00025 gdk_threads_enter();
00026 ev = gdk_event_new(GDK_CLIENT_EVENT);
00027 client_ev = (GdkEventClient *)ev;
00028 client_ev->message_type = gdk_atom_intern("ThreadEnd", FALSE);
00029 gtk_propagate_event(GTK_WIDGET(data), ev);
00030 gdk_event_free(ev);
00031 gdk_threads_leave();
00032
00033 return NULL;
00034 }
00035
00036 void on_clicked(GtkButton *button, gpointer user_data)
00037 {
00038 g_thread_create(thread_func, user_data, FALSE, NULL);
00039 }
00040
00041 gboolean on_client_event(GtkWidget *widget, GdkEventClient *ev, gpointer user_data)
00042 {
00043 g_print("on_client_event() message_type:\"%s\".\n", gdk_atom_name(ev->message_type));
00044 return TRUE;
00045 }
00046
00047 int main(int argc, char *argv[])
00048 {
00049 GtkWidget *window;
00050 GtkWidget *button;
00051
00052 g_thread_init(NULL);
00053 gdk_threads_init();
00054
00055 gtk_init(&argc, &argv);
00056
00057 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00058
00059 button = gtk_button_new_with_label("Push me!");
00060 gtk_widget_show(button);
00061 gtk_container_add(GTK_CONTAINER(window), button);
00062 g_signal_connect(button, "clicked", G_CALLBACK(on_clicked), window);
00063
00064 g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
00065
00066 g_signal_connect(window, "client-event", G_CALLBACK(on_client_event), NULL);
00067
00068 gtk_widget_show(window);
00069 gdk_threads_enter();
00070 gtk_main();
00071 gdk_threads_leave();
00072 return 0;
00073 }
00074

pythonならば、こう。

00001 #!/usr/bin/env python
00002 # -*- coding: utf-8 -*-
00003
00004 import threading
00005 import time
00006
00007 import pygtk
00008 pygtk.require("2.0")
00009 import gtk, gobject
00010
00011 class MyThread(threading.Thread):
00012 def __init__(self, window):
00013 threading.Thread.__init__(self)
00014 self.window = window
00015
00016 def run(self):
00017 print("start sleep.")
00018 time.sleep(3)
00019 print("end sleep.")
00020
00021 gtk.gdk.threads_enter()
00022 ev = gtk.gdk.Event(gtk.gdk.CLIENT_EVENT)
00023 ev.message_type = gtk.gdk.atom_intern("ThreadEnd")
00024 self.window.event(ev)
00025 gtk.gdk.threads_leave()
00026
00027 class MyWindow(gtk.Window):
00028 def __init__(self):
00029 gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
00030
00031 button = gtk.Button("Push me!")
00032 button.show()
00033 self.add(button)
00034 button.connect("clicked", self.on_clicked)
00035
00036 self.connect("client-event", self.on_client_event)
00037
00038 def on_clicked(self, *args):
00039 thread = MyThread(self)
00040 thread.start()
00041
00042 def on_client_event(self, widget, ev):
00043 print("on_client_event() message_type:\"%s\"." % str(ev.message_type))
00044 return True
00045
00046 if __name__ == "__main__":
00047 gtk.gdk.threads_init()
00048
00049 window = MyWindow()
00050 window.connect("destroy", gtk.main_quit)
00051 window.show()
00052
00053 gtk.gdk.threads_enter()
00054 gtk.main()
00055 gtk.gdk.threads_leave()
00056

一応うまく動作しているっぽいのだけど、正直gtk_propagate_event関数の使い方がこれであっているのか、自信はありません(苦笑)
というか、出来ればFAQのようにシグナルで処理したいので、こんな事をするのはWindowsの時だけにしたいな。