Managing a Graphical User Interface within an Object
10196 Rate this article:
No rating
Managing a Graphical User Interface within an Object
Anonym Thursday, May 5, 2016
In many projects an object will include a Graphical User Interface (GUI) for displaying or manipulating data. Here is an example – That can be used as a template – that demonstrates how this can be done. See the method headers and comments in the code for more information. To try it out:
Save the following code to a file named myobject__define.pro
Open an compile the file in the IDL Development Environment
Execute the following at the command prompt
a. o = obj_new('myobject')
b. o->ConstructGUI
;##############################################################################
; This example demonstrates managing a Graphical User Interface (GUI) from an
; object.
;##############################################################################
;------------------------------------------------------------------------------
;+
; The event handler called by XMANAGER. This is defined by the EVENT_PRO
; keyword to WIDGET_BASE in MYOBJECT::CONSTRUCTGUI.
;
; :Params:
; sEvent: in, required, type="structure"
; An IDL widget event structure
;-
In many projects an object will include a Graphical User Interface (GUI) for displaying or manipulating data. Here is an example – That can be used as a template – that demonstrates how this can be done. See the method headers and comments in the code for more information. To try it out:
Save the following code to a file named myobject__define.pro
Open an compile the file in the IDL Development Environment
Execute the following at the command prompt
a. o =obj_new('myobject')
b. o->ConstructGUI
;##############################################################################
; This example demonstrates managing a Graphical User Interface (GUI) from an
; object.
;##############################################################################
;------------------------------------------------------------------------------
;+
; The event handler called by XMANAGER. This is defined by the EVENT_PRO
; keyword to WIDGET_BASE in MYOBJECT::CONSTRUCTGUI.
;
; :Params:
; sEvent: in, required, type="structure"
; An IDL widget event structure
;-
promyobject_event, sEvent
compile_optidl2, logical_predicate
; Get the instance of MYOBJECT stored in the UVALUE of the top level base
widget_control, sEvent.top, GET_UVALUE=oMyObject
; Send the event structure to the object's event handler
oMyObject->Event, sEvent
end
;------------------------------------------------------------------------------
;+
; This routine will be called when the object's GUI is realized. This is
; defined by the NOTIFY_REALIZE keyword to WIDGET_BASE in
; MYOBJECT::CONSTRUCTGUI.
;
; :Params:
; tlb: in, required, type="long"
; The widget ID of the GUIs top level base
;-
promyobject_notifyrealize, tlb
compile_optidl2, logical_predicate
; Get the instance of MYOBJECT stored in the UVALUE of the top level base
widget_control, tlb, GET_UVALUE=oMyObject
; Call the object's NOTIFYREALIZE method
oMyObject->NotifyRealize
end
;------------------------------------------------------------------------------
;+
; Lifecycle method called when object is destroyed via OBJ_DESTROY. It simply
; calls the destruct method which handles all of the cleanup.
;-
promyobject::Cleanup
compile_optidl2, logical_predicate
self->Destruct
end
;------------------------------------------------------------------------------
;+
; Closes (destroys) the object's GUI
;-
promyobject::CloseGUI
compile_optidl2, logical_predicate
; If the object's top level base ID is not a valid widget ID then do nothing
if~widget_info(self.tlb, /VALID_ID)thenreturn
self->UpdateText,'Closing the GUI...'
wait,1.0
widget_control, self.tlb, /DESTROY
self.tlb=0
end
;------------------------------------------------------------------------------
;+
; Constructs the Graphical User Interface
;-
promyobject::ConstructGUI
compile_optidl2, logical_predicate
ifwidget_info(self.tlb, /VALID_ID)thenbegin
; The object's top level base ID is valid. Do not construct another GUI.
return
endif
self.tlb=widget_base(/COLUMN, $
; This keyword defines the name of the event handler that XMANAGER will use
EVENT_PRO='myobject_event', $
; This keyword defines the name of the routine to be called when the GUI is
; realized
NOTIFY_REALIZE='myobject_notifyrealize', $
TITLE="My Object's GUI", $
TLB_FRAME_ATTR=1, $; Do not allow the GUI to be resized
/TLB_KILL_REQUEST_EVENTS)
xSize =300
wDraw =widget_draw (self.tlb, /BUTTON_EVENTS, /MOTION_EVENTS, $
XSIZE=xSize, YSIZE=200)
wText =widget_text (self.tlb, SCR_XSIZE=xSize, /SCROLL, UNAME= 'text', $
YSIZE=10)
wBase =widget_base(self.tlb, /ALIGN_RIGHT, /ROW)
wButton =widget_button(wBase, UNAME='ok', VALUE='OK')
wButton =widget_button(wBase, UNAME='close', VALUE='Close')
ss =get_screen_size()
wGeom =widget_info(self.tlb, /GEOMETRY)
widget_control, self.tlb, XOFFSET=(ss[0]-wGeom.scr_xSize)/2, $
YOFFSET=(ss[1]-wGeom.scr_ySize)/2
; Set the UVALUE of the top level base to the instance of the object. This
; way, we can access the object in the event handler and send the event into
; an object method
widget_control, self.tlb, SET_UVALUE=self
widget_control, self.tlb, /REALIZE
end
;------------------------------------------------------------------------------
;+
; This method is for cleaning up when the object is destroyed (e.g. Clean up
; heap variables)
;-
promyobject::Destruct
compile_optidl2, logical_predicate
self->CloseGUI
end
;------------------------------------------------------------------------------
;+
; The main event handler method for the object. This will be called in
; MYOBJECT_EVENT.
;
; :Params:
; sEvent: in, required, type="structure"
; An IDL widget event structure
;-
promyobject::Event, sEvent
compile_optidl2, logical_predicate
; A method is defined for each type of widget event. Send the event to the
; correct handler.
casetag_names(sEvent, /STRUCTURE_NAME)of
'WIDGET_BUTTON': self->EventButton, sEvent
'WIDGET_DRAW': self->EventDraw, sEvent
'WIDGET_KILL_REQUEST':begin
self->UpdateText,'[X] was pressed'
self->CloseGUI
end
else:help, sEvent
endcase
end
;------------------------------------------------------------------------------
;+
; This method handles button widget events
;
; :Params:
; sEvent: in, required, type="structure"
; An IDL {WIDGET_BUTTON} structure
;-
promyobject::EventButton, sEvent
compile_optidl2, logical_predicate
casewidget_info(sEvent.id, /UNAME)of
'close':begin
self->UpdateText,'Close button pressed'
self->CloseGUI
end
'ok': self->UpdateText,'OK button pressed'
else:
endcase
end
;------------------------------------------------------------------------------
;+
; This method handles draw widget events.
;
; :Params:
; sEvent: in, required, type="structure"
; An IDL {WIDGET_DRAW} structure
;-
promyobject::EventDraw, sEvent
compile_optidl2, logical_predicate
casesEvent.typeof
0:begin
casesEvent.pressof
1: str ='Left mouse button pressed'
2: str ='Middle mouse button pressed'
4: str ='Right mouse button pressed'
else:
endcase
end
1:begin
casesEvent.releaseof
1: str ='Left mouse button released'
2: str ='Middle mouse button released'
4: str ='Right mouse button released'
else:
endcase
end
2: str ='Mouse motion'
else:
endcase
if(n_elements(str)EQ0)thenreturn
str+=' ['+strtrim(sEvent.x,2)+','+strtrim(sEvent.y,2)+']'
self->UpdateText, str
end
;------------------------------------------------------------------------------
;+
; This method is for accessing widget IDs
;
; :Returns:
; The widget ID if a valid NAME (uname) is input and 0 otherwisee
;
; :Params:
; name: in, required, type="string"
; The uName of the widget whose ID is to be returned
;
; :Keywords:
; PARENT: in, optional, type="integer"
; The widget ID of the parent widget whose children are to be searched. If
; not set the GUI's top level base will be used.
;-
functionmyobject::GetWID, name, $
PARENT=wParent
compile_optidl2, logical_predicate
if(n_elements(wParent)EQ0)thenwParent = self.tlb
return,widget_info(wParent, FIND_BY_UNAME=name)
end
;------------------------------------------------------------------------------
;+
; Lifecycle method for initializing an instance of the object
;
; :Returns:
; 1 if the object initializes successfully and 0 otherwise.
;-
functionmyobject::Init
compile_optidl2, logical_predicate
; Initialize any member variables here
return,1
end
;------------------------------------------------------------------------------
;+
; Called by MYOBJECT_NOTIFYREALIZE after the GUI has been realized.
;-
promyobject::NotifyRealize
compile_optidl2, logical_predicate
; Start the event handler
xmanager,'myobject', self.tlb
end
;------------------------------------------------------------------------------
;+
; The method adds a string or an array of strings to the text widget
;
; :Params:
; strNew: in, required, type="string"
; The string(s) to be added to the text widget
;-
promyobject::UpdateText, strNew
compile_optidl2, logical_predicate
wText = self->GetWID('text')
ySize = (widget_info(wText, /GEOMETRY)).ySize
widget_control,wText, /APPEND, SET_VALUE=strNew
widget_control,wText, GET_VALUE=str
widget_control,wText, SET_TEXT_TOP_LINE=(n_elements(str)-ySize+2)>0
end
;------------------------------------------------------------------------------
;+
; Class structure definition
;
; :Fields:
; tlb: The widget ID of the GUI's top level base. This can be used to access
; all widgets in the GUI.
;-
promyobject__define
compile_optidl2, logical_predicate
void = {myobject$
,tlb:0L$
}
end
promyobject_event, sEvent
compile_optidl2, logical_predicate
; Get the instance of MYOBJECT stored in the UVALUE of the top level base
widget_control, sEvent.top, GET_UVALUE=oMyObject
; Send the event structure to the object's event handler
oMyObject->Event, sEvent
end
;------------------------------------------------------------------------------
;+
; This routine will be called when the object's GUI is realized. This is
; defined by the NOTIFY_REALIZE keyword to WIDGET_BASE in
; MYOBJECT::CONSTRUCTGUI.
;
; :Params:
; tlb: in, required, type="long"
; The widget ID of the GUIs top level base
;-
promyobject_notifyrealize, tlb
compile_optidl2, logical_predicate
; Get the instance of MYOBJECT stored in the UVALUE of the top level base
widget_control, tlb, GET_UVALUE=oMyObject
; Call the object's NOTIFYREALIZE method
oMyObject->NotifyRealize
end
;------------------------------------------------------------------------------
;+
; Lifecycle method called when object is destroyed via OBJ_DESTROY. It simply
; calls the destruct method which handles all of the cleanup.
;-
promyobject::Cleanup
compile_optidl2, logical_predicate
self->Destruct
end
;------------------------------------------------------------------------------
;+
; Closes (destroys) the object's GUI
;-
promyobject::CloseGUI
compile_optidl2, logical_predicate
; If the object's top level base ID is not a valid widget ID then do nothing
if~widget_info(self.tlb, /VALID_ID)thenreturn
self->UpdateText,'Closing the GUI...'
wait,1.0
widget_control, self.tlb, /DESTROY
self.tlb=0
end
;------------------------------------------------------------------------------
;+
; Constructs the Graphical User Interface
;-
promyobject::ConstructGUI
compile_optidl2, logical_predicate
ifwidget_info(self.tlb, /VALID_ID)thenbegin
; The object's top level base ID is valid. Do not construct another GUI.
return
endif
self.tlb=widget_base(/COLUMN, $
; This keyword defines the name of the event handler that XMANAGER will use
EVENT_PRO='myobject_event', $
; This keyword defines the name of the routine to be called when the GUI is
; realized
NOTIFY_REALIZE='myobject_notifyrealize', $
TITLE="My Object's GUI", $
TLB_FRAME_ATTR=1, $; Do not allow the GUI to be resized
/TLB_KILL_REQUEST_EVENTS)
xSize =300
wDraw =widget_draw (self.tlb, /BUTTON_EVENTS, /MOTION_EVENTS, $
XSIZE=xSize, YSIZE=200)
wText =widget_text (self.tlb, SCR_XSIZE=xSize, /SCROLL, UNAME= 'text', $
YSIZE=10)
wBase =widget_base(self.tlb, /ALIGN_RIGHT, /ROW)
wButton =widget_button(wBase, UNAME='ok', VALUE='OK')
wButton =widget_button(wBase, UNAME='close', VALUE='Close')
ss =get_screen_size()
wGeom =widget_info(self.tlb, /GEOMETRY)
widget_control, self.tlb, XOFFSET=(ss[0]-wGeom.scr_xSize)/2, $
YOFFSET=(ss[1]-wGeom.scr_ySize)/2
; Set the UVALUE of the top level base to the instance of the object. This
; way, we can access the object in the event handler and send the event into
; an object method
widget_control, self.tlb, SET_UVALUE=self
widget_control, self.tlb, /REALIZE
end
;------------------------------------------------------------------------------
;+
; This method is for cleaning up when the object is destroyed (e.g. Clean up
; heap variables)
;-
promyobject::Destruct
compile_optidl2, logical_predicate
self->CloseGUI
end
;------------------------------------------------------------------------------
;+
; The main event handler method for the object. This will be called in
; MYOBJECT_EVENT.
;
; :Params:
; sEvent: in, required, type="structure"
; An IDL widget event structure
;-
promyobject::Event, sEvent
compile_optidl2, logical_predicate
; A method is defined for each type of widget event. Send the event to the
; correct handler.
casetag_names(sEvent, /STRUCTURE_NAME)of
'WIDGET_BUTTON': self->EventButton, sEvent
'WIDGET_DRAW': self->EventDraw, sEvent
'WIDGET_KILL_REQUEST':begin
self->UpdateText,'[X] was pressed'
self->CloseGUI
end
else:help, sEvent
endcase
end
;------------------------------------------------------------------------------
;+
; This method handles button widget events
;
; :Params:
; sEvent: in, required, type="structure"
; An IDL {WIDGET_BUTTON} structure
;-
promyobject::EventButton, sEvent
compile_optidl2, logical_predicate
casewidget_info(sEvent.id, /UNAME)of
'close':begin
self->UpdateText,'Close button pressed'
self->CloseGUI
end
'ok': self->UpdateText,'OK button pressed'
else:
endcase
end
;------------------------------------------------------------------------------
;+
; This method handles draw widget events.
;
; :Params:
; sEvent: in, required, type="structure"
; An IDL {WIDGET_DRAW} structure
;-
promyobject::EventDraw, sEvent
compile_optidl2, logical_predicate
casesEvent.typeof
0:begin
casesEvent.pressof
1: str ='Left mouse button pressed'
2: str ='Middle mouse button pressed'
4: str ='Right mouse button pressed'
else:
endcase
end
1:begin
casesEvent.releaseof
1: str ='Left mouse button released'
2: str ='Middle mouse button released'
4: str ='Right mouse button released'
else:
endcase
end
2: str ='Mouse motion'
else:
endcase
if(n_elements(str)EQ0)thenreturn
str+=' ['+strtrim(sEvent.x,2)+','+strtrim(sEvent.y,2)+']'
self->UpdateText, str
end
;------------------------------------------------------------------------------
;+
; This method is for accessing widget IDs
;
; :Returns:
; The widget ID if a valid NAME (uname) is input and 0 otherwisee
;
; :Params:
; name: in, required, type="string"
; The uName of the widget whose ID is to be returned
;
; :Keywords:
; PARENT: in, optional, type="integer"
; The widget ID of the parent widget whose children are to be searched. If
; not set the GUI's top level base will be used.
;-
functionmyobject::GetWID, name, $
PARENT=wParent
compile_optidl2, logical_predicate
if(n_elements(wParent)EQ0)thenwParent = self.tlb
return,widget_info(wParent, FIND_BY_UNAME=name)
end
;------------------------------------------------------------------------------
;+
; Lifecycle method for initializing an instance of the object
;
; :Returns:
; 1 if the object initializes successfully and 0 otherwise.
;-
functionmyobject::Init
compile_optidl2, logical_predicate
; Initialize any member variables here
return,1
end
;------------------------------------------------------------------------------
;+
; Called by MYOBJECT_NOTIFYREALIZE after the GUI has been realized.
;-
promyobject::NotifyRealize
compile_optidl2, logical_predicate
; Start the event handler
xmanager,'myobject', self.tlb
end
;------------------------------------------------------------------------------
;+
; The method adds a string or an array of strings to the text widget
;
; :Params:
; strNew: in, required, type="string"
; The string(s) to be added to the text widget
;-
promyobject::UpdateText, strNew
compile_optidl2, logical_predicate
wText = self->GetWID('text')
ySize = (widget_info(wText, /GEOMETRY)).ySize
widget_control,wText, /APPEND, SET_VALUE=strNew
widget_control,wText, GET_VALUE=str
widget_control,wText, SET_TEXT_TOP_LINE=(n_elements(str)-ySize+2)>0
end
;------------------------------------------------------------------------------
;+
; Class structure definition
;
; :Fields:
; tlb: The widget ID of the GUI's top level base. This can be used to access
; all widgets in the GUI.
;-
promyobject__define
compile_optidl2, logical_predicate
void = {myobject$
,tlb:0L$
}
end
Informing Real-Time Operations with SmartCam Augmented Reality Getting creative with ENVI + IDL