TouchEvent または TrackBallMoveEvent でテキストを使用して円を回転させる方法。
- この種のサークルを作成するにはどうすればよいですか? - 円を作成して回転させましたが、常に 0 度から始まります。 
- この種のサークルを作成する他のオプションはありますか? 
各円には異なるテキストがあり、各円は独立して移動できます。

TouchEvent または TrackBallMoveEvent でテキストを使用して円を回転させる方法。
この種のサークルを作成するにはどうすればよいですか?
円を作成して回転させましたが、常に 0 度から始まります。
この種のサークルを作成する他のオプションはありますか?
各円には異なるテキストがあり、各円は独立して移動できます。

ですから、これで完全ではありませんが、必要なものはほとんど揃っていると思います。
基本的に、Field各ディスクを表すサブクラスを作成しました。ラベルの配列を渡してフィールドを作成し、周囲、半径、および色に間隔を空けます。それぞれにハードコーディングされているDiscFieldのは、テキストのエッジ インセットです。これは、ディスク間の特定のサイズの違いを想定しています。おそらくそれをより動的にする必要があります。
public class DiscField extends Field {
   /** Used to map Manager's 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;
   }
}
すべてのDiscFieldオブジェクトを含むのはDiscManager. DiscFieldsこれは で子を整列し、sublayout()タッチ イベントの適切な委譲を処理します ... フィールドがオーバーラップし、その半径 (つまりコーナー) 内に収まらないDiscFieldsエクステント内のタッチは、より大きなディスクで処理する必要があるためです。
   /** 
    * 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's 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);
      }
   }
最後に、それらを使用するための画面:
public class DiscScreen extends MainScreen {
   public DiscScreen() {
      super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);
      add(new DiscManager(Field.USE_ALL_WIDTH));
   }
}
