青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 16, 文章 - 0, 評(píng)論 - 55, 引用 - 0
數(shù)據(jù)加載中……

fltk剖析 main-loop(二)

做為一個(gè)以c++為目標(biāo)語(yǔ)言且要適配各種平臺(tái)的界面庫(kù),F(xiàn)LTK注定是小眾的,所以寫的內(nèi)容要限定一下受眾。如果你對(duì)c/c++比較熟悉,至少對(duì)某一種操作系統(tǒng)的API比較熟悉,希望找到某種一次編寫到處編譯的界面庫(kù),同時(shí)對(duì)靈活性和尺寸比較在意,那么這個(gè)文檔就比較適合你。如果你只是希望學(xué)會(huì)怎么使用fltk,并不想深入了解它背后的原理,那么這個(gè)文檔就不太適合,fltk的在線文檔在這里:http://www.fltk.org/documentation.php

fltk最初的思路來(lái)自于1987年的NeXT系統(tǒng),初始版本針對(duì)的是X,所以代碼里有一些用X開(kāi)頭的函數(shù)名,但隨著代碼的不斷演進(jìn),接口逐漸變得和系統(tǒng)無(wú)關(guān)。

基本上,fltk認(rèn)為所有的操作系統(tǒng)都會(huì)提供以下幾種功能:
1.窗口創(chuàng)建和銷毀
2.繪圖(點(diǎn),直線,曲線,圓...)
3.字體顯示
4.輸入設(shè)備交互(鍵盤、鼠標(biāo))

只要有這幾種功能,不需要系統(tǒng)提供全套的控件,也可以自行構(gòu)建出界面。另外系統(tǒng)還會(huì)提供一些附加功能,對(duì)于豐富界面也很有幫助,但并不是充分必要條件,比如
1.圖片讀寫
2.文件操作
3.打印機(jī)
4.輸入法

基于這樣的認(rèn)知,做為一個(gè)GUI庫(kù),fltk需要提供一個(gè)模型,把這些元素組合在一起,既要有足夠的彈性又要足夠簡(jiǎn)單,F(xiàn)LTK采用的是main-loop,相信很多人開(kāi)始學(xué)習(xí)c語(yǔ)言的時(shí)候都會(huì)寫下面的代碼:
#include <stdio.h>
int main(int argc, char** argv)
{
   printf("hello world\n");
   return 0;
}

fltk所使用的模型就和這個(gè)類似,用偽代碼表示就是:
#include <fltk.h>
int main(int argc, char **argv)
{
   create_window(); // 創(chuàng)建窗口
   create_widget(); // 創(chuàng)建控件
   while (1) {
      if ( wait() ) break; // 事件循環(huán)
   }
   return 0;
}

是不是和gtk很類似?

這個(gè)模型的好處是容易理解,如果把所有的流程都用class包裹起來(lái),雖然貌似充滿了oo的味道,但是對(duì)于理解代碼反而是有害的。任何代碼都有一個(gè)入口,為了面向?qū)ο螅踔涟讶肟谝膊仄饋?lái),只會(huì)增加學(xué)習(xí)者的困擾。比如mfc,qt,juce,wxwidgets,如果想分析代碼,光是找到起點(diǎn)就很不容易,尤其為了oo,很多GUI庫(kù)用宏將main都包裹了起來(lái),更增加了理解的難度。代碼不應(yīng)該讓編譯器舒服,也不應(yīng)該屈從于某種思想,而是應(yīng)該以人為本,讓程序員看的輕松用的輕松。人的注意力是有限的,短期記憶大概只有十幾分鐘的時(shí)間,同時(shí)注意到的目標(biāo)也不多,而且似乎人的思維模式是線性的,也就是說(shuō)只能在一條線上做深入思考,并行處理好幾個(gè)問(wèn)題,大腦會(huì)短路。當(dāng)然有些發(fā)達(dá)的大腦有一心多用的本領(lǐng),但是總要照顧大多數(shù)人吧?

首先談?wù)勥@個(gè)main(),為什么叫這個(gè)名字?這和編譯器和操作系統(tǒng)有關(guān),具體原因可以自行百度,重要的只有一條,這是程序的入口。事實(shí)上并不是所有的操作系統(tǒng)都用這個(gè)名稱,osx/ios/linux是用main,windows/wince用的是winmain,android/windows phone干脆沒(méi)有main,所以要為所有的平臺(tái)編寫統(tǒng)一的main。先看看windows平臺(tái)的實(shí)現(xiàn),打開(kāi)fltk的源代碼,找到src/fl_call_main.c
extern int main(int, char *[]);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  int rc, i;
  char **ar;

#  ifdef _DEBUG
// 這里用來(lái)創(chuàng)建一個(gè)cmd窗口,或者叫dos窗口,用以輸出調(diào)試結(jié)果,只在debug版里提供
 /*
  * If we are using compiling in debug mode, open a console window so
  * we can see any printf's, etc...
  *
  * While we can detect if the program was run from the command-line -
  * look at the CMDLINE environment variable, it will be "WIN" for
  * programs started from the GUI - the shell seems to run all WIN32
  * applications in the background anyways...
  */

  AllocConsole();
  freopen("conin$", "r", stdin);
  freopen("conout$", "w", stdout);
  freopen("conout$", "w", stderr);
#  endif /* _DEBUG */

  ar = (char**) malloc(sizeof(char*) * (__argc + 1));
  i = 0;
  while (i < __argc) {
    int l;
    unsigned dstlen;
    if (__wargv ) {
      for (l = 0; __wargv[i] && __wargv[i][l]; l++) {}; /* is this just wstrlen??? */
      dstlen = (l * 5) + 1;
      ar[i] = (char*) malloc(dstlen);
/*    ar[i][fl_unicode2utf(__wargv[i], l, ar[i])] = 0; */
      dstlen = fl_utf8fromwc(ar[i], dstlen, __wargv[i], l);
      ar[i][dstlen] = 0;
    } else {
      for (l = 0; __argv[i] && __argv[i][l]; l++) {};
      dstlen = (l * 5) + 1;
      ar[i] = (char*) malloc(dstlen);
/*      ar[i][mbcs2utf(__argv[i], l, ar[i], dstlen)] = 0; */
      ar[i][mbcs2utf(__argv[i], l, ar[i])] = 0;
    }
    i++;
  }
  ar[__argc] = 0;
  /* Run the standard main entry point function... */
  rc = main(__argc, ar);

#  ifdef _DEBUG
  fclose(stdin);
  fclose(stdout);
  fclose(stderr);
#  endif /* _DEBUG */

  return rc;
}

看起來(lái)很簡(jiǎn)單,就是將winmain包裝了一下,做了一些初始化的工作,再引出main。

osx/linux直接使用了main,所以沒(méi)什么可解釋的

接下來(lái)是loop。在windows下面比較好理解,打開(kāi)src/Fl_win32.cxx,找到如下的代碼:
int fl_wait(double time_to_wait) {
  ...
  if (Fl::idle && !in_idle) { // 若處于空閑時(shí)間且存在idle函數(shù),執(zhí)行之
    in_idle = 1;
    Fl::idle();
    in_idle = 0;
  }
  ... 
  while ((have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE)) > 0) {
    if (fl_send_system_handlers(&fl_msg))
      continue;

    // Let applications treat WM_QUIT identical to SIGTERM on *nix
    if (fl_msg.message == WM_QUIT)
      raise(SIGTERM);

    if (fl_msg.message == fl_wake_msg) {
      // Used for awaking wait() from another thread
      thread_message_ = (void*)fl_msg.wParam;
      process_awake_handler_requests();
    }

    TranslateMessage(&fl_msg);
    DispatchMessageW(&fl_msg);
  }
  ...
  return 1;
}
基本上就是<<Windows程序設(shè)計(jì)>>上的那一套,就不做說(shuō)明了

再打開(kāi)src/Fl_x.cxx,找到fl_wait函數(shù),這里是linux下的loop主體,具體代碼就不分析了,有興趣的可以去找X編程的資料

最后是osx的loop,在osx下面runlooper是不能由程序直接控制的,只能通過(guò)外圍發(fā)送和接收消息的方式曲線救國(guó),所以FLTK用了一個(gè)線程,然后在線程里和runlooper交互。打開(kāi)src/Fl_cocoa.mm,找到fl_wait函數(shù),再找到DataReady類,這兩個(gè)部分組合起來(lái)就構(gòu)成了osx的loop功能,具體實(shí)現(xiàn)是用object-c和c/c++混合完成的

以上是各個(gè)系統(tǒng)各自的loop功能,最后還要將他們整合起來(lái),打開(kāi)src/Fl.cxx:
int Fl::run() {
  while (Fl_X::first) wait(FOREVER);
  return 0;
}

double Fl::wait(double time_to_wait) {
  // delete all widgets that were listed during callbacks
  do_widget_deletion();

#ifdef WIN32

  return fl_wait(time_to_wait);

#elif defined(__APPLE__)

  run_checks();
  return fl_mac_flush_and_wait(time_to_wait);

#else

  if (first_timeout) {
    elapse_timeouts();
    Timeout *t;
    while ((t = first_timeout)) {
      if (t->time > 0) break;
      // The first timeout in the array has expired.
      missed_timeout_by = t->time;
      // We must remove timeout from array before doing the callback:
      void (*cb)(void*) = t->cb;
      void *argp = t->arg;
      first_timeout = t->next;
      t->next = free_timeout;
      free_timeout = t;
      // Now it is safe for the callback to do add_timeout:
      cb(argp);
    }
  } else {
    reset_clock = 1; // we are not going to check the clock
  }
  run_checks();
//  if (idle && !fl_ready()) {
  if (idle) {
    if (!in_idle) {
      in_idle = 1;
      idle();
      in_idle = 0;
    }
    // the idle function may turn off idle, we can then wait:
    if (idle) time_to_wait = 0.0;
  }
  if (first_timeout && first_timeout->time < time_to_wait)
    time_to_wait = first_timeout->time;
  if (time_to_wait <= 0.0) {
    // do flush second so that the results of events are visible:
    int ret = fl_wait(0.0);
    flush();
    return ret;
  } else {
    // do flush first so that user sees the display:
    flush();
    if (idle && !in_idle) // 'idle' may have been set within flush()
      time_to_wait = 0.0;
    return fl_wait(time_to_wait);
  }
#endif
}

看起來(lái)很明顯,就是將各個(gè)平臺(tái)的fl_wait包裝起來(lái)組合成統(tǒng)一的接口,現(xiàn)在看一個(gè)fltk的示例代碼:test/hello.cxx
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>

int main(int argc, char **argv) {
  Fl_Window *window = new Fl_Window(340,180);
  Fl_Box *box = new Fl_Box(20,40,300,100,"Hello, World!");
  box->box(FL_UP_BOX);
  box->labelfont(FL_BOLD+FL_ITALIC);
  box->labelsize(36);
  box->labeltype(FL_SHADOW_LABEL);
  window->end();
  window->show(argc, argv);
  return Fl::run();
}

將Fl::run()展開(kāi),就是
int main(int argc, char **argv) {
  .. // create windows and widgets
 
  while (Fl_X::first) wait(FOREVER);
  return 0;
}

這就是FLTK的main-loop模型。簡(jiǎn)單,實(shí)用,好理解

posted on 2015-11-01 11:58 cyantree 閱讀(2274) 評(píng)論(0)  編輯 收藏 引用


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            91久久在线视频| 午夜激情一区| 久久在线免费观看视频| 亚洲精品影院在线观看| 午夜综合激情| 欧美日韩高清免费| 亚洲高清视频的网址| 欧美在线视频一区二区| 亚洲美女尤物影院| 免费在线成人av| 伊人久久综合| 欧美久久久久久蜜桃| 久久久99精品免费观看不卡| 性欧美长视频| 久久国产精品亚洲77777| 一区二区日韩精品| 亚洲午夜激情| 欧美成人一区在线| 永久免费视频成人| 亚洲第一网站| 午夜天堂精品久久久久| 欧美fxxxxxx另类| 欧美成ee人免费视频| 久久综合电影| 国产精品免费小视频| 日韩视频免费观看高清在线视频 | 欧美寡妇偷汉性猛交| 久久精品国产清高在天天线| 一区二区三区在线观看欧美| 国产精品麻豆va在线播放| 欧美成人精品在线| 欧美视频在线观看视频极品| 欧美四级在线| 狠狠色丁香婷婷综合久久片| 亚洲成色最大综合在线| 亚洲图片欧美午夜| 亚洲美女网站| 欧美大秀在线观看| 国产日韩精品入口| 亚洲欧美精品一区| 久久国产视频网| 亚洲视频电影图片偷拍一区| 欧美日韩国产探花| 一二三区精品| 夜夜嗨av一区二区三区网页| 欧美日韩精品欧美日韩精品一 | 欧美国产欧美亚洲国产日韩mv天天看完整 | 国产精品入口福利| 葵司免费一区二区三区四区五区| 欧美精品日韩综合在线| 国产精品一区二区你懂的| 一区二区三区视频观看| 欧美成人一区在线| 亚洲国产裸拍裸体视频在线观看乱了中文 | 亚洲精品永久免费| 欧美激情影院| 欧美激情中文字幕一区二区 | 久久久久久自在自线| 久久精品久久综合| 91久久精品一区二区别| 亚洲日本无吗高清不卡| 欧美视频免费在线观看| 性欧美办公室18xxxxhd| 久久成人精品| 精品99视频| 欧美激情一区三区| 欧美高清成人| 国产伦精品一区二区三| 久久精品在线观看| 性8sex亚洲区入口| 欧美连裤袜在线视频| 欧美午夜精品伦理| 亚洲美女在线视频| 欧美激情一区二区三区全黄| 亚洲看片网站| 欧美精品一区二区三| 亚洲精品一区二| 亚洲精品国产精品国自产观看浪潮| 久久亚洲私人国产精品va| 国产精品久久久久久久久久久久 | 久久久久国内| 亚洲欧美日韩国产| 国产精品欧美风情| 亚洲图片欧美日产| 亚洲视频在线观看| 国产裸体写真av一区二区| 国产亚洲精品美女| 欧美成人一区二区三区| 欧美日韩另类丝袜其他| 久久成人18免费网站| 模特精品在线| 欧美一区二区视频在线| 老牛影视一区二区三区| 亚洲欧美激情四射在线日 | 最新成人在线| 国产美女一区| 亚洲精品美女91| 国产一区二区在线观看免费播放 | 狂野欧美激情性xxxx欧美| 亚洲私人影院在线观看| 久久久久久久综合狠狠综合| 亚洲影院色无极综合| 久久亚洲美女| 欧美一区二区三区在线观看| 欧美成人在线免费视频| 久久精品人人做人人爽电影蜜月| 欧美二区视频| 久久九九国产精品| 欧美日韩1区2区3区| 老牛影视一区二区三区| 国产精品国产三级国产普通话三级 | 亚洲一级一区| 久久免费偷拍视频| 欧美一区精品| 欧美色区777第一页| 欧美成人中文| 国产一区二区高清不卡| 一区二区三区|亚洲午夜| 亚洲区国产区| 女同性一区二区三区人了人一| 国产色综合网| 在线观看欧美亚洲| 亚洲视频一二三| 亚洲美女毛片| 另类亚洲自拍| 久久这里只有| 国产色产综合产在线视频| 在线亚洲一区二区| 亚洲最新在线视频| 欧美不卡一区| 欧美成人高清| 一区二区自拍| 久久精品女人的天堂av| 久久精品国产69国产精品亚洲| 欧美视频一区二区| 亚洲理论在线| 日韩一级网站| 欧美电影在线| 亚洲国产高清自拍| 亚洲国产精品久久久久秋霞不卡| 久久国产精品久久国产精品| 欧美在线二区| 国产欧美日韩精品丝袜高跟鞋| 正在播放欧美视频| 亚洲少妇在线| 欧美色精品在线视频| 亚洲乱码一区二区| 一区二区三区国产在线观看| 欧美另类亚洲| 亚洲伦理精品| 亚洲自拍偷拍一区| 国产精品久久久久久久9999| 亚洲婷婷国产精品电影人久久| 亚洲午夜精品久久久久久浪潮 | 国产深夜精品福利| 亚洲欧美精品一区| 久久www成人_看片免费不卡| 国产欧美一区二区三区国产幕精品| 亚洲永久字幕| 欧美在线观看一区二区三区| 国产嫩草一区二区三区在线观看 | 久久国产精品亚洲77777| 久久精品视频在线观看| 国内精品**久久毛片app| 久久gogo国模啪啪人体图| 久久久久综合网| 在线欧美视频| 欧美v日韩v国产v| 亚洲福利国产精品| 夜夜嗨av一区二区三区网页| 欧美无乱码久久久免费午夜一区| 在线视频日本亚洲性| 欧美伊人久久久久久久久影院 | 中文精品99久久国产香蕉| 欧美亚洲成人网| 亚洲欧美日韩精品久久奇米色影视| 欧美在线免费观看| 悠悠资源网亚洲青| 欧美高清在线| 亚洲视频一二| 鲁鲁狠狠狠7777一区二区| 亚洲欧洲日本在线| 欧美午夜一区二区| 欧美一区二区三区免费看| 欧美成熟视频| 亚洲淫性视频| 黑人一区二区| 欧美极品色图| 亚洲欧美韩国| 米奇777在线欧美播放| 夜夜嗨一区二区| 国产精品视频福利| 久久久欧美一区二区| 亚洲乱码国产乱码精品精可以看| 性亚洲最疯狂xxxx高清| 伊人成人开心激情综合网| 欧美黄色免费| 午夜在线一区二区| 亚洲成色777777在线观看影院| 亚洲伊人第一页|