Scripting Resources for DigitalMicrograph™

banner

Dave Mitchell's DigitalMicrograph™ Scripting Website

Home | Scripts | Examples | Functions | Recent Updates | Tutorials | Resources | Publications | Consulting | Projects | Contact & Bio |PyJEM| Search

 

Example: Adding a Key Listener to an Image
Function
An example script which shows how to add a key listener to an image, which will act upon key strokes.
Version
20130807, v1.0
Author
D. R. G. Mitchell
Acknowledgements
Dervied from Bernhard Schaffer's example code on the DMSUG
Comments

Example code which shows how to add a key listener to an imagedisplay. This is useful if you want to use keyboard-based strokes to manipulate an image. The advantage of a listener is that it does not require a continuous loop to check for keyboard strokes, as would be used with the getkey() function. GetKey() runs as a foreground thread and uses up all available CPU cycles, whereas this approach uses very little CPU time.

This example creates an image with an ROI on it. Use the arrow keys to move the ROI around and press any other key to finish.

System Requirements
Should be compatible with all recent versions of DigitalMicrograph.
Known Issues
-
Supported
Yes
Included Files
Main script file.
Source Code

// Example code which shows how to add a key listener to an imagedisplay.

// This is useful if you want to use keyboard-based strokes to manipulate

// an image. The advantage of a listener is that it does not require a

// continuous loop to check for keyboard strokes, as would be used with

// the getkey() function. GetKey() runs as a foreground thread and uses

// up all available CPU cycles, whereas this approach uses very little

// CPU time.

 

// Acknowledgements: dervied from Bernhard Schaffer's example code on the DMSUG

 

// D. R. G. Mitchell, adminnospam@dmscripting.com (remove the nospam to make this work)

// version:20130807, v1.0, www.dmscripting.com

 

// Create a key handler object to process key strokes

 

class MyKeyHandler

{

number KeyToken // the numerical id of the listener - global to the object

 

// This listener is added in the main part of the code. This initialise function

// passes in the listener's ID, so that it available within the class - it is

// declared as a Global variable within the class, so that all class methods can

// access it. It is used to identify the listener when removing it.

 

image initialise(object self, number KeyTok)

{

KeyToken=KeyTok

}

 

// Th HandleKey() method responds when a key is pressed. The object keydescription

// contains a description of the key that has been pressed. Common examples

// include: "q", "esc", "space", "left", "up" etc.

// The HandleyKey() function must return a number, even if it is being used

// solely to detect when an image is closed. A nice feature of having a key

// listener attached to an image is that if that image is closed, the listener

// object will go out of scope and its destructor function will be called. This

// can be a very handy way of knowing when a user has closed an image. To use a

// key listener in that way, all the code in the method below could be dispensed with

// and return 0 would be the only the code. That way, when ever a key was pressed, this

// method would do nothing (except return a zero). The code to respond to the closed

// image would then be in the destructor method.

// This code looks for arrow key presses and uses them to move a region of interest

// around the front-most image. If any other key is pressed, the ROI is deleted and

// the listener is removed.

 

number HandleKey(object self, imagedisplay imgdisp, object keydescription)

{

result("\nHandleKey method called\n")

number keypressed=0 // a flag which is set to 1 when any arrow key is pressed

// but is set to zero for any other key pressed

// sources the ROI on the front-most image and get its coordinates

roi theroi=imgdisp.imagedisplaygetroi(0)

number top, left, bottom, right

theroi.roigetrectangle(top, left, bottom, right)

 

// Test for key presses and move the ROI accordingly. Arrow keys set the keypressed

// variable to 1. If a value of zero is detected - this indicates that a non-arrow key has been

// pressed.

if(keydescription.MatchesKeyDescriptor( "left" ))

{

result("\nYou pressed left.")

theroi.roisetrectangle(top, left-5, bottom, right-5)

keypressed=1

}

if(keydescription.MatchesKeyDescriptor( "right" ))

{

result("\nYou pressed right.")

theroi.roisetrectangle(top, left+5, bottom, right+5)

keypressed=1

}

 

if(keydescription.MatchesKeyDescriptor( "up" ))

{

result("\nYou pressed up.")

theroi.roisetrectangle(top-5, left, bottom-5, right)

keypressed=1

 

}

if(keydescription.MatchesKeyDescriptor( "down" ))

{

result("\nYou pressed down.")

theroi.roisetrectangle(top+5, left, bottom+5, right)

keypressed=1

}

 

// any key pressed except an arrow key results in keypressed=0

// This results in the ROI being deleted and the listener being removed.

// It is important that the removal of the

// listener is done after all other operations, otherwise the

// an error will occur as the object goes out of scope when the listener is removed.

if(keypressed==0)

{

Result("\n\nKey Handler removed.")

if(roiisvalid(theroi)) imgdisp.imagedisplaydeleteroi(theroi)

imgdisp.imagedisplayremovekeyhandler(KeyToken)

}

// The KeyHandler function must return a number even if it is

// being used solely to detect when the image is closed.

return 0

}

 

 

// Constructor - does nothing here except report in the Results window

 

Mykeyhandler(object self)

{

result("\n\nKey Handler attached.")

}

 

// Destructor responds when any key except an arrow is pressed or, if the

// the image is closed (or if the ROI is deleted).

// Thiese last two attributes are useful of detecting user actions like closing

// ROIs and images

~Mykeyhandler(object self)

{

result("\nKey Handler destructed.")

}

 

}

 

 

// Wrap all the main code within a function and then call that function as a single

// line main script. This helps ensure there are no memory leaks.

 

void main()

{

// create an image containing an ROI

number xsize=512

number ysize=512

image front:=realimage("",4,xsize, ysize)

front=icol

showimage(front)

// Add a title to the image and work out the midpoint

setname(front, "Move ROI with arrow keys - any key to end")

imagedisplay frontdisp=front.imagegetimagedisplay(0)

number midx=xsize/2

number midy=ysize/2

 

// Create and add an ROI which is centred and has a sidelenth of 20 pixels

roi theroi=createroi()

theroi.roisetrectangle(midy-10, midx-10, midy+10, midx+10)

frontdisp.imagedisplayaddroi(theroi)

// Add the key handler to the image and pass the handler's numerical ID into the

// the KeyListener object

object KeyListener=alloc(MyKeyHandler)

number keyToken = frontdisp.ImageDisplayAddKeyHandler(KeyListener, "HandleKey")

KeyListener.initialise (KeyToken)

result("\n\nPress the arrow keys to move the region of interest.\n\nPress any other key to end.")

}

// Main script

 

main()