X

NV5 Geospatial Blog

Each month, NV5 Geospatial posts new blog content across a variety of categories. Browse our latest posts below to learn about important geospatial information or use the search bar to find a specific topic or author. Stay informed of the latest blog posts, events, and technologies by joining our email list!



9010 Rate this article:
No rating

Managing a Graphical User Interface within an Object

Anonym

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

;-

pro myobject_event , sEvent

compile_opt idl2, 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

;-

pro myobject_notifyrealize , tlb

compile_opt idl2, 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.

;-

pro myobject :: Cleanup

compile_opt idl2, logical_predicate

self-> Destruct

end

 

;------------------------------------------------------------------------------

;+

; Closes (destroys) the object's GUI

;-

pro myobject ::CloseGUI

compile_opt idl2, 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) then return

self-> UpdateText ,'Closing the GUI...'

wait , 1.0

widget_control , self.tlb, /DESTROY

self.tlb= 0

end

 

;------------------------------------------------------------------------------

;+

; Constructs the Graphical User Interface

;-

pro myobject ::ConstructGUI

compile_opt idl2, logical_predicate

if widget_info (self. tlb , /VALID_ID) then begin

; 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)

;-

pro myobject ::Destruct

compile_opt idl2, 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

;-

pro myobject ::Event, sEvent

compile_opt idl2, logical_predicate

; A method is defined for each type of widget event.  Send the event to the

; correct handler.

case tag_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

;-

pro myobject ::EventButton, sEvent

compile_opt idl2, logical_predicate

case widget_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

;-

pro myobject ::EventDraw, sEvent

compile_opt idl2, logical_predicate

case sEvent.type of

0 : begin

case sEvent.press of

1 : str ='Left mouse button pressed'

2 : str ='Middle mouse button pressed'

4 : str ='Right mouse button pressed'

else :

endcase

end

1 : begin

case sEvent.release of

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) EQ 0 ) then return

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.

;-

function myobject ::GetWID, name, $

PARENT=wParent

compile_opt idl2, logical_predicate

if ( n_elements (wParent) EQ 0 ) then wParent = 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.

;-

function myobject ::Init

compile_opt idl2, logical_predicate

; Initialize any member variables here

return , 1

end

 

;------------------------------------------------------------------------------

;+

; Called by MYOBJECT_NOTIFYREALIZE after the GUI has been realized.

;-

pro myobject ::NotifyRealize

compile_opt idl2, 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

;-

pro myobject ::UpdateText, strNew

compile_opt idl2, 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.

;-

pro myobject__define

compile_opt idl2, logical_predicate

void = {myobject$

,tlb: 0L $

}

end

pro myobject_event , sEvent

compile_opt idl2, 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

;-

pro myobject_notifyrealize , tlb

compile_opt idl2, 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.

;-

pro myobject :: Cleanup

compile_opt idl2, logical_predicate

self-> Destruct

end

 

;------------------------------------------------------------------------------

;+

; Closes (destroys) the object's GUI

;-

pro myobject ::CloseGUI

compile_opt idl2, 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) then return

self-> UpdateText ,'Closing the GUI...'

wait , 1.0

widget_control , self.tlb, /DESTROY

self.tlb= 0

end

 

;------------------------------------------------------------------------------

;+

; Constructs the Graphical User Interface

;-

pro myobject ::ConstructGUI

compile_opt idl2, logical_predicate

if widget_info (self. tlb , /VALID_ID) then begin

; 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)

;-

pro myobject ::Destruct

compile_opt idl2, 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

;-

pro myobject ::Event, sEvent

compile_opt idl2, logical_predicate

; A method is defined for each type of widget event.  Send the event to the

; correct handler.

case tag_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

;-

pro myobject ::EventButton, sEvent

compile_opt idl2, logical_predicate

case widget_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

;-

pro myobject ::EventDraw, sEvent

compile_opt idl2, logical_predicate

case sEvent.type of

0 : begin

case sEvent.press of

1 : str ='Left mouse button pressed'

2 : str ='Middle mouse button pressed'

4 : str ='Right mouse button pressed'

else :

endcase

end

1 : begin

case sEvent.release of

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) EQ 0 ) then return

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.

;-

function myobject ::GetWID, name, $

PARENT=wParent

compile_opt idl2, logical_predicate

if ( n_elements (wParent) EQ 0 ) then wParent = 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.

;-

function myobject ::Init

compile_opt idl2, logical_predicate

; Initialize any member variables here

return , 1

end

 

;------------------------------------------------------------------------------

;+

; Called by MYOBJECT_NOTIFYREALIZE after the GUI has been realized.

;-

pro myobject ::NotifyRealize

compile_opt idl2, 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

;-

pro myobject ::UpdateText, strNew

compile_opt idl2, 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.

;-

pro myobject__define

compile_opt idl2, logical_predicate

void = {myobject$

,tlb: 0L $

}

end



Please login or register to post comments.
«May 2025»
SunMonTueWedThuFriSat
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567
Digital Number, Radiance, and...

Number of views (168939)

Push Broom and Whisk Broom Sensors

Number of views (150062)

The Many Band Combinations of Landsat 8

Number of views (118153)

What Type of Loop Should I Use?

Number of views (78366)

Mapping Coastal Erosion Using LiDAR

Number of views (58349)