How to rotate a circle with text on canvas in Blackberry

How to Rotate a circle with text on TouchEvent or on TrackBallMoveEvent.

  • How to create such a circle?

    I created a circle and rotated it, but it always starts at 0 degrees.

  • Is there any other way to create such a circle?

Each circle has a different text, and each of the circles can move independently .

enter image description here

+6
source share
1 answer

So this is definitely not complete, but I think this is a big part of what you need.

Limitations / Assumptions

  • So far, I have implemented only touch processing, since I find it harder. If I get time later, I will come back and add a trackball .
  • I did not give any momentum to the spinning discs. After the user finger leaves the disk, it will stop rotating.
  • I'm not sure if the transitions between the drives are 100% right. You will need to do some testing. At least they are right.
  • When you mentioned Canvas in the title, I assumed that this does not mean that you need to use J2ME Canvas . Writing BlackBerry applications with RIM interface libraries is pretty much everything I've done.

Decision

Essentially, I created a subclass of Field to represent each drive. You create a field by passing an array of labels to fit around the perimeter, radius, and color. The hardcoded in each DiscField is an insert for text for text, which implies a certain size difference between the disks. You should probably make this more dynamic.

 public class DiscField extends Field { /** Used to map Manager TouchEvents into our coordinate system */ private int _offset = 0; private int _radius; private int _fillColor; private double _currentRotation = 0.0; private double _lastTouchAngle = 0.0; private boolean _rotating = false; private String[] _labels; /** Text inset from outer disc edge */ private static final int INSET = 30; private DiscField() { } public DiscField(String[] labels, int radius, int fillColor) { super(Field.FOCUSABLE); _labels = labels; _radius = radius; _fillColor = fillColor; } protected void layout(int width, int height) { setExtent(Math.min(width, getPreferredWidth()), Math.min(height, getPreferredHeight())); } private void drawFilledCircle(Graphics g, int x, int y, int r) { // http://stackoverflow.com/a/1186851/119114 g.fillEllipse(x, y, x + r, y, x, y + r, 0, 360); } private void drawCircle(Graphics g, int x, int y, int r) { g.drawEllipse(x, y, x + r, y, x, y + r, 0, 360); } protected void paint(Graphics graphics) { int oldColor = graphics.getColor(); graphics.setColor(_fillColor); drawFilledCircle(graphics, _radius, _radius, _radius); graphics.setColor(Color.WHITE); drawCircle(graphics, _radius, _radius, _radius); // plot the text around the circle, inset by some 'padding' value int textColor = (_fillColor == Color.WHITE) ? Color.BLACK : Color.WHITE; graphics.setColor(textColor); // equally space the labels around the disc double interval = (2.0 * Math.PI / _labels.length); for (int i = 0; i < _labels.length; i++) { // account for font size when plotting text int fontOffsetX = getFont().getAdvance(_labels[i]) / 2; int fontOffsetY = getFont().getHeight() / 2; int x = _radius + (int) ((_radius - INSET) * Math.cos(i * interval - _currentRotation)) - fontOffsetX; int y = _radius - (int) ((_radius - INSET) * Math.sin(i * interval - _currentRotation)) - fontOffsetY; graphics.drawText(_labels[i], x, y); } graphics.setColor(oldColor); } protected void drawFocus(Graphics graphics, boolean on) { if (on) { int oldColor = graphics.getColor(); int oldAlpha = graphics.getGlobalAlpha(); // just draw a white shine to indicate focus graphics.setColor(Color.WHITE); graphics.setGlobalAlpha(80); drawFilledCircle(graphics, _radius, _radius, _radius); // reset graphics context graphics.setColor(oldColor); graphics.setGlobalAlpha(oldAlpha); } } protected void onUnfocus() { super.onUnfocus(); _rotating = false; } protected boolean touchEvent(TouchEvent event) { switch (event.getEvent()) { case TouchEvent.MOVE: { setFocus(); // Get the touch location, within this Field int x = event.getX(1) - _offset - _radius; int y = event.getY(1) - _offset - _radius; if (x * x + y * y <= _radius * _radius) { double angle = MathUtilities.atan2(y, x); if (_rotating) { // _lastTouchAngle only valid if _rotating _currentRotation += angle - _lastTouchAngle; // force a redraw (paint) with the new rotation angle invalidate(); } else { _rotating = true; } _lastTouchAngle = angle; return true; } } case TouchEvent.UNCLICK: case TouchEvent.UP: { _rotating = false; return true; } case TouchEvent.DOWN: { setFocus(); int x = event.getX(1) - _offset - _radius; int y = event.getY(1) - _offset - _radius; if (x * x + y * y <= _radius * _radius) { _lastTouchAngle = MathUtilities.atan2(y, x); _rotating = true; return true; } } default: break; } return super.touchEvent(event); } protected boolean trackwheelRoll(int arg0, int arg1, int arg2) { return super.trackwheelRoll(arg0, arg1, arg2); // TODO! } public int getPreferredHeight() { return getPreferredWidth(); } public int getPreferredWidth() { return 2 * _radius; } public String[] getLabels() { return _labels; } public void setLabels(String[] labels) { this._labels = labels; } public int getRadius() { return _radius; } public void setRadius(int radius) { this._radius = radius; } public double getCurrentAngle() { return _currentRotation; } public void setCurrentAngle(double angle) { this._currentRotation = angle; } public int getOffset() { return _offset; } public void setOffset(int offset) { this._offset = offset; } } 

Contains all DiscField objects - this is DiscManager . It aligns the DiscFields in sublayout() and handles the proper delegation of touch events ... since the fields overlap and touch within the DiscField , which is also not included in its radius (i.e. angles), must be processed by a large disk.

  /** * A DiscManager is a container for DiscFields and manages proper delegation * of touch event handling. */ private class DiscManager extends Manager { private int _maxRadius = 0; public DiscManager(long style){ super(style); DiscField outerDisc = new DiscField(new String[] { "1", "2", "3", "4", "5", "6" }, 180, Color.BLUE); _maxRadius = outerDisc.getRadius(); DiscField middleDisc = new DiscField(new String[] { "1", "2", "3", "4", "5" }, 120, Color.GRAY); middleDisc.setOffset(_maxRadius - middleDisc.getRadius()); DiscField innerDisc = new DiscField(new String[] { "1", "2", "3", "4" }, 60, Color.RED); innerDisc.setOffset(_maxRadius - innerDisc.getRadius()); // order matters here: add(outerDisc); add(middleDisc); add(innerDisc); } protected void sublayout(int width, int height) { setExtent(2 * _maxRadius, 2 * _maxRadius); // each disc needs to have the same x,y center to be concentric for (int i = 0; i < getFieldCount(); i++) { if (getField(i) instanceof DiscField) { DiscField disc = (DiscField) getField(i); int xCenter = _maxRadius - disc.getRadius(); int yCenter = _maxRadius - disc.getRadius(); setPositionChild(disc, xCenter, yCenter); layoutChild(disc, 2 * _maxRadius, 2 * _maxRadius); } } } protected boolean touchEvent(TouchEvent event) { int eventCode = event.getEvent(); // Get the touch location, within this Manager int x = event.getX(1); int y = event.getY(1); if ((x >= 0) && (y >= 0) && (x < getWidth()) && (y < getHeight())) { int field = getFieldAtLocation(x, y); if (field >= 0) { DiscField df = null; for (int i = 0; i < getFieldCount(); i++) { if (getField(field) instanceof DiscField) { int r = ((DiscField)getField(field)).getRadius(); // (_maxRadius, _maxRadius) is the center of all discs if ((x - _maxRadius) * (x - _maxRadius) + (y - _maxRadius) * (y - _maxRadius) <= r * r) { df = (DiscField)getField(field); } else { // touch was not within this disc radius, so the one slightly bigger // should be passed this touch event break; } } } // Let event propagate to child field return (df != null) ? df.touchEvent(event) : super.touchEvent(event); } else { if (eventCode == TouchEvent.DOWN) { setFocus(); } // Consume the event return true; } } // Event wasn't for us, let superclass handle in default manner return super.touchEvent(event); } } 

Finally, a screen for using them:

 public class DiscScreen extends MainScreen { public DiscScreen() { super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR); add(new DiscManager(Field.USE_ALL_WIDTH)); } } 

results

enter image description here

+7
source

All Articles