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!



Easily Share Workflows With the Analytics Repository

Easily Share Workflows With the Analytics Repository

10/27/2025

With the recent release of ENVI® 6.2 and the Analytics Repository, it’s now easier than ever to create and share image processing workflows across your organization. With that in mind, we wrote this blog to: Introduce the Analytics Repository Describe how you can use ENVI’s interactive workflows to... Read More >

Deploy, Share, Repeat: AI Meets the Analytics Repository

Deploy, Share, Repeat: AI Meets the Analytics Repository

10/13/2025

The upcoming release of ENVI® Deep Learning 4.0 makes it easier than ever to import, deploy, and share AI models, including industry-standard ONNX models, using the integrated Analytics Repository. Whether you're building deep learning models in PyTorch, TensorFlow, or using ENVI’s native model creation tools, ENVI... Read More >

Blazing a trail: SaraniaSat-led Team Shapes the Future of Space-Based Analytics

Blazing a trail: SaraniaSat-led Team Shapes the Future of Space-Based Analytics

10/13/2025

On July 24, 2025, a unique international partnership of SaraniaSat, NV5 Geospatial Software, BruhnBruhn Innovation (BBI), Netnod, and Hewlett Packard Enterprise (HPE) achieved something unprecedented: a true demonstration of cloud-native computing onboard the International Space Station (ISS) (Fig. 1). Figure 1. Hewlett... Read More >

NV5 at ESA’s Living Planet Symposium 2025

NV5 at ESA’s Living Planet Symposium 2025

9/16/2025

We recently presented three cutting-edge research posters at the ESA Living Planet Symposium 2025 in Vienna, showcasing how NV5 technology and the ENVI® Ecosystem support innovation across ocean monitoring, mineral exploration, and disaster management. Explore each topic below and access the full posters to learn... Read More >

Monitor, Measure & Mitigate: Integrated Solutions for Geohazard Risk

Monitor, Measure & Mitigate: Integrated Solutions for Geohazard Risk

9/8/2025

Geohazards such as slope instability, erosion, settlement, or seepage pose ongoing risks to critical infrastructure. Roads, railways, pipelines, and utility corridors are especially vulnerable to these natural and human-influenced processes, which can evolve silently until sudden failure occurs. Traditional ground surveys provide only periodic... Read More >

1345678910Last
«November 2025»
SunMonTueWedThuFriSat
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456
9956 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.