fltk
fltk 1.1.8rc2を試してみた。
別スレッドで何か処理をして、その結果をGUIのスレッドで表示するというのがよくあるが、1.xだとFl::awake()とFl::add_fd()の二通りでできる。
まずawakeでやってみた。こちらはコールバック関数を直接指定することができ、コールバック関数がGUIスレッドのキューに入って、アイドル時にGUIのスレッドで呼び出されるようになっている。
2.x系だとFltk::awakeはメッセージだけを渡すようになっている。処理スレッドでGUIをlock()してから変更を加え、awake()を呼び出すと(スレッドメッセージが通知されて)必要なら再描画してくれるという感じぽい。
LinuxはEUCで試したのだが、fltk本体にパッチを当てないと(XLoadQueryFont/XDrawStringの代わりにXCreateFontSet/XmbDrawStringにするとか)日本語が表示できない。ソースのコメントに
- XRender extensionありのXFree86 4
- FreeType2サポートありのlibXft
だと直接UTF-8が描画できるとなっているんだけど試してない。
Linuxの日本語周りはちんぷんかんぷん。SetWindowText("ああああ")とかで日本語が表示できるWindowsはえらい。
#include <FL/Fl.H> #include <FL/Fl_Window.H> #include <FL/Fl_Button.H> #include <locale.h> #ifdef WIN32 #include <Windows.h> #include <Process.h> #pragma comment(lib, "ws2_32") #pragma comment(lib, "comctl32") inline static bool create_thread( void *(*function)(Fl_Window *), void *param ) { return _beginthread( (void (*)(void *))function, 0, param ) != (UINT_PTR)-1; } #else #include <unistd.h> #include <pthread.h> #define Sleep(ms) usleep((ms) * 1000) inline static bool create_thread( void *(*function)(Fl_Window *), void *param ) { pthread_t network_thread; return pthread_create( &network_thread, NULL, (void *(*)(void *))function, param ) == 0; } #endif // GUIのスレッドから呼び出されるコールバック static void MainThreadCallback( Fl_Window *parent ) { Fl_Widget *button = parent->child( 0 ); #ifdef WIN32 LOGFONT LogFont; GetObject( ::GetStockObject( DEFAULT_GUI_FONT ), sizeof LogFont, &LogFont ); Fl::set_font( FL_FREE_FONT, LogFont.lfFaceName ); #else Fl::set_font( FL_FREE_FONT, "-misc-vl pgothic-medium-*-*--*-*-*-*-*-*-*-0" ); #endif button->labelfont(FL_FREE_FONT); button->label( "こんにちは世界!" ); } // 別スレッド static void *WorkerThread( Fl_Window *parent ) { Sleep( 2000 ); Fl::awake( (Fl_Awake_Handler)MainThreadCallback, parent ); return NULL; } int main(int argc, char* argv[]) { setlocale( LC_ALL, "" ); // ウィンドウとボタンの作成 Fl_Window window(320, 120); Fl_Button button( 20,20, 280, 60, "Hello, world!"); window.show(argc, argv); // 別スレッドの作成 if ( !create_thread( WorkerThread, &window ) ) return 1; // メッセージループ Fl::lock(); return Fl::run(); }
GUIのコードがものすごく少ない。この単純さは素晴らしい。