Let me give an example. This code works within a manager:
protected boolean navigationMovement(int dx, int dy, int status, int time) {
int focusIndex = getFieldWithFocusIndex();
while (dy > 0) {
if (focusIndex + columnwidth.length >= getFieldCount()) {
return false;
} else {
Field f = getField(focusIndex + columnwidth.length);
if (f.isFocusable()) {
f.setFocus();
dy--;
}
}
}
while (dy < 0) {
if (focusIndex - columnwidth.length < 0) {
return false;
} else {
Field f = getField(focusIndex - columnwidth.length);
if (f.isFocusable()) {
f.setFocus();
dy++;
}
}
}
while (dx > 0) {
focusIndex++;
if (focusIndex >= getFieldCount()) {
return false;
} else {
Field f = getField(focusIndex);
if (f.isFocusable()) {
f.setFocus();
dx--;
}
}
}
while (dx < 0) {
focusIndex--;
if (focusIndex < 0) {
return false;
} else {
Field f = getField(focusIndex);
if (f.isFocusable()) {
f.setFocus();
dx++;
}
}
}
return true;
}
Now my screen adds the 3 different managers like this.
add(new Custom_TopField(this, 0, -1, "", 1, 1));
add(new Custom_BottomField(this, 0));
add(new Custom_HeaderField(Config_GlobalFunction.latest));
all also extends Manager but when i go down, it is going left instead of going to the bottom.
I found a solution but this solution is not practical at all. I created all the class within a java class. So, the class cannot be reuse.
Related
I would like to sum up the code below to make it less and more beautiful.
I have 5 models (User, Group, Event, Member, Appearance), three shown below.
I’d like to simplify the code.
String getId(uri) {
String pathSegment;
if (uri.pathSegments.length >= 2) {
pathSegment = uri.pathSegments[1];
} else {
return null;
}
switch (resource) {
case 'users':
for (User user in models[resource]) {
if (user.id == pathSegment) {
return pathSegment;
} else {
return null;
}
}
break;
case 'groups':
for (Group group in models[resource]) {
if (group.id == pathSegment) {
return pathSegment;
} else {
return null;
}
}
break;
case 'events':
for (Event event in models[resource]) {
if (event.id == pathSegment) {
return pathSegment;
} else {
return null;
}
}
break;
default:
break;
}
return null;
}
If your User, Group, and Event have a common id, then You can simplify your code by using dynamic type. See related documentation.
String getId(uri) {
String pathSegment;
if (uri.pathSegments.length >= 2) {
pathSegment = uri.pathSegments[1];
} else {
return null;
}
return _getIdFromItems(models[resource], pathSegment);
}
String _getIdFromItems(List<dynamic> items, String pathSegment) {
for (dynamic item in items) {
if (item.id == pathSegment) {
return pathSegment;
} else {
return null;
}
}
return null;
}
I need to have a control which will wordwrap, add scrollbars, etc - but ignore the enter key and jump to the next control using tab/shift tab. I can't seem to get this right.
This is the control I have done, and it seems to just simply stay in the text area. (This was used from an old example online and it seems to work only if the textArea is in the same node as the rest).
public class TabAndEnterIgnoringTextArea extends TextArea {
final TextArea myTextArea = this;
public TabAndEnterIgnoringTextArea() {
this.setWrapText(true);
addEventFilter(KeyEvent.KEY_PRESSED, new TabAndEnterHandler());
}
private class TabAndEnterHandler implements EventHandler<KeyEvent> {
private KeyEvent recodedEvent;
#Override
public void handle(KeyEvent event) {
if (recodedEvent != null) {
recodedEvent = null;
return;
}
Parent parent = getParent();
if (parent != null) {
switch (event.getCode()) {
case ENTER:
if (event.isControlDown()) {
recodedEvent = recodeWithoutControlDown(event);
myTextArea.fireEvent(recodedEvent);
} else {
Event parentEvent = event.copyFor(parent, parent);
myTextArea.getParent().fireEvent(parentEvent);
}
event.consume();
break;
case TAB:
if (event.isControlDown()) {
recodedEvent = recodeWithoutControlDown(event);
myTextArea.fireEvent(recodedEvent);
} else if (event.isShiftDown()) {
ObservableList<Node> children = FXCollections.observableArrayList();
addAllDescendents(parent, children);
int idx = children.indexOf(myTextArea);
if (idx > 0) {
for (int i = idx - 1; i > 0; i--) {
if (children.get(i).isFocusTraversable()) {
children.get(i).requestFocus();
break;
}
}
}
} else {
ObservableList<Node> children = FXCollections.observableArrayList();
addAllDescendents(parent, children);
int idx = children.indexOf(myTextArea);
if (idx >= 0) {
for (int i = idx + 1; i < children.size(); i++) {
if (children.get(i).isFocusTraversable()) {
children.get(i).requestFocus();
break;
}
}
if (idx + 1 >= children.size()) {
for (int i = 0; i < idx; i++) {
if (children.get(i).isFocusTraversable()) {
children.get(i).requestFocus();
break;
}
}
}
}
}
event.consume();
break;
default:
break;
}
}
}
private void addAllDescendents(Parent parent, ObservableList<Node> nodes) {
for (Node node : parent.getChildrenUnmodifiable()) {
nodes.add(node);
if (node instanceof Parent)
addAllDescendents((Parent) node, nodes);
}
}
private KeyEvent recodeWithoutControlDown(KeyEvent event) {
return new KeyEvent(event.getEventType(), event.getCharacter(), event.getText(), event.getCode(),
event.isShiftDown(), false, event.isAltDown(), event.isMetaDown());
}
}
Once I land in my field, it won't leave with the keyboard. Any ideas? Also - I shouldn't assume that the next control is actually in the nodes within my parent, as the control may be part of another control where its the last control and the next one might be on the parent above.
Basically I want the next landable item in the scenegraph.
I am able to do it with internal API - but I know that is very discouraged.
public class TabAndEnterIgnoringTextArea extends TextArea {
final TextArea myTextArea = this;
public TabAndEnterIgnoringTextArea() {
addEventFilter(KeyEvent.KEY_PRESSED, new TabAndEnterHandler());
}
class TabAndEnterHandler implements EventHandler<KeyEvent> {
private KeyEvent recodedEvent;
#Override
public void handle(KeyEvent event) {
if (recodedEvent != null) {
recodedEvent = null;
return;
}
Parent parent = myTextArea.getParent();
Scene scene = parent.getScene();
while (scene == null){
parent = parent.getParent();
scene = parent.getScene();
}
SceneTraversalEngine engine = new SceneTraversalEngine(getScene());
if (parent != null) {
switch (event.getCode()) {
case ENTER:
if (event.isControlDown()) {
recodedEvent = recodeWithoutControlDown(event);
myTextArea.fireEvent(recodedEvent);
} else {
Event parentEvent = event.copyFor(parent, parent);
myTextArea.getParent().fireEvent(parentEvent);
}
event.consume();
break;
case TAB:
if(event.isShiftDown()){
engine.trav(myTextArea, Direction.PREVIOUS);
}else {
engine.trav(myTextArea, Direction.NEXT);
}
}
}
}
private KeyEvent recodeWithoutControlDown(KeyEvent event) {
return new KeyEvent(event.getEventType(), event.getCharacter(), event.getText(), event.getCode(),
event.isShiftDown(), false, event.isAltDown(), event.isMetaDown());
}
}
}
Thanks
I think I found a solution which will allow me to have this work as designed.
public class TabAndEnterIgnoringTextArea extends TextArea {
final TextArea myTextArea = this;
public TabAndEnterIgnoringTextArea() {
this.setWrapText(true);
addEventFilter(KeyEvent.KEY_PRESSED, new TabAndEnterHandler());
}
private class TabAndEnterHandler implements EventHandler<KeyEvent> {
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.TAB || event.getCode() == KeyCode.ENTER) {
event.consume();
if(event.getCode() == KeyCode.TAB){
selectNextNode(!event.isShiftDown());
}
}
}
private void selectNextNode(boolean forward){
List<Node> nodes = getAllNodes(myTextArea.getScene().getRoot());
int index = nodes.indexOf(myTextArea);
if(forward){
if(index < nodes.size() - 1) {
nodes.get(index + 1).requestFocus();
}else {
nodes.get(0).requestFocus();
}
}else {
if(index == 0) {
nodes.get(nodes.size() - 1).requestFocus();
}else {
nodes.get(index - 1).requestFocus();
}
}
}
private ArrayList<Node> getAllNodes(Parent root) {
ArrayList<Node> nodes = new ArrayList<Node>();
addAllDescendents(root, nodes);
return nodes;
}
private void addAllDescendents(Parent parent, ArrayList<Node> nodes) {
for (Node node : parent.getChildrenUnmodifiable()) {
if(node.isFocusTraversable()){
nodes.add(node);
}
if (node instanceof Parent)
addAllDescendents((Parent)node, nodes);
}
}
}
}
If you see anything wrong with this approach I would appreciate it, but it seems to work for my purposes.
This is some code that should create a oval that can be controlled via arrow keys.
I have done lots of research but I haven't been able to find a solution to my problem.
I am using Eclipse Mars with the Java language. Here is my code.
package com.game;
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Game extends Applet implements KeyListener, Runnable {
public int x,y;
public boolean up,down,left,right;
public Image offscreen;
public Graphics d;
public void init(){
setSize(854,480);
Thread th = new Thread(this);
th.start();
offscreen = createImage(854,480);
d = offscreen.getGraphics();
this.addKeyListener(new Game());
}
public void run(){
while(true)
{
System.out.println("X: " + x);
System.out.println("Y: " + y);
if(left == true){
x--;
}
if(right == true){
x++;
}
if(up == true){
y--;
}
if(down == true){
y++;
}
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void keyTyped(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
left = true;
System.out.println("Left key pressed");
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
right = true;
System.out.println("Right key pressed");
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
left = true;
System.out.println("Left key pressed");
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
right = true;
System.out.println("Left key pressed");
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
left = false;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
right = false;
}
}
public void paint (Graphics g){
d.clearRect(0, 0, 854, 480);
d.drawOval(x, y, 20, 20);
g.drawImage(offscreen, 0, 0, this);
}
public void update(Graphics g){
paint(g);
}
}
When running this code, pressing arrow keys is not doing anything.
I have made list view with checkboxes. I have read similar articles n many people have suggested to do changes in drawlistRow but it is not happening. Can u suggest me where should i change to make it a multi line list.The code snippet is :
Updated: I updated my code and it is still not working
public class CheckboxListField extends MainScreen implements ListFieldCallback, FieldChangeListener {
int mCheckBoxesCount = 5;
private Vector _listData = new Vector();
private ListField listField;
private ContactList blackBerryContactList;
private BlackBerryContact blackBerryContact;
private Vector blackBerryContacts;
private MenuItem _toggleItem;
ButtonField button;
BasicEditField mEdit;
CheckboxField cb;
CheckboxField[] chk_service;
HorizontalFieldManager hm4;
CheckboxField[] m_arrFields;
boolean mProgrammatic = false;
public static StringBuffer sbi = new StringBuffer();
VerticalFieldManager checkBoxGroup = new VerticalFieldManager();
LabelField task;
//A class to hold the Strings in the CheckBox and it's checkbox state (checked or unchecked).
private class ChecklistData
{
private String _stringVal;
private boolean _checked;
ChecklistData()
{
_stringVal = "";
_checked = false;
}
ChecklistData(String stringVal, boolean checked)
{
_stringVal = stringVal;
_checked = checked;
}
//Get/set methods.
private String getStringVal()
{
return _stringVal;
}
private boolean isChecked()
{
return _checked;
}
private void setStringVal(String stringVal)
{
_stringVal = stringVal;
}
private void setChecked(boolean checked)
{
_checked = checked;
}
//Toggle the checked status.
private void toggleChecked()
{
_checked = !_checked;
}
}
CheckboxListField()
{
_toggleItem = new MenuItem("Change Option", 200, 10)
{
public void run()
{
//Get the index of the selected row.
int index = listField.getSelectedIndex();
//Get the ChecklistData for this row.
ChecklistData data = (ChecklistData)_listData.elementAt(index);
//Toggle its status.
data.toggleChecked();
//Update the Vector with the new ChecklistData.
_listData.setElementAt(data, index);
//Invalidate the modified row of the ListField.
listField.invalidate(index);
if (index != -1 && !blackBerryContacts.isEmpty())
{
blackBerryContact =
(BlackBerryContact)blackBerryContacts.
elementAt(listField.getSelectedIndex());
ContactDetailsScreen contactDetailsScreen =
new ContactDetailsScreen(blackBerryContact);
UiApplication.getUiApplication().pushScreen(contactDetailsScreen);
}
}
};
listField = new ListField();
listField.setRowHeight(getFont().getHeight() * 2);
listField.setCallback(this);
reloadContactList();
//CheckboxField[] cb = new CheckboxField[blackBerryContacts.size()];
for(int count = 0; count < blackBerryContacts.size(); ++count)
{
BlackBerryContact item =
(BlackBerryContact)blackBerryContacts.elementAt(count);
String displayName = getDisplayName(item);
CheckboxField cb = new CheckboxField(displayName, false);
cb.setChangeListener(this);
add(cb);
listField.insert(count);
}
blackBerryContacts.addElement(cb);
add(checkBoxGroup);
}
protected void makeMenu(Menu menu, int instance)
{
menu.add(new MenuItem("Get", 2, 2) {
public void run() {
for (int i = 0; i < checkBoxGroup.getFieldCount(); i++) {
//for(int i=0; i<blackBerryContacts.size(); i++) {
CheckboxField checkboxField = (CheckboxField)checkBoxGroup
.getField(i);
if (checkboxField.getChecked()) {
sbi.append(checkboxField.getLabel()).append("\n");
}
}
Dialog.inform("Selected checkbox text::" + sbi);
}
});
super.makeMenu(menu, instance);
}
private boolean reloadContactList()
{
try {
blackBerryContactList =
(ContactList)PIM.getInstance().openPIMList
(PIM.CONTACT_LIST, PIM.READ_ONLY);
Enumeration allContacts = blackBerryContactList.items();
blackBerryContacts = enumToVector(allContacts);
listField.setSize(blackBerryContacts.size());
return true;
} catch (PIMException e)
{
return false;
}
}
//Convert the list of contacts from an Enumeration to a Vector
private Vector enumToVector(Enumeration contactEnum) {
Vector v = new Vector();
if (contactEnum == null)
return v;
while (contactEnum.hasMoreElements()) {
v.addElement(contactEnum.nextElement());
}
return v;
}
public void drawListRow(ListField list, Graphics graphics, int index, int y, int w)
{
ChecklistData currentRow = (ChecklistData)this.get(list, index);
StringBuffer rowString = new StringBuffer();
if (currentRow.isChecked())
{
rowString.append(Characters.BALLOT_BOX_WITH_CHECK);
}
else
{
rowString.append(Characters.BALLOT_BOX);
}
//Append a couple spaces and the row's text.
rowString.append(Characters.SPACE);
rowString.append(Characters.SPACE);
rowString.append(currentRow.getStringVal());
//graphics.drawText("ROW", 0, y, 0, w);
//String rowNumber = "one";
//Draw the text.
graphics.drawText(rowString.toString(), 0, y, 0, w);
/*graphics.drawText("ROW " + rowNumber, y, 0, w);
graphics.drawText("ROW NAME", y, 20, w);
graphics.drawText("row details", y + getFont().getHeight(), 20, w); */
}
public void drawRow(Graphics g, int x, int y, int width, int height) {
// Arrange the cell fields within this row manager.
layout(width, height);
// Place this row manager within its enclosing list.
setPosition(x, y);
// Apply a translating/clipping transformation to the graphics
// context so that this row paints in the right area.
g.pushRegion(getExtent());
// Paint this manager's controlled fields.
subpaint(g);
g.setColor(0x00CACACA);
g.drawLine(0, 0, getPreferredWidth(), 0);
// Restore the graphics context.
g.popContext();
}
public static String getDisplayName(Contact contact)
{
if (contact == null)
{
return null;
}
String displayName = null;
// First, see if there is a meaningful name set for the contact.
if (contact.countValues(Contact.NAME) > 0) {
final String[] name = contact.getStringArray(Contact.NAME, 0);
final String firstName = name[Contact.NAME_GIVEN];
final String lastName = name[Contact.NAME_FAMILY];
if (firstName != null && lastName != null) {
displayName = firstName + " " + lastName;
} else if (firstName != null) {
displayName = firstName;
} else if (lastName != null) {
displayName = lastName;
}
if (displayName != null) {
final String namePrefix = name[Contact.NAME_PREFIX];
if (namePrefix != null) {
displayName = namePrefix + " " + displayName;
}
return displayName;
}
}
return displayName;
}
//Returns the object at the specified index.
public Object get(ListField list, int index)
{
return _listData.elementAt(index);
/*if (listField == list)
{
//If index is out of bounds an exception will be thrown,
//but that's the behaviour we want in that case.
//return blackBerryContacts.elementAt(index);
_listData = (Vector) blackBerryContacts.elementAt(index);
return _listData.elementAt(index);
}
return null;*/
}
//Returns the first occurence of the given String, bbeginning the search at index,
//and testing for equality using the equals method.
public int indexOfList(ListField list, String p, int s)
{
//return listElements.getSelectedIndex();
//return _listData.indexOf(p, s);
return -1;
}
//Returns the screen width so the list uses the entire screen width.
public int getPreferredWidth(ListField list)
{
return Graphics.getScreenWidth();
//return Display.getWidth();
}
public void fieldChanged(Field field, int context) {
boolean mProgrammatic = false;
if (!mProgrammatic) {
mProgrammatic = true;
CheckboxField cbField = (CheckboxField) field;
int index = blackBerryContacts.indexOf(cbField);
if (cbField.getChecked())
{
for(int i=0;i<blackBerryContacts.size();i++)
{
Dialog.inform("Selected::" + cbField.getLabel());
sbi=new StringBuffer();
sbi.append(cbField.getLabel());
}
}
mProgrammatic = false;
}
}
This code may be improved with:
Using ListField instead of VerticalFieldManager + CheckboxField array (ListField is much more faster, 100+ controls may slow down UI)
Using simple array instead of vector in list data (it's faster)
Moving contacts load from UI thread (we should aware of blocking UI thread with heavy procedures like IO, networking or work with contact list)
Actually using ListField with two line rows has one issue: we have to set the same height for all rows in ListField. So there always will be two lines per row, no matter if we will use second line or not. But it's really better than UI performance issues.
See code:
public class CheckboxListField extends MainScreen implements
ListFieldCallback {
private ChecklistData[] mListData = new ChecklistData[] {};
private ListField mListField;
private Vector mContacts;
private MenuItem mMenuItemToggle = new MenuItem(
"Change Option", 0, 0) {
public void run() {
toggleItem();
};
};
private MenuItem mMenuItemGet = new MenuItem("Get", 0,
0) {
public void run() {
StringBuffer sbi = new StringBuffer();
for (int i = 0; i < mListData.length; i++) {
ChecklistData checkboxField = mListData[i];
if (checkboxField.isChecked()) {
sbi.append(checkboxField.getStringVal())
.append("\n");
}
}
Dialog.inform("Selected checkbox text::\n"
+ sbi);
}
};
// A class to hold the Strings in the CheckBox and it's checkbox state
// (checked or unchecked).
private class ChecklistData {
private String _stringVal;
private boolean _checked;
ChecklistData(String stringVal, boolean checked) {
_stringVal = stringVal;
_checked = checked;
}
// Get/set methods.
private String getStringVal() {
return _stringVal;
}
private boolean isChecked() {
return _checked;
}
// Toggle the checked status.
private void toggleChecked() {
_checked = !_checked;
}
}
CheckboxListField() {
// toggle list field item on navigation click
mListField = new ListField() {
protected boolean navigationClick(int status,
int time) {
toggleItem();
return true;
};
};
// set two line row height
mListField.setRowHeight(getFont().getHeight() * 2);
mListField.setCallback(this);
add(mListField);
// load contacts in separate thread
loadContacts.run();
}
protected Runnable loadContacts = new Runnable() {
public void run() {
reloadContactList();
// fill list field control in UI event thread
UiApplication.getUiApplication().invokeLater(
fillList);
}
};
protected Runnable fillList = new Runnable() {
public void run() {
int size = mContacts.size();
mListData = new ChecklistData[size];
for (int i = 0; i < mContacts.size(); i++) {
BlackBerryContact item = (BlackBerryContact) mContacts
.elementAt(i);
String displayName = getDisplayName(item);
mListData[i] = new ChecklistData(
displayName, false);
}
mListField.setSize(size);
}
};
protected void toggleItem() {
// Get the index of the selected row.
int index = mListField.getSelectedIndex();
if (index != -1) {
// Get the ChecklistData for this row.
ChecklistData data = mListData[index];
// Toggle its status.
data.toggleChecked();
// Invalidate the modified row of the ListField.
mListField.invalidate(index);
BlackBerryContact contact = (BlackBerryContact) mContacts
.elementAt(mListField
.getSelectedIndex());
// process selected contact here
}
}
protected void makeMenu(Menu menu, int instance) {
menu.add(mMenuItemToggle);
menu.add(mMenuItemGet);
super.makeMenu(menu, instance);
}
private boolean reloadContactList() {
try {
ContactList contactList = (ContactList) PIM
.getInstance()
.openPIMList(PIM.CONTACT_LIST,
PIM.READ_ONLY);
Enumeration allContacts = contactList.items();
mContacts = enumToVector(allContacts);
mListField.setSize(mContacts.size());
return true;
} catch (PIMException e) {
return false;
}
}
// Convert the list of contacts from an Enumeration to a Vector
private Vector enumToVector(Enumeration contactEnum) {
Vector v = new Vector();
if (contactEnum == null)
return v;
while (contactEnum.hasMoreElements()) {
v.addElement(contactEnum.nextElement());
}
return v;
}
public void drawListRow(ListField list,
Graphics graphics, int index, int y, int w) {
Object obj = this.get(list, index);
if (obj != null) {
ChecklistData currentRow = (ChecklistData) obj;
StringBuffer rowString = new StringBuffer();
if (currentRow.isChecked()) {
rowString
.append(Characters.BALLOT_BOX_WITH_CHECK);
} else {
rowString.append(Characters.BALLOT_BOX);
}
// Append a couple spaces and the row's text.
rowString.append(Characters.SPACE);
rowString.append(Characters.SPACE);
rowString.append(currentRow.getStringVal());
// Draw the text.
graphics.drawText(rowString.toString(), 0, y,
0, w);
String secondLine = "Lorem ipsum dolor sit amet, "
+ "consectetur adipiscing elit.";
graphics.drawText(secondLine, 0, y
+ getFont().getHeight(),
DrawStyle.ELLIPSIS, w);
} else {
graphics.drawText("No rows available.", 0, y,
0, w);
}
}
public static String getDisplayName(Contact contact) {
if (contact == null) {
return null;
}
String displayName = null;
// First, see if there is a meaningful name set for the contact.
if (contact.countValues(Contact.NAME) > 0) {
final String[] name = contact.getStringArray(
Contact.NAME, 0);
final String firstName = name[Contact.NAME_GIVEN];
final String lastName = name[Contact.NAME_FAMILY];
if (firstName != null && lastName != null) {
displayName = firstName + " " + lastName;
} else if (firstName != null) {
displayName = firstName;
} else if (lastName != null) {
displayName = lastName;
}
if (displayName != null) {
final String namePrefix = name[Contact.NAME_PREFIX];
if (namePrefix != null) {
displayName = namePrefix + " "
+ displayName;
}
return displayName;
}
}
return displayName;
}
// Returns the object at the specified index.
public Object get(ListField list, int index) {
Object result = null;
if (mListData.length > index) {
result = mListData[index];
}
return result;
}
// Returns the first occurrence of the given String,
// beginning the search at index, and testing for
// equality using the equals method.
public int indexOfList(ListField list, String p, int s) {
return -1;
}
// Returns the screen width so the list uses the entire screen width.
public int getPreferredWidth(ListField list) {
return Graphics.getScreenWidth();
// return Display.getWidth();
}
}
Have a nice coding!
I want to marquee some text in a BlackBerry app.
Here it is. Just make a class with name MarqueeLabel and copy-paste this code then you can use this class to display a marquee text:
package mypackage;
import java.util.Timer;
import java.util.TimerTask;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.LabelField;
class MarqueLabel extends LabelField {
int currentChar = 0;
String currentText = null;
Font ourFont;
private Timer _scrollTimer;
private TimerTask _scrollTimerTask;
public MarqueLabel(String text, long style) {
super(text, style);
}
public void paint(Graphics graphics) {
currentText = this.getText();
if (currentChar < currentText.length()) {
currentText = currentText.substring(currentChar);
}
graphics.drawText(currentText, 0, 0, DrawStyle.ELLIPSIS, Display.getWidth());
super.paint(graphics);
}
public void layout(int width, int height) {
ourFont = this.getFont();
setExtent(500, ourFont.getHeight());
}
protected void onDisplay() {
startScroll();
}
protected void onUnfocus() {
startScroll();
}
private void startScroll() {
// Start scrolling
final String fullText = this.getText();
if (_scrollTimer == null) {
_scrollTimer = new Timer();
_scrollTimerTask = new TimerTask() {
public void run() {
currentChar = currentChar + 2;
if (currentChar > fullText.length()) {
currentChar = 0;
}
invalidate();
}
};
_scrollTimer.scheduleAtFixedRate(_scrollTimerTask, 0, 450);
}
}
protected void onFocus(int direction) {
if (_scrollTimer != null) {
_scrollTimerTask.cancel();
_scrollTimer.cancel();
_scrollTimer = null;
_scrollTimerTask = null;
}
}
protected boolean navigationMovement(int dx, int dy,
int status, int time) {
currentText = this.getText();
int oldCurrentChar = currentChar;
if (Math.abs(dx) > Math.abs(dy)) {
if (dx > 0) {
currentChar = Math.min(currentText.length() - 1,
currentChar + 1);
} else if (dx < 0) {
currentChar = Math.max(0, currentChar - 1);
}
if (oldCurrentChar != currentChar) {
this.invalidate();
}
return true;
} else {
return super.navigationMovement(dx, dy, status, time);
}
}
}