新控件的創(chuàng )建是通過(guò)繼承已經(jīng)存在的控件來(lái)得到的,一般控件繼承Fl_Widget得到,組合控件繼承Fl_Group得到
一個(gè)普通控件一般通過(guò)接收和顯示一個(gè)值來(lái)與用戶(hù)交互
一個(gè)組合控件包含一組子控件并處理子控件的移動(dòng),改變大小,顯示或隱藏事件。Fl_Group是所有組合控件的基類(lèi),其他組合控件比如Fl_Pack, Fl_Scroll, Fl_Tabs , Fl_Tile, Fl_Window都是他的子類(lèi)
你也可以通過(guò)繼承其他的已存在控件來(lái)得到你要的控件,通過(guò)提供不同的外觀(guān)和接口。比如Button 控件都是 Fl_Button類(lèi)的子類(lèi)。他們的共同點(diǎn)是都是通過(guò)鼠標點(diǎn)擊事件與用戶(hù)交互。唯一不同的是按鈕的外觀(guān)。
你的子類(lèi)可以直接繼承Fl_Widget 類(lèi),也可以繼承任何Fl_Widget類(lèi)的子類(lèi)。Fl_Widget只有四個(gè)虛擬函數,子類(lèi)必須重載所有的或部分的這些函數。
構造函數應該有以下參數
MyClass(int x, int y, int w, int h, const char *label = 0);
這就允許該類(lèi)能很好的應用于FLUID中
這個(gè)構造函數必須調用基類(lèi)的構造函數并傳遞相同的參數
MyClass::MyClass(int x, int y, int w, int h, const char *label): Fl_Widget(x, y, w, h, label) {// do initialization stuff...}Fl_Widget的保護構造函數通過(guò)傳遞的參數x,y,w,h,label分別設置x(),y(),w(),h()和label()并初始化其他的屬性如:
type(0);
box(FL_NO_BOX);
color(FL_BACKGROUND_COLOR);
selection_color(FL_BACKGROUND_COLOR);
labeltype(FL_NORMAL_LABEL);
labelstyle(FL_NORMAL_STYLE);
labelsize(FL_NORMAL_SIZE);
labelcolor(FL_FOREGROUND_COLOR);
align(FL_ALIGN_CENTER);
callback(default_callback,0);
flags(ACTIVE|VISIBLE);
image(0);
deimage(0);
以下的成員函數是Fl_Widget提供給子類(lèi)的:
Fl_Widget::clear_visible
Fl_Widget::damage
Fl_Widget::draw_box
Fl_Widget::draw_focus
Fl_Widget::draw_label
Fl_Widget::set_flag
Fl_Widget::set_visible
Fl_Widget::test_shortcut
Fl_Widget::type
第一個(gè)函數是指對象的部分需要更新。參數mask中的位設置傳遞給damage().draw()函數能根據該值得到哪些需要重畫(huà)。公共成員函數Fl_Widget::redraw()只是簡(jiǎn)單的做Fl_Widget::damage(FL_DAMAGE_ALL),即所有的都重畫(huà),但是你的控件真正執行的時(shí)候會(huì )調用私有成員函數damage(n).
第二個(gè)函數指某個(gè)區域無(wú)效,需要重畫(huà)。
第三個(gè)函數返回所有damage(n)的調用所產(chǎn)生的位。
當重新畫(huà)一個(gè)控件時(shí),你應該先看看無(wú)效位,再決定你的控件的哪部分需要重新畫(huà)。Handle()函數能夠設置單獨的無(wú)效位限制需要重畫(huà)的數量。
MyClass::handle(int event) {
...
if (change_to_part1) damage(1);
if (change_to_part2) damage(2);
if (change_to_part3) damage(4);
}
MyClass::draw() {
if (damage() & FL_DAMAGE_ALL) {
... draw frame/box and other static stuff ...
}
if (damage() & (FL_DAMAGE_ALL | 1)) draw_part1();
if (damage() & (FL_DAMAGE_ALL | 2)) draw_part2();
if (damage() & (FL_DAMAGE_ALL | 4)) draw_part3();
}
void Fl_Widget::draw_box() const
第一個(gè)函數根據該控件的尺度畫(huà)他的box().第二個(gè)函數根據box的類(lèi)型b ,顏色c畫(huà)box.
在一個(gè)空間的限制box中畫(huà)出焦點(diǎn)筐。第二個(gè)函數允許指定另一個(gè)不同box來(lái)畫(huà)焦點(diǎn)
Fl_Widget::draw_label() const
void Fl_Widget::draw_label(int x, int y, int w, int h) const
void Fl_Widget::draw_label(int x, int y, int w, int h, Fl_Align align) const
Draw()函數調用該函數來(lái)畫(huà)一個(gè)控件的label,如果標簽出了該控件的box 范圍,將不會(huì )被畫(huà)出。
第二種形式自定義一個(gè)box來(lái)畫(huà)標簽,比如用于移動(dòng)的滑塊
第三種形式可以將標簽畫(huà)在任意的地方
與Fl_Widget::show() Fl_Widget::hide()作用相同,但不發(fā)送FL_SHOW,FL_HIDE事件。
返回一個(gè)8位的標示符,用于與Forms兼容,你也可以同于其他任何目的,設置的值應該小于100,以免與系統的保留值沖突
虛擬函數int handle(int event)被用來(lái)處理任何發(fā)送給控件的事件.他能:
改變控件的狀態(tài)
調用Fl_Widget::redraw()如果該控件需要重新顯示
調用Fl_Widget::damage(n)當控件需要部分更新時(shí)(假如你在Fl_Widget::draw()函數中提供了對該函數的支持)
調用Fl_Widget::do_callback()如果一個(gè)回調函數產(chǎn)生時(shí).
調用Fl_Widget::handle()對子控件
事件用一個(gè)整數來(lái)標識.最近事件產(chǎn)生的其他消息靜態(tài)存儲在本地,調用Fl::event_*()可以得到.
以下是一個(gè)利用handle()處理事件的例子,該控件的行為類(lèi)似按鈕同時(shí)接收x按鍵并調用回調函數
int MyClass::handle(int event) {
switch(event) {
case FL_PUSH:
highlight = 1;
redraw();
return 1;
case FL_DRAG: {
int t = Fl::event_inside(this);
if (t != highlight) {
highlight = t;
redraw();
}
}
return 1;
case FL_RELEASE:
if (highlight) {
highlight = 0;
redraw();
do_callback();
// never do anything after a callback, as the callback
// may delete the widget!
}
return 1;
case FL_SHORTCUT:
if (Fl::event_key() == 'x') {
do_callback();
return 1;
}
return 0;
default:
return Fl_Widget::handle(event);
}
}
當你的handle()函數處理某事件后不能返回0,若是返回0,父控件將會(huì )把該事件發(fā)送給其他控件。
當FLTK需要重畫(huà)控件時(shí)將調用虛擬函數draw().只有在damage()返回非0值時(shí)調用該函數,draw()返回后,damage()被清0。Draw()應該被聲明為保護成員函數,避免在不需要寫(xiě)畫(huà)圖代碼時(shí)用到。
Damage()將包含從最后一次調用draw()后damage(n)調用產(chǎn)生的所有與或位信息,根據該信息只重畫(huà)需要重畫(huà)的位置,只有FLTK認為需要全部重畫(huà)時(shí)才打開(kāi)FL_DAMAGE_ALL位,比如收到expose事件。
resize(int x,int y,int w,int h)在控件被移動(dòng)和改變大小時(shí)被調用,這些參數分別是新位置,寬度和高度。但是x(),y(),w(),h(),還是以前的值,若要改變這些值,必須在基類(lèi)中也調用resize()函數
不需要調用redraw()函數,至少只改變x(),y()時(shí)不需要,因為一個(gè)組合控件有一套更有效的方法來(lái)畫(huà)新的位置
一個(gè)組合控件包括一個(gè)或多個(gè)子控件。制作組合控件必須繼承Fl_Group類(lèi).不繼承Fl_Group類(lèi)當然也可能可以制作一個(gè)組合控件,但是你還是要重新寫(xiě)Fl_Group類(lèi)里面的工作
子控件可能在類(lèi)里面聲明
class MyClass : public Fl_Group {
Fl_Button the_button;
Fl_Slider the_slider;
...
};
構造函數要初始化這些子控件。他們將被自動(dòng)的add()到group中。因為Fl_Group構造函數調用了begin().在構造函數中不要忘記調用end()函數
MyClass::MyClass(int x, int y, int w, int h) :
Fl_Group(x, y, w, h),
the_button(x + 5, y + 5, 100, 20),
the_slider(x, y + 50, w, 20)
{
...(you could add dynamically created child widgets here)...
end(); // don't forget to do this!
}
聯(lián)系客服