跳转至

Managing a Graphical User Interface within an Object

原文链接: https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/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