📄 scrollablemessagesbox.java
字号:
// ScrollableMessagesBox.java// Andrew Davison, ad@fivedots.coe.psu.ac.th, August 2005/* A scrollable messages box containing multiple message lines, which can be scrolled off the top of the box or scrolled down off the bottom. A message line is added by calling addMessage(). A scrollbar is drawn on the right hand side of the canvas, but it's only a picture. It doesn't support any text controls itself. The scrolling is controlled by commands or by up/down game action keys. Key repetition is supported, either through keyRepeated(), or by using a TimerTask to periodically repeat the current scroll movement.*/import javax.microedition.lcdui.*;import java.util.Timer;public class ScrollableMessagesBox extends CustomItem implements ItemCommandListener{ // offsets for writing text private static final int XOFFSET = 5; private static final int YOFFSET = 3; // timer task delay between repeating private static final int KEY_DELAY = 200; // 0.2 secs /* the factor multiplied to the number of text box lines to get the number of lines stored internally */ private static final float LINES_FACTOR = 1.5f; private Command upCmd, downCmd; private boolean upArrowShowing, downArrowShowing; /* whether the up and down arrows are showing on the scrollbar drawn on the canvas */ private int width, height; // of the scrolling box private int fontHeight; private int maxVisLines; // max no. of visible lines private String[] lines; // stores the message lines private int maxLines; // max no. of stored lines private int numLines = 0; // current number of stored lines private int firstVisLine = 0; /* index of the line that's currently visible at the top of the box */ private int msgCounter = 1; // used to number the messages // key repeating timer and task private Timer timer; private KeyRepeatTask keyRepeatTask; private boolean upKeyPressed = false; private boolean downKeyPressed = false; public ScrollableMessagesBox(String title, int w, int h) { super(title); width = w; height = h; Font f = Font.getDefaultFont(); fontHeight = f.getHeight(); maxVisLines = (height-(YOFFSET+1))/fontHeight; /* (YOFFSET+1) represents the offset from the top before the first message line is drawn and the border offset from the bottom of the customItem. */ // initialize lines storage, the lines[] array maxLines = (int)(LINES_FACTOR * maxVisLines); lines = new String[maxLines]; // create commands, but don't show them yet upCmd = new Command("Up", Command.ITEM, 1); downCmd = new Command("Down", Command.ITEM, 1); upArrowShowing = false; downArrowShowing = false; setItemCommandListener(this); setKeyRepetition(); } // end of ScrollableMessagesBox() private void setKeyRepetition() /* If key repetition is not supported then set up a timer task to trigger repeat operations. */ {/* The following code is edited out since I found on WTK2.2. Beta for Win98 that hasKeyRepeats() returned true but key repeats were not generated at run time. // decide how to offer key repetition if(hasKeyRepeats()) System.out.println("Key Repeat is supported"); else { // key repeat not supported System.out.println("Key Repeat not supported");*/ // start a timer to carry out key repeats keyRepeatTask = new KeyRepeatTask(this); timer = new Timer(); timer.schedule(keyRepeatTask, 0, KEY_DELAY);// } } // end of setKeyRepetition() private boolean hasKeyRepeats() // are key repeats supported? { return ((getInteractionModes() & KEY_REPEAT) != 0); } // --------------- accept a new message ----------------------- public void addMessage(String msg) // add a message to the text box { checkMessageSpace(); // store the message lines[numLines] = "" + msgCounter + ". " + msg; numLines++; msgCounter++; ensureLineVisibility(); // switch on down arrow if 2 or more lines have been added so far if (!downArrowShowing && (numLines > 1)) { addCommand(downCmd); downArrowShowing = true; } repaint(); } // end of addMessage() private void checkMessageSpace() /* Check if the lines[] array is full. If it is, then the oldest message (lines[0]) must be deleted. The other lines are moved up in the array, making room for the new message at the end. */ { if (numLines == maxLines) { // is lines[] full? for (int i=0; i < (maxLines-1); i++) lines[i] = lines[i+1]; // delete first line; move others up numLines--; if (firstVisLine > 0) // adjust visible line index firstVisLine--; } } // end of checkMessageSpace() private void ensureLineVisibility() /* Check if the newly entered line is visible on screen. If not then scroll the text lines up so that the new line is visible at the bottom of the screen. */ { // is the new line positioned off the bottom of the screen? int offScreenDist = numLines - (firstVisLine + maxVisLines); // System.out.println("offscreen dist: " + offScreenDist); if (offScreenDist > 0) { firstVisLine += offScreenDist; // move display down so new line is visible if (!upArrowShowing) { addCommand(upCmd); upArrowShowing = true; // can now move up } } } // end of ensureLineVisibility() // ----------------- UI methods ---------------- /* up and down text movement can be triggered by key presses or command menu items. Key repetition is supported. */ protected void keyPressed(int keyCode) { // System.out.println("keyPressed: " + keyCode); int gameAct = getGameAction(keyCode); if ((gameAct == Canvas.UP) && upArrowShowing) { textMovesDown(); upKeyPressed = true; } else if ((gameAct == Canvas.DOWN) && downArrowShowing) { textMovesUp(); downKeyPressed = true; } } // end of keyPressed() protected void keyReleased(int keyCode) { // System.out.println("keyReleased: " + keyCode); int gameAct = getGameAction(keyCode); if ((gameAct == Canvas.UP) && upKeyPressed) upKeyPressed = false; else if ((gameAct == Canvas.DOWN) && downKeyPressed) downKeyPressed = false; } // end of keyReleased() protected void keyRepeated(int keyCode) // called if key repeats are supported by CustomItem { System.out.println("keyRepeated: " + keyCode); int gameAct = getGameAction(keyCode); if ((gameAct == Canvas.UP) && upArrowShowing) textMovesDown(); else if ((gameAct == Canvas.DOWN) && downArrowShowing) textMovesUp(); } // end of keyRepeated() public void repeatTextMove() /* Called by KeyRepeatTask periodically to repeat the current text movement operation. This timer task is only switched on if automatic key repeats aren't available. */ { // System.out.println("repeatTextMove()"); if (upKeyPressed && upArrowShowing) textMovesDown(); else if (downKeyPressed && downArrowShowing) textMovesUp(); } // end of repeatTextMove() public void commandAction(Command c, Item i) // use commands to move the text { if (c == upCmd) textMovesDown(); else if (c == downCmd) textMovesUp(); } // end of CommandAction() private void textMovesDown() /* When the up command/key is pressed, then the messages should be moved _down_. This allows earlier messages to be seen. */ { if (firstVisLine > 0) { // if not already at messages start // System.out.println("textMovesDown()"); firstVisLine--; if (firstVisLine == 0) { // showing first message at top removeCommand(upCmd); // disable upward scrolling upArrowShowing = false; } if (!downArrowShowing) { addCommand(downCmd); // enable downward scrolling downArrowShowing = true; } repaint(); } } // end of textMovesDown() private void textMovesUp() /* When the down command/key is pressed, then the messages should be moved _up_. This moves newer messages up the screen. */ { if (firstVisLine < numLines-1) { // if not already at end of messages // System.out.println("textMovesUp()"); firstVisLine++; if (firstVisLine == numLines-1) { // showing last message at top removeCommand(downCmd); // disable downward scrolling downArrowShowing = false; } if (!upArrowShowing) { addCommand(upCmd); // enable upward scrolling upArrowShowing = true; } repaint(); } } // end of textMovesUp() // ------------------ painting ------------------------ protected void paint(Graphics g, int w, int h) /* The canvas is white with a black border, with a scrollbar drawn on the right. The text is drawn in lines, down the left side. */ { // a white background with a black border g.setColor(255, 255, 255); // white background g.fillRect(0, 0, w, h); g.setColor(0,0,0); // black border g.drawRect(1, 1, w-2, h-2); drawScrollBar(g, w, h); int yPos = YOFFSET; // calculate the index of the first invisible line int invisLine = firstVisLine + maxVisLines; int firstInvisLine = (numLines < invisLine) ? numLines : invisLine; // write the visible lines onto the canvas for (int i = firstVisLine; i < firstInvisLine; i++) { if (i == 0) // this line is the first saved line g.drawString("(first) " + lines[i], XOFFSET, yPos, Graphics.TOP|Graphics.LEFT); else g.drawString(lines[i], XOFFSET, yPos, Graphics.TOP|Graphics.LEFT); yPos += fontHeight; } } // end of paint() private void drawScrollBar(Graphics g, int w, int h) /* The scrollbar is a two-headed thick arrow parallel to the right hand side of the canvas. The upwards and downwards triangles change to circles when it's not possible to move the text up or down. There's a lot of magic numbers here for the coordinates and sizes, but at least the coordinates are specified relative to the width and height of the canvas (w and h). */ { // grey vertical bar g.setColor(128,128,128); // grey g.fillRect(w-14, 13, 6, h-26); g.setColor(0,0,0); // black // upwards head of the bar if (!upArrowShowing) { g.setColor(128,128,128); // grey g.fillArc(w-17, 7, 12, 12, 0, 360); // filled circle g.setColor(0,0,0); // black } else g.fillTriangle(w-11,6, w-6,18, w-16,18); // downwards head of the bar if (!downArrowShowing) { g.setColor(128,128,128); // grey g.fillArc(w-17, h-19, 12, 12, 0, 360); // filled circle g.setColor(0,0,0); // black } else g.fillTriangle(w-11,h-6, w-6,h-18, w-16,h-18); } // end of drawScrollBar() // ----------- dimension methods --------------------- protected int getMinContentHeight() { return height; } protected int getMinContentWidth() { return width; } protected int getPrefContentHeight(int w) { return height; } protected int getPrefContentWidth(int h) { return width; }} // end of ScrollableMessagesBox class
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -