如何在Blackberry中使用Canvas上的文本旋转圆圈

Sil*_*ler 3 java blackberry touch

如何在TouchEvent或TrackBallMoveEvent上使用文本旋转圆圈.

  1. 我如何创建这种圈子?

    我创建了一个圆圈并旋转它,但它总是从0度开始.

  2. 有没有其他选择来创建这种圈子?

每个圆圈都有不同的文字,每个圆圈都可以独立移动.

在此输入图像描述

Nat*_*ate 7

所以,这绝对不完整,但我认为这是你需要的大部分内容.

限制/假设

  1. 到目前为止,我只实现了触摸处理,因为我认为这更难.如果我以后有时间,我会回来添加轨迹球处理.
  2. 我没有给旋转盘任何动力.用户的手指离开光盘后,它会停止旋转.
  3. 我不确定光盘之间的焦点转换是100%正确的.你必须做一些测试.至少他们大多是对的.
  4. 当您在标题中提到Canvas时,我认为并不意味着您需要使用J2ME Canvas.使用RIM UI库编写BlackBerry应用程序几乎就是我所做的一切.

基本上,我创建了一个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;
   }
}
Run Code Online (Sandbox Code Playgroud)

包含所有DiscField对象的是DiscManager.它对齐孩子DiscFieldssublayout(),并处理触摸事件的正确代表团......自从领域重叠,和内部的触摸DiscField小号程度不也属于它的半径范围内(即拐角)应由较大的光盘进行处理.

   /** 
    * 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);
      }
   }
Run Code Online (Sandbox Code Playgroud)

最后,使用它们的屏幕:

public class DiscScreen extends MainScreen {

   public DiscScreen() {
      super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);

      add(new DiscManager(Field.USE_ALL_WIDTH));
   }
}
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述

  • +1为你的勇气..代表用户工作. (2认同)