The Canvas class is a base class for writing
only.
applications that need to
handle low-level events and to issue graphics calls for drawing to the
display. Game applications will likely make heavy use of the
Canvas class.
From an application development perspective, the Canvas class is
interchangeable with standard Screen classes, so an
application may mix and
match Canvas with high-level screens as needed. For
example, a List screen
may be used to select the track for a racing game, and a
Canvas subclass
would implement the actual game.
The Canvas provides the developer with methods to
handle game actions,
key events, and
pointer events (if supported by the device). Methods are
also provided to identify the device's capabilities and mapping of
keys to game actions.
The key events are reported with respect to key codes, which
are directly bound to concrete keys on the device, use of which may hinder
portability. Portable applications should use game actions instead of key
codes.
Like other subclasses of Displayable , the
Canvas class allows the
application to register a listener for commands. Unlike other
Displayables ,
however, the Canvas class requires applications to
subclass it in order to
use it. The paint() method is declared
abstract , and so the
application must provide an implementation in its subclass. Other
event-reporting methods are not declared abstract, and their
default implementations are empty (that is, they do nothing). This allows
the application to override only the methods that report events in which the
application has interest.
This is in contrast to the {@link Screen Screen} classes, which allow
the application to define listeners and to register them with instances of
the Screen classes. This style is not used for the
Canvas class, because
several new listener interfaces would need to be created, one for each kind
of event that might be delivered. An alternative would be to have fewer
listener interfaces, but this would require listeners to filter out events
in which they had no interest.
Key Events
Applications receive keystroke events in which the individual keys are
named within a space of key codes. Every key for which events are
reported to MIDP applications is assigned a key code.
The key code values are unique for each hardware key unless two keys are
obvious synonyms for each other.
MIDP defines the following key codes:
{@link #KEY_NUM0 KEY_NUM0},
{@link #KEY_NUM1 KEY_NUM1},
{@link #KEY_NUM2 KEY_NUM2},
{@link #KEY_NUM3 KEY_NUM3},
{@link #KEY_NUM4 KEY_NUM4},
{@link #KEY_NUM5 KEY_NUM5},
{@link #KEY_NUM6 KEY_NUM6},
{@link #KEY_NUM7 KEY_NUM7},
{@link #KEY_NUM8 KEY_NUM8},
{@link #KEY_NUM9 KEY_NUM9},
{@link #KEY_STAR KEY_STAR}, and
{@link #KEY_POUND KEY_POUND}.
(These key codes correspond to keys on a ITU-T standard telephone keypad.)
Other keys may be present on the keyboard, and they will generally have key
codes distinct from those list above. In order to guarantee portability,
applications should use only the standard key codes.
The standard key codes' values are equal to the Unicode encoding for the
character that represents the key. If the device includes any other keys
that have an obvious correspondence to a Unicode character, their key code
values should equal the Unicode encoding for that character. For keys that
have no corresponding Unicode character, the implementation must use
negative values. Zero is defined to be an invalid key code. It is thus
possible for an application to convert a keyCode into a Unicode character
using the following code:
if (keyCode > 0) {
char ch = (char)keyCode;
// ...
}
|
This technique is useful only in certain limited cases. In particular,
it is not sufficient for full textual input, because it does not handle
upper and lower case, keyboard shift states, and characters that require
more than one keystroke to enter. For textual input, applications should
always use {@link TextBox TextBox} or {@link TextField TextField}
objects.
It is sometimes useful to find the name of a key in order to
display a message about this key. In this case the application may use the
{@link #getKeyName(int) getKeyName()} method to find a key's name.
Game Actions
Portable applications that need arrow key events and gaming-related events
should use game actions in preference to key codes and key names.
MIDP defines the following game actions:
{@link #UP UP},
{@link #DOWN DOWN},
{@link #LEFT LEFT},
{@link #RIGHT RIGHT},
{@link #FIRE FIRE},
{@link #GAME_A GAME_A},
{@link #GAME_B GAME_B},
{@link #GAME_C GAME_C}, and
{@link #GAME_D GAME_D}.
Each key code may be mapped to at most one game action. However, a game
action may be associated with more than one key code. The application can
translate a key code into a game action using the {@link #getGameAction(int)
getGameAction(int keyCode)} method, and it can translate a game action into
a key code using the {@link #getKeyCode(int) getKeyCode(int gameAction)}
method. There may be multiple keycodes associated with a particular game
action, but getKeyCode returns only one of them. Supposing
that g is a valid game action and k
is a valid key code for a key associated with a game action, consider
the following expressions:
g == getGameAction(getKeyCode(g)) // (1)
k == getKeyCode(getGameAction(k)) // (2)
|
Expression (1) is always true. However, expression (2)
might be true but is not necessarily true.
The implementation is not allowed to change the mapping of game
actions and key codes during execution of the application.
Portable applications that are interested in using game actions should
translate every key event into a game action by calling the {@link
#getGameAction getGameAction()} method and then testing the result. For
example, on some devices the game actions UP ,
DOWN , LEFT and RIGHT may be
mapped to 4-way navigation arrow keys. In this case,
getKeyCode(UP) would
return a device-dependent code for the up-arrow key. On other devices, a
possible mapping would be on the number keys 2 ,
4 , 6 and 8 . In this case,
getKeyCode(UP) would return KEY_NUM2 . In
both cases, the getGameAction()
method would return the LEFT game action when the user
presses the key that
is a "natural left" on her device.
Commands
It is also possible for the user to issue {@link Command commands} when
a canvas is current. Commands are mapped to keys and menus in a
device-specific fashion. For some devices the keys used for commands may
overlap with the keys that will deliver key code events to the canvas. If
this is the case, the device will provide a means transparent to the
application that enables the user to select a mode that determines whether
these keys will deliver commands or key code events to the application.
When the Canvas is in normal mode (see below),
the set of key code events available to a canvas will not change depending
upon the number of commands present or the presence of a command listener.
When the Canvas is in full-screen mode, if there is no
command listener
present, the device may choose to deliver key code events for keys that
would otherwise be reserved for delivery of commands. Game developers
should be aware that access to commands will vary greatly across devices,
and that requiring the user to issue commands during game play may have a
great impact on the ease with which the game can be played.
Event Delivery
The Canvas object defines several methods that are
called by the
implementation. These methods are primarily for the purpose of delivering
events to the application, and so they are referred to as
event delivery methods. The set of methods is:
-
showNotify()
-
hideNotify()
-
keyPressed()
-
keyRepeated()
-
keyReleased()
-
pointerPressed()
-
pointerDragged()
-
pointerReleased()
-
paint()
These methods are all called serially. That is, the implementation will
never call an event delivery method before a prior call to any of
the event delivery methods has returned. The
serviceRepaints() method is an exception to this rule, as it
blocks until paint() is called and returns. This will occur
even if the application is in the midst of one of the event delivery
methods when it calls serviceRepaints() .
The {@link Display#callSerially Display.callSerially()} method can be
used to serialize some application-defined work with the event stream.
For further information, see the
Event Handling and
Concurrency
sections of the package summary.
The key-related, pointer-related, and paint() methods
will only be called while the Canvas is actually
visible on the output
device. These methods will therefore only be called on this
Canvas object
only after a call to showNotify() and before a call to
hideNotify() . After
hideNotify() has been called, none of the key,
pointer, and paint
methods will be called until after a
subsequent call to
showNotify() has returned. A call to a
run() method resulting from
callSerially() may occur irrespective of calls to
showNotify() and
hideNotify() .
The {@link #showNotify() showNotify()} method is called prior to the
Canvas actually being made visible on the display, and
the {@link
#hideNotify() hideNotify()} method is called after the
Canvas has been
removed from the display. The visibility state of a
Canvas (or any other
Displayable object) may be queried through the use of the {@link
Displayable#isShown() Displayable.isShown()} method. The change in
visibility state of a Canvas may be caused by the
application management
software moving MIDlets between foreground and
background states, or by the
system obscuring the Canvas with system screens.
Thus, the calls to
showNotify() and hideNotify() are not
under the control of the MIDlet and
may occur fairly frequently. Application developers are encouraged to
perform expensive setup and teardown tasks outside the
showNotify() and
hideNotify() methods in order to make them as
lightweight as possible.
A Canvas can be in normal mode or in full-screen
mode. In normal mode,
space on the display may be occupied by command labels, a title, and a
ticker. By setting a Canvas into full-screen mode,
the application is
requesting that the Canvas occupy as much of the
display space as is
possible. In full-screen mode, the title and ticker are not displayed even
if they are present on the Canvas , and
Commands may be presented using some
alternative means (such as through a pop-up menu). Note that the
implementation may still consume a portion of the display for things like
status indicators, even if the displayed Canvas is in
full-screen mode. In
full-screen mode, although the title is not displayed, its text may still
be used for other purposes, such as for the title of a pop-up menu of
Commands .
Canvas objects are in normal mode by default. The normal vs.
full-screen mode setting is controlled through the use of the {@link
#setFullScreenMode} method.
Calling {@link #setFullScreenMode} may result in
{@link #sizeChanged(int, int) sizeChanged()} being called.
The default implementation of this method does nothing.
The application can override this method to handle changes
in size of available drawing area.
Note: As mentioned in the "Specification
Requirements" section
of the overview, implementations must provide the user with an indication
of network usage. If the indicator is rendered on screen,
it must be visible when network activity occurs, even when
the Canvas is in full-screen mode. |