1

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

一切正常,但是当焦点从顶部按钮变为屏幕下方的图片时,图像似乎出现故障并且无法正确绘制自己。请参阅下面的图片以获取示例:

(焦点在屏幕顶部(未显示)) 初始画面

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

滚动屏幕后

无论我在缩略图库中添加多少图片,都会发生这种情况。

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

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);
}

}

4

2 回答 2

1

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

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

我的解决方案:

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。我把它改成了 extend Manager

  2. 原始代码setExtent()以不同的大小调用。我不认为那是你想要的。 ExtentField. 虚拟范围是虚拟大小,您希望将其设置为大于实际范围,以便启用滚动。您不需要动态计算纵向与横向的不同范围,因为传递给的widthandheight参数sublayout()已经反映了这一点。我不确定您是否真的需要设置不同的虚拟范围。我认为您可能应该始终将虚拟范围高度设置为行数乘以图片高度,并考虑边距。

  3. 您的原始代码中有一个未使用的变量scrWidth。我在上面评论了它。

于 2012-06-16T01:31:17.527 回答
0

你最近也发过这个问题吧?我是否正确假设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()像我一样添加一个呼叫。

查看 Rupak 对您的其他问题的回答,检查您的ImageButtonField.paint()方法也很好,并确保如果该领域不在焦点上,您不会忽略执行重要的绘图步骤。

于 2012-06-14T00:21:02.063 回答