非焦点和滚动的自定义BitmapField错误(BlackBerry)

时间:2012-06-13 20:45:56

标签: blackberry java-me focus blackberry-os6 bitmapfield

尝试在BlackBerry 6上实现图片库时,我遇到了这个恼人的问题。

一切正常,但是当焦点从顶部按钮改变到屏幕下方的图片时,图像似乎有毛刺而不能正确地绘画。请参阅下面的图片以获取示例:

(焦点位于屏幕顶部(未显示)) initial screen

(焦点现在位于左下方的图像上,请注意顶部图像现在因未知原因而空白)

after scroll screen

无论我在tumbnail画廊添加多少张照片,都会发生这种情况。

现在这是我的代码,(关于缩略图绘制的一部分)

public ProductImage(String productName){
    super(VERTICAL_SCROLL|VERTICAL_SCROLLBAR);

    currentProduct = productName;

    createGUI(); 
}
public void createGUI(){
    deleteAll();
    try{
        Storage.loadPicture();
    }catch(NullPointerException e){
        e.printStackTrace();
    }
    this.setTitle(new LabelField(_resources.getString(PRODUCT_IMAGE), Field.FIELD_HCENTER));
    if(ToolbarManager.isToolbarSupported())
    {
        Toolbar tb = new Toolbar();
        setToolbar(tb.createToolBar());
    }
    else{
        Toolbar tb = new Toolbar();
        add(tb.createNavBar());
    }

    picVector = Storage.getPicture(currentProduct);

    EncodedImage enc = EncodedImage.getEncodedImageResource("camera.png");
    EncodedImage sizeEnc = ImageResizer.sizeImage(enc, Display.getHeight(), Display.getHeight());

    takenPicture = new BitmapField(enc.getBitmap());

    vfMain = new VerticalFieldManager();
    vfMain.add(logo);
    vfMain.add(new SeparatorField());
    add(vfMain);
    prepareBmpFields();
}   

 private void prepareBmpFields() {

        System.out.println("This is the vector size: " + picVector.getPicVector().size());

        LayoutManager manager = new LayoutManager();


        FieldChangeListener itemListener = new ButtonListener(); 


        mBmpFields = new ImageButtonField[picVector.getPicVector().size()];

        for (int i = 0; i < picVector.getPicVector().size(); i++) {
                /*EncodedImage image = EncodedImage
                                .getEncodedImageResource((String)imageVector.elementAt(i));*/
            byte[] data = getData((String)picVector.getPicVector().elementAt(i));
            //Encode and Resize image 
            EncodedImage  eImage = EncodedImage.createEncodedImage(data,0,data.length);

             eImage = ImageResizer.resizeImage(eImage, mImgWidth, mImgHeight);
             ImageButtonField currentImage = new ImageButtonField(eImage.getBitmap());
             currentImage.setAssociatedPath((String)picVector.getPicVector().elementAt(i));
             mBmpFields[i] = currentImage;
             mBmpFields[i].setChangeListener(itemListener);
             manager.add(mBmpFields[i]);

        }
        vfMain.add(manager);
    }

    private class LayoutManager extends VerticalFieldManager {
        public LayoutManager() {
            super(VERTICAL_SCROLL | VERTICAL_SCROLLBAR);
        }

        protected void sublayout(int width, int height) {
            int columns = mScrWidth / (mImgWidth + 2 * mImgMargin);

            int scrWidth = Display.getWidth();

              int rows = mBmpFields.length / columns
                + (mBmpFields.length % columns > 0 ? 1 : 0);
              int counter = 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;

                if(mBmpFields.length > counter){
                    Field field = mBmpFields[counter];
                    layoutChild(field, mImgWidth, mImgHeight);
                    setPositionChild(field, posX, posY);
                    counter++;
                };
               }  
             }
              if(Display.getWidth() < Display.getHeight()){
                setExtent(mScrWidth, (int)(mScrHeight*1.25));
                }
              else{
                  setExtent(mScrWidth, (int)(mScrHeight*2)); 
              }
        }


        public int getPreferredWidth() {
            return mScrWidth;
        }
        public int getPreferredHeight() {
            return mScrHeight;
        }
    }
}

我删除了许多不相关的代码部分,但所需的代码就在那里。

有谁知道可能导致此问题的原因?谢谢你的帮助!

编辑:根据要求,这是我对ImageButtonField类的实现:

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Characters;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.BitmapField;

public class ImageButtonField extends BitmapField{

String associatedPath ="";
BitmapField image2;

public ImageButtonField(Bitmap image) {
    super(image);
}
public void setAssociatedPath(String path){
    associatedPath = path;
}
public String getAssociatedPath(){
    return associatedPath;
}
public boolean isFocusable() {
    return true;
}
protected void applyTheme(Graphics arg0, boolean arg1) {
}

protected void drawFocus(Graphics graphics, boolean on) {
}
protected void onFocus(int direction) {
      // only change appearance if this button is enabled (aka editable)
      if (isEditable()) {
         invalidate();  // repaint
      } 
      super.onFocus(direction);
   }

   public void onUnfocus() {
      invalidate();  // repaint
      super.onUnfocus();
   }
protected boolean navigationClick(int status, int time) {
    fieldChangeNotify(0);
    return true;
}

protected boolean trackwheelClick(int status, int time) {
    fieldChangeNotify(0);
    return true;
}

protected void paint(Graphics graphics) {
    super.paint(graphics);
    if (isFocus()) {
        graphics.setGlobalAlpha(128);
        graphics.setColor(0x888888);
        graphics.fillRect(0, 0, getWidth(), getHeight());
    }else{
        graphics.setGlobalAlpha(0);
        graphics.setColor(0x000000);
        graphics.fillRect(0, 0, getWidth(), getHeight());
        //graphics.drawBitmap(0, 0, getWidth(), getHeight(), image2.getB, 0, 0);
    }
}

protected boolean keyChar(char character, int status, int time) {
    if(Characters.ENTER == character || Characters.SPACE == character) {
        fieldChangeNotify(0);
        return true;
    }
    return super.keyChar(character, status, time);
}

}

2 个答案:

答案 0 :(得分:1)

好的,所以你可以忽略我的第一个答案,但由于我当时没有你的ImageButtonField代码,我不想把它扔掉......也许其他人会觉得它很有用

最后,我不需要对ImageButtonField进行任何更改,但我确实更改了您的LayoutManager课程。我发现这是问题的方式是我刚开始用内置的UI替换你的自定义UI类。我将ImageButtonField替换为BitmapField。这没有解决它。然后,我将LayoutManager替换为FlowFieldManager并修复了它。所以,我知道问题出在哪里。

我的解决方案:

private class LayoutManager extends Manager {
  public LayoutManager() {
     super(VERTICAL_SCROLL | VERTICAL_SCROLLBAR);
  }

  protected void sublayout(int width, int height) {
     setExtent(width, height);
     // TODO: maybe always set the same virtual extent?
     if (Display.getWidth() < Display.getHeight()) {
        setVirtualExtent(mScrWidth, (int) (mScrHeight * 1.25));
     } else {
        setVirtualExtent(mScrWidth, (int) (mScrHeight * 2));
     }

     int columns = mScrWidth / (mImgWidth + 2 * mImgMargin);
     // int scrWidth = Display.getWidth();

     int rows = mBmpFields.length / columns + (mBmpFields.length % columns > 0 ? 1 : 0);
     int counter = 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;

           if (mBmpFields.length > counter) {
              Field field = mBmpFields[counter];
              layoutChild(field, mImgWidth, mImgHeight);
              setPositionChild(field, posX, posY);
              counter++;
           }
        }
     }
  }

  public int getPreferredWidth() {
     return mScrWidth;
  }

  public int getPreferredHeight() {
     return mScrHeight;
  }
}

我无法肯定地说我理解为什么你的原始代码不起作用,但我可以说我不会在原始代码中做过一些事情:

  1. 原始代码正在扩展VerticalFieldManager,但正在sublayout()中完成所有工作。所以,我认为没有任何意义延伸VerticalFieldManager。我将其更改为只展开Manager

  2. 原始代码使用不同大小调用setExtent()。我不认为这就是你想要的。 范围Field的实际尺寸。 虚拟范围是虚拟大小,您希望将其设置为大于实际范围,以便启用滚动。您不需要为纵向与横向动态计算不同的范围,因为传递给width的{​​{1}}和height参数已经反映了这一点。我不确定你是否真的需要设置不同的虚拟范围。我认为你应该总是将虚拟范围高度设置为图片高度的行数,占边距。

  3. 原始代码中有一个未使用的变量sublayout()。我在上面评论过它。

答案 1 :(得分:0)

你也是posted this question recently,对吗?假设您在此引用的ImageButtonField与您在另一个问题中所处理的ImageButtonField相同,我是否正确?

我看不到你ImageButtonField的完整实现,你也可以在这里发布。但是,看看你的另一个问题的答案,我感觉你在Field做了一些自定义焦点处理,也许它没有做得很好。在任何情况下,该类可能是问题所在。

我有一个类似我自己的public class CustomButtonField extends Field { private Bitmap _button; // the currently displayed button image private Bitmap _on; // image for 'on' state (aka in-focus) private Bitmap _off; // image for 'off' state (aka out-of-focus) protected void onFocus(int direction) { // only change appearance if this button is enabled (aka editable) if (isEditable()) { _button = _on; invalidate(); // repaint } super.onFocus(direction); } protected void onUnfocus() { _button = _off; invalidate(); // repaint super.onUnfocus(); } protected void drawFocus(Graphics graphics, boolean on) { // override superclass implementation and do nothing } public boolean isFocusable() { return true; } 子类,这里是我定义的焦点处理方法:

paint()

我还有paint()的自定义实现。我不会在这里显示所有内容,因为很多代码可能与您的问题无关,但我的graphics.drawBitmap(_padding, _padding, _fieldWidth, _fieldHeight, _button, 0, 0); 确实包含此调用:

onFocus()

您可能不关心我为聚焦和未聚焦状态分别创建图像的事实......也许您始终会显示相同的图像。

但是,可能需要检查的是onUnfocus()invalidate()方法。您可能需要像我一样添加对ImageButtonField.paint()的调用。

看看Rupak对你的另一个问题的回答,检查你的{{1}}方法也是一件好事,并确保如果该字段不是焦点,你不会忽视做重要的绘图步骤。