【问题标题】:BlackBerry - draw image on the screen黑莓 - 在屏幕上绘制图像
【发布时间】:2023-03-07 13:19:01
【问题描述】:

如何在屏幕上绘制特定大小和位置的png图像?

【问题讨论】:

    标签: user-interface graphics blackberry java-me png


    【解决方案1】:

    调整图片大小

     public EncodedImage sizeImage(EncodedImage image, int width, 
      int height) {
      EncodedImage result = null;
    
      int currentWidthFixed32 = Fixed32.toFP(image.getWidth());
      int currentHeightFixed32 = Fixed32.toFP(image.getHeight());
    
      int requiredWidthFixed32 = Fixed32.toFP(width);
      int requiredHeightFixed32 = Fixed32.toFP(height);
    
      int scaleXFixed32 = Fixed32.div(currentWidthFixed32,
        requiredWidthFixed32);
      int scaleYFixed32 = Fixed32.div(currentHeightFixed32,
        requiredHeightFixed32);
    
      result = image.scaleImage32(scaleXFixed32, scaleYFixed32);
      return result;
     }
    

    这个函数将在下面的代码中使用。

    简单画图

    Simply painting images http://img268.imageshack.us/img268/9918/bb8310.png

    让我们以表格的方式绘制 9 张图像,图像大小不同,但我们会将它们调整为 80x80 并赋予它们 10 像素的边距。

    假设您的项目资源中有 9 张 png 图像。

    1. 加载图片
    2. 调整图片大小
    3. 在特定位置的每个绘制事件上绘制图像

    代码:

    class Scr extends MainScreen {
     int mImgWidth = 80;
     int mImgHeight = 80;
     int mImgMargin = 10;
     String fileNames[] = { "1.png", "2.png", "3.png", "4.png", "5.png",
       "6.png", "7.png", "8.png", "9.png" };
     EncodedImage[] mImages;
    
     public Scr() {
     super();
      prepareImages();
     }
    
     private void prepareImages() {
      mImages = new EncodedImage[fileNames.length];
      for (int i = 0; i < fileNames.length; i++) {
       EncodedImage image = EncodedImage
         .getEncodedImageResource(fileNames[i]);
       mImages[i] = sizeImage(image, mImgWidth, mImgHeight);
      }
     }
    
     protected void paint(Graphics graphics) {
      paintImages(graphics);
      super.paint(graphics);
     }
    
     private void paintImages(Graphics graphics) {
      int scrWidth = Display.getWidth();
      int columns = scrWidth / (mImgWidth + 2 * mImgMargin);
      int rows = mImages.length / columns
        + (mImages.length % columns > 0 ? 1 : 0);
      for (int i = 0; i < rows; i++) {
       for (int j = 0; j < columns; j++) {
        int posX = j * (mImgWidth + 2 * mImgMargin) + mImgMargin;
        int posY = i * (mImgHeight + 2 * mImgMargin) + mImgMargin;
        EncodedImage image = mImages[i * columns + j];
        graphics.drawImage(posX, posY, mImgWidth, mImgHeight,
          image, 0, 0, 0);
       }
      }
     }
    }
    

    简单画图 - 优化

    看一下 Scr 的 paint() 方法。每次刷新时,整个图像表都会重新绘制,这意味着每次绘制都会调用 9 个 drawImage。如果我们只拍一张这张表的快照并在 paint() 方法中使用它呢?

    class ScrOpt extends MainScreen {
     int mScrWidth = Display.getWidth();
     int mScrHeight = Display.getHeight();
     int mImgWidth = 80;
     int mImgHeight = 80;
     int mImgMargin = 10;
     String fileNames[] = { "1.png", "2.png", "3.png", "4.png", "5.png",
       "6.png", "7.png", "8.png", "9.png" };
     EncodedImage[] mImages;
     Bitmap mImgTable;
    
     public ScrOpt() {
      super();
      prepareImages();
      mImgTable = paintImages();
     }
    
     private void prepareImages() {
      mImages = new EncodedImage[fileNames.length];
      for (int i = 0; i < fileNames.length; i++) {
       EncodedImage image = EncodedImage
         .getEncodedImageResource(fileNames[i]);
       mImages[i] = sizeImage(image, mImgWidth, mImgHeight);
      }
     }
    
     private Bitmap paintImages() {
      Bitmap result = new Bitmap(mScrWidth, mScrHeight);
      Graphics graphics = new Graphics(result);
      int scrWidth = mScrWidth;
      int columns = scrWidth / (mImgWidth + 2 * mImgMargin);
      int rows = mImages.length / columns
        + (mImages.length % columns > 0 ? 1 : 0);
      for (int i = 0; i < rows; i++) {
       for (int j = 0; j < columns; j++) {
        int posX = j * (mImgWidth + 2 * mImgMargin) + mImgMargin;
        int posY = i * (mImgHeight + 2 * mImgMargin) + mImgMargin;
        EncodedImage image = mImages[i * columns + j];
        graphics.drawImage(posX, posY, mImgWidth, mImgHeight, image, 0,
          0, 0);
       }
      }
      return result;
     }
    
     protected void paint(Graphics graphics) {  
      super.paint(graphics);
      graphics.drawBitmap(0, 0, mScrWidth, mScrHeight, mImgTable, 0, 0);
     }
    }
    

    你可以进一步优化它,using paintBackground() method

    使用位图字段

    以上所有内容都是关于使用Graphics 将图像直接绘制到屏幕上。有时它很棒 - 当您想要显示一些动画或背景图像时。但是,如果您想保持标准的 UI 用户体验,并使用图像作为字段呢?

    alt text http://img142.imageshack.us/img142/7485/bb83102.png

    海峡是BitmapField

    class ScrBmpField extends MainScreen {
     int mImgWidth = 80;
     int mImgHeight = 80;
     int mImgMargin = 10;
     String fileNames[] = { "1.png", "2.png", "3.png", "4.png", "5.png",
       "6.png", "7.png", "8.png", "9.png" };
     BitmapField[] mBmpFields;
    
     public ScrBmpField() {
      super(VERTICAL_SCROLL|VERTICAL_SCROLLBAR);
      prepareBmpFields();  
     }
    
     private void prepareBmpFields() {
      mBmpFields = new BitmapField[fileNames.length];
      for (int i = 0; i < fileNames.length; i++) {
       EncodedImage image = EncodedImage
         .getEncodedImageResource(fileNames[i]);
       image = sizeImage(image, mImgWidth, mImgHeight);
       mBmpFields[i] = 
           new BitmapField(image.getBitmap(), FOCUSABLE|FIELD_HCENTER);
       mBmpFields[i].setMargin(mImgMargin, mImgMargin, 
           mImgMargin, mImgMargin);
       add(mBmpFields[i]);
      }
     }
    }
    

    使用 BitmapField - 自定义布局

    alt text http://img9.imageshack.us/img9/403/bb83103.png

    要在管理器中设置BitmapFields的自定义位置,可以实现manager with custom layout

    class ScrLayout extends MainScreen {
        int mScrWidth = Display.getWidth();
        int mScrHeight = Display.getHeight();
        int mImgWidth = 80;
        int mImgHeight = 80;
        int mImgMargin = 10;
        String fileNames[] = { "1.png", "2.png", "3.png", "4.png", "5.png",
                "6.png", "7.png", "8.png", "9.png" };
        BitmapField[] mBmpFields;
    
        public ScrLayout() {
            super(VERTICAL_SCROLL | VERTICAL_SCROLLBAR);
            prepareBmpFields();
        }
    
        private void prepareBmpFields() {
            LayoutManager manager = new LayoutManager();
            add(manager);
            mBmpFields = new BitmapField[fileNames.length];
            for (int i = 0; i < fileNames.length; i++) {
                EncodedImage image = EncodedImage
                        .getEncodedImageResource(fileNames[i]);
                image = sizeImage(image, mImgWidth, mImgHeight);
                mBmpFields[i] = 
                    new BitmapField(image.getBitmap(), FOCUSABLE);
                manager.add(mBmpFields[i]);
            }
        }
    
        class LayoutManager extends VerticalFieldManager {
            public LayoutManager() {
                super(VERTICAL_SCROLL | VERTICAL_SCROLLBAR);
            }
    
            protected void sublayout(int width, int height) {
                int columns = mScrWidth / (mImgWidth + 2 * mImgMargin);
                for (int i = 0, j = 0; i < mBmpFields.length; i++) {
                    int posX = j * (mImgWidth + 2 * mImgMargin) + mImgMargin;
                    int posY = i * (mImgHeight + 2 * mImgMargin) + mImgMargin;
                    Field field = mBmpFields[i];
                    layoutChild(field, mImgWidth, mImgHeight);
                    setPositionChild(field, posX, posY);
    
                    j = (j == columns - 1) ? 0 : j + 1;
                }
                setExtent(mScrWidth, mScrHeight);
            }
            public int getPreferredWidth() {
                return mScrWidth;
            }
            public int getPreferredHeight() {
                return mScrHeight;
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      初始化函数中的某处:

       Image myImage = Image.createImage("/myimage.png");
      

      在画布的绘制功能中:

       g.drawImage(myImage, posX, posY, Graphics.TOP|Graphics.LEFT);
      

      (其中 g 是您从绘制函数中获得的 Graphics 对象)

      编辑:修复了 cmets 中指出的小错误

      【讨论】:

        【解决方案3】:

        如果您使用 net.rim.device.api.system.PNGEncodedImage 或从 net.rim.device.api.system.EncodedImage 扩展的其他类之一,您可以使用 scaleImage32(int scaleX, int scaleY) 方法(在 OS 4.2 及更高版本中可用)将图像缩放到您想要的大小。请注意,尽管 scaleX 和 scaleY 输入为 int,但实际上是 net.rim.device.api.math.Fixed32,以便以一半大小显示图像:

        EncodedImage halfSize = myImage.scaleImage32(Fixed32.toFP(2), Fixed32.toFP(2));
        

        或者对于两倍原始大小的图像:

        EncodedImage twiceSize = myImage.scaleImage32(Fixed32.tenThouToFP(5000), Fixed32.tenThouToFP(5000));
        

        【讨论】:

        • 唯一的缺点是代码只使用 rim 类,因此不能移植到任何其他 java 设备。
        • 是的,但您的答案仅满足 OP 指定的两个要求之一。
        【解决方案4】:
        private VerticalFieldManager mainBackVerticalFieldManager = null;
        
        int deviceWidth = Display.getWidth();
        int deviceHeight = Display.getHeight();    
        
        mainBackVerticalFieldManager   = new VerticalFieldManager(VerticalFieldManager.NO_VERTICAL_SCROLL|VerticalFieldManager.NO_VERTICAL_SCROLLBAR){
                protected void paint(Graphics graphics) {
                    graphics.clear();
                    graphics.drawBitmap(0, 0, deviceWidth,deviceHeight,Bitmap.getBitmapResource(Constants.PURCHASE_SUMMARY_BG), 0,0);
                    super.paint(graphics);
                };
            };
        

        在这里您可以根据需要更改设备宽度和高度。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-18
          • 1970-01-01
          相关资源
          最近更新 更多