这是一个系列讲座,从官方文档《photon_prog_guide》而来,主要讲述QNX下的GUI编程-Photon编程,主要针对初学者。
第一个例子:
首先我们创建一个QNX PhotonAppbuilder project,这时会自动打开PhAB工具。PhAB工具界面如下所示:
我们在弹出的对话框中选择新的应用程序样式为base window。
我们在右侧的widget palette中选择label 并回到我们的窗口上点击一下,发现新创建了一个label,之后我们到资源控制面板并选择label的Label Text属性,修改为“Hello World!”
在PhAB中选择Build→Generate UI,这时将生成界面代码,然后回到QNX Momentics IDE,编译工程并下载到目标机运行,可以查看到刚才编辑的效果。
第二个例子:
下面我们在窗口上添加一个Button,并修改其Bevel Width属性为6,Font属性为Text Font,设置Horz Alignment属性为Pt_CENTER,在Basic Flag属性中添加Pt_TOP_INLINE、Pt_BOTTOM_INLINE、Pt_LEFT_INLINE、Pt_RIGHT_INLINE属性、修改Color:Fill属性,查看修改后的效果。
Label控件可以通过设置Label Type属性为Pt_IMAGE使其显示一个图片而不显示文字,选择Label Image属性可以编辑Label的显示图片。
添加一个PtMultiText Widget显示一个多行文本。编辑Text String属性可以修改显示的文字。
添加一个PtList Widget可以显示一个选择列表。修改List of Items可以修改选择项。
很多时候我们可能需要创建相同表现的widget,此时我们可以创建一个widget模板。选择一个widget并从右键菜单选择Define Templete创建一个widget 模板。当成功创建一个模板widget之后我们可以从PhAB的window菜单选择Show Templetes显示模板并将其添加到我们的界面中去。
第三个例子:
使用PhAB,我们可以通过两步创建菜单:
在一个应用程序中添加一个Menu Bar,并添加两个Menu Button,设置它们的instant name分别为base_file和base_help ,同时设置Label Text属性为File和Help。
在Project菜单中选择Add Menu,并将其name修改为filemenu,修改Menu Item添加菜单项,并将新菜单项的inst name修改为file_new,同样创建file_open,file_save,之后再新建一个Separator菜单项,最后建立一个file_quit菜单项。
为了在点击File菜单按钮时显示file菜单,我们需要将Arm回调关联到这个按钮。选择base_file按钮的Arm回调,由于我们想弹出一个菜单,选择Menu。之后在Name下拉菜单中选择我们的filemenu。
回到filemenu的编辑,我们选择file_quit菜单项,添加一个Quit回调函数。
选择Build->Generate UI生成界面代码,然后在PhAB中选择菜单Window->Show Project看到文件列表中的Quit.c,选择他并点击Edit按钮,或者直接双击来修改quit函数。
int Quit( PtWidget_t *widget, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo ) { /* eliminate 'unreferenced' warnings */ widget = widget, apinfo = apinfo, cbinfo = cbinfo; PtExit( EXIT_SUCCESS ); return( Pt_CONTINUE ); }
之后运行程序观看效果。
第四个例子:
接上面的程序,我们创建一个helpmenu菜单,并且建立菜单项help_help,help_about,同时我们建立help_about菜单项的callback为一个名为aboutdlg的对话框对象(由于对话框现在还不存在,我们只能在列表框中手动输入对话框名称)。在setup function框中,我们输入aboutdlg_setup,这里指定了aboutdlg在实例化时将要调用的函数。同时对话框的Location属性我们设置为Center Screen。最终设置的效果如下图:
选择apply之后PhAB弹出一个对话框让我们选择aboutdlg应该是什么类型,我们选择Plain类型。
下面我们选择aboutdlg对话框,放两个PtLabel对象到对话框上,再放一个按钮。设置一个Label名字为about_version并什么都不显示,另一个显示文字“about this demo”。Button的名字为about_done,显示文字“Done”。并将该按钮的active callback设置为Done类型。
下面添加相应事件代码:
int aboutdlg_setup( PtWidget_t *link_instance, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo ) { /* eliminate 'unreferenced' warnings */ link_instance = link_instance, apinfo = apinfo, cbinfo = cbinfo; PtSetResource( ABW_about_version, Pt_ARG_TEXT_STRING, "1.00", 0); return( Pt_CONTINUE ); }
编译代码并执行可以查看效果。
第五个例子:
接上面的例子,我们从Project菜单选择新建一个Window,选择Plain样式并把Window的名字修改为newwin。
从新建的newwin的callback中我们选择window manager,添加newwin_close函数,回到Resource控制面板选择Notify,并确认选择Ph_WM_CLOSE标志。
把主窗口的filenew菜单项的回调修改为对窗口newwin,并选择Setup函数为newwin_setup。
在newwin中添加一个PtRect、四个PtButton并显示如下:
修改上面一行三个按钮中:
最左边那个名字为btn_red,显示文字Red,添加Active Callback为color_change函数。
中间那个名字为btn_green,显示文字Green,添加Active Callback为color_change函数。
最右边那个名字为btn_blue,显示文字Blue,添加Active Callback为color_change函数。
下面一个最大的按钮的text修改为“Change previous window's color”,名字为btn_prev,回调同样是color_change函数。
最后界面如图:
下面生成界面代码并修改:
newwin_setup.c修改:
int win_ctr = 0; PtWidget_t *win[5]; int newwin_setup( PtWidget_t *link_instance, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo ) { /* eliminate 'unreferenced' warnings */ char buffer[40]; /* eliminate ’unreferenced’ warnings */ link_instance = link_instance, apinfo = apinfo; cbinfo = cbinfo; /* Note: Returning Pt_END in a prerealize setup function tells PhAB to destroy the module without realizing it */ /* allow only 5 windows max */ if ( win_ctr == 5 ) { return( Pt_END ); } /* save window-module instance pointer */ win[win_ctr] = link_instance; sprintf( buffer, "Window %d", win_ctr + 1 ); PtSetResource( win[win_ctr], Pt_ARG_WINDOW_TITLE, buffer, 0 ); win_ctr++; return( Pt_CONTINUE ); }
color_change.c修改为:
PgColor_t colors[5] = {Pg_BLACK, Pg_YELLOW, Pg_MAGENTA, Pg_CYAN, Pg_GREEN}; int base_clr = -1; extern int win_ctr; extern PtWidget_t *win[5]; int color_change( PtWidget_t *widget, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo ) { int i, prev; PtWidget_t *this_window; /* eliminate ’unreferenced’ warnings */ widget = widget, apinfo = apinfo, cbinfo = cbinfo; /* Get a pointer to the current window. */ this_window = ApGetInstance( widget ); if ( ApName( widget ) == ABN_btn_red ) { PtSetResource( ApGetWidgetPtr( this_window, ABN_color_rect ), Pt_ARG_FILL_COLOR, Pg_RED, 0 ); } else if ( ApName( widget ) == ABN_btn_green ) { PtSetResource( ApGetWidgetPtr( this_window, ABN_color_rect ), Pt_ARG_FILL_COLOR, Pg_GREEN, 0 ); } else if ( ApName( widget ) == ABN_btn_blue ) { PtSetResource( ApGetWidgetPtr( this_window, ABN_color_rect ), Pt_ARG_FILL_COLOR, Pg_BLUE, 0 ); } else if ( ApName( widget ) == ABN_btn_prev ) { /* Note: Here we use the window-module instance pointers saved in newwin_setup to update the window previous to the current window provided it hasn’t been closed. Determine which window is previous to this window. */ prev = -1; for ( i = 0; i < win_ctr; i++ ) { if ( win[i] == this_window ) { prev = i - 1; break; } } /* If the window still exists, update its background color. */ if ( prev != -1 && win[prev] ) { base_clr++; if (base_clr >= 5) { base_clr = 0; } PtSetResource( win[prev], Pt_ARG_FILL_COLOR, colors[base_clr], 0 ); } } return( Pt_CONTINUE ); }
newwin_close.c修改为:
extern int win_ctr; extern PtWidget_t *win[5]; int newwin_close( PtWidget_t *widget, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo ) { PhWindowEvent_t *we = cbinfo->cbdata; int i; /* eliminate ’unreferenced’ warnings */ apinfo = apinfo; /* only process WM close events */ if ( we->event_f != Ph_WM_CLOSE ) { return( Pt_CONTINUE ); } /* okay it’s a close so who is it? */ for ( i = 0; i < win_ctr; i++ ) { if ( win[i] == widget ) { win[i] = NULL; break; } } return( Pt_CONTINUE ); }
编译运行,查看效果。