Как сохранить изображение в постоянном магазине

Я работаю над приложением BlackBerry, у которого есть "Кнопка изображения". Кнопка "Изображение" может меняться с "ВКЛ" на "ВЫКЛ" и наоборот при каждом нажатии. Теперь, что я пытаюсь сделать, когда приложение закрывается и загружается снова, эта "кнопка изображения" должна загружаться как ее последнее состояние. Если для "Image Button" было установлено значение "ON" и приложение закрыто, то при следующей загрузке оно будет загружено как "ON". Если при создании кнопки изображения установлено значение "true", изображение загружается как "ВКЛ", даже если оно было создано как выключенное. Я создаю ImageButton вне конструктора:

LabeledSwitch onImg=new LabeledSwitch(off,on,off,on,true); 

Затем внутри конструктора я попытался проверить последнее состояние изображения и, соответственно, снова создать кнопку изображения. Однако (boolean)((Boolean) persistentHashtable.get("image")). BooleanValue() генерирует исключение CastException, даже если оно компилируется нормально.

persistentObject = PersistentStore.getPersistentObject(KEY);

 if (persistentObject.getContents() == null) 
 {
    persistentHashtable = new Hashtable();
    persistentObject.setContents(persistentHashtable);
 } else {
    persistentHashtable = (Hashtable) persistentObject.getContents();
     }

  if (persistentHashtable.containsKey("image")) 
 {
     boolean booleanVal = (boolean)((Boolean) persistentHashtable.get("image")).booleanValue();
     if (booleanVal==true)
     {
         onImg=new LabeledSwitch(on,off,on,off,true);
     }
     else
     {
         onImg=new LabeledSwitch(off,on,off,on,false);
     }
 }

Я сохраняю состояние изображения на выходе:

public boolean onClose() 
    {
        int choose=Dialog.ask(Dialog.D_YES_NO, "Are you sure Want to Exit?");
        if(choose==Dialog.YES)
        {
            if(onImg._on)
             persistentHashtable.put("image", Boolean.TRUE);

            else
                persistentHashtable.put("image", Boolean.FALSE); 
            System.exit(0);

        }
        return true;
    }

Пожалуйста, руководство. Для справки ниже приведен класс LabeledSwitch, используемый для создания кнопки изображения:

import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;

public class LabeledSwitch extends Field {
    private String _textOn;
    private String _textOff;

    private int _textWidth;
    private int _textHeight;

    private int _totalWidth;
    private int _totalHeight;

    private Bitmap _imageOn;
    private Bitmap _imageOnFocus;
    private Bitmap _imageOff;
    private Bitmap _imageOffFocus;

    public boolean _on; //chngd
    private boolean _selected;

    private Font _labelFont;

    private static MenuItem _changeOptionsItem = new ChangeOptionMenuItem();

    private int _textColour = 0x888888;
    private int _textColourFocus = 0x000000;

    private int _horizontalTextImageGap;

    private Bitmap _switchImage;  
    private String _labelText;  
    int mHeight;
    int mWidth;

    public LabeledSwitch(){}

    public LabeledSwitch( Bitmap imageOn
                , Bitmap imageOff
                , Bitmap imageOnFocus
                , Bitmap imageOffFocus
                , boolean onByDefault ) {
        super( Field.FIELD_VCENTER );

        //_textOn = textOn ="";
        //_textOff = textOff ="";

        _imageOn = imageOn;
        _imageOff = imageOff;
        _imageOnFocus = imageOnFocus;
        _imageOffFocus = imageOffFocus;
        _on = onByDefault; 
        _selected = false;

        _horizontalTextImageGap = _imageOn.getHeight() / 3;

    }

    public void applyFont() {
        _labelFont = getFont().derive( Font.PLAIN, _imageOn.getHeight()  );
    }

    /**
     * Change the state of the switch
     * @param on - if true, the switch will be set to on state
     */
    public void setOn(boolean on) {
        _on = on;
        invalidate();
    }

    public boolean getOnState() {
        return _on;
    }

    public boolean isFocusable() {
        return true;
    }

    public int getPreferredWidth() {
        return _totalWidth;
    }

    public int getPreferredHeight() {
        return _totalHeight;
    }

    protected void layout( int width, int height ) {
        // 
        _textWidth = Math.max( _labelFont.getAdvance( _textOn + "a" ), _labelFont.getAdvance( _textOff + "a" ) )-36;
        _textHeight = _labelFont.getHeight();

        _totalWidth = _imageOn.getWidth() + _horizontalTextImageGap + _textWidth;
        _totalHeight = _imageOn.getHeight();

        mWidth = getPreferredWidth();
        mHeight = getPreferredHeight();
        setExtent(mWidth, mHeight);

       // setExtent( _totalWidth, _totalHeight );
    }

    public void paint( Graphics g ){
        Font oldFont = g.getFont();
        int oldColor = g.getColor();

        try { 

            if( _on ) {
                _switchImage = g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS) ? _imageOnFocus : _imageOn;
            } else {
                _switchImage = g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS) ? _imageOffFocus : _imageOff;
            }

            g.setFont( _labelFont );

            // Determine Label Colour
            g.setColor( g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS) ? _textColourFocus : _textColour );

            // Label
            g.drawText( _on ? _textOn : _textOff, 0, ( getHeight() - _textHeight ) / 2, DrawStyle.RIGHT, _textWidth ); 

            // Image
            //g.drawBitmap( _textWidth + _horizontalTextImageGap, 0, _switchImage.getWidth(), _switchImage.getHeight(), _switchImage, 0, 0 );
            g.drawBitmap(0, 5, mWidth, mHeight, _switchImage, 0, 0);
        } finally {
            g.setFont( oldFont );
            g.setColor( oldColor );
        }
    }

    public void paintBackground( Graphics g ) {}

    protected void drawFocus( Graphics g, boolean on ){
        // Paint() handles it all
        g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
        paint( g );
    }

    protected boolean keyChar( char key, int status, int time ){
        if( key == Characters.SPACE || key == Characters.ENTER ) {
            toggle();            
            return true;
        }
        return false;
    }

    protected boolean navigationClick(int status, int time){
        toggle();            
        return true;    
    }

    protected boolean invokeAction(int action){
        switch( action ) {
            case ACTION_INVOKE: {
                toggle(); 
                return true;
            }
        }
        return super.invokeAction( action );
    }

    protected boolean trackwheelClick( int status, int time ){        
        if( isEditable() ) {
            toggle();            
            return true;
        }
        return super.trackwheelClick(status, time);
    }

    /**
     * Toggles the state of the switch
     */
    private void toggle(){
        _on = !_on;
        invalidate();
        fieldChangeNotify( 0 );
    }

    public void setDirty( boolean dirty ){
        // We never want to be dirty or muddy
    }

    public void setMuddy( boolean muddy ){
        // We never want to be dirty or muddy
    }    

    protected void makeContextMenu(ContextMenu contextMenu){
        super.makeContextMenu(contextMenu);
        if((Ui.getMode() < Ui.MODE_ADVANCED) && isEditable()) {
            contextMenu.addItem(_changeOptionsItem);
        }
    }

    /**
     * @category Internal InnerClass
     */
    static class ChangeOptionMenuItem extends MenuItem {
        ChangeOptionMenuItem() {
            super("Toggle", 30270, 10);
        }

        ChangeOptionMenuItem(String text) {
            super(text, 30270, 10);
        }

        public void run() {
            LabeledSwitch theSwitch = (LabeledSwitch)getTarget();
            theSwitch.toggle();
        }

        public int getPriority() {
            return 100 + (getTarget().isMuddy() ? 1000 : 0);
        }
    };
}

2 ответа

Решение

Итак, я думаю, что здесь может быть несколько проблем. Я думаю, что Евгений прав насчет commit() вызов.

Тем не менее, я думаю, что LabeledSwitch класс используется неправильно. Я догадываюсь, что ты не написал этот класс? Я говорю это только потому, что вижу несколько соглашений о кодировании в одном классе.

Видя несколько пользовательских классов BlackBerry UI, подобных этому, я считаю, что этот класс должен работать так:

  1. Класс может переключаться между двумя визуальными состояниями, которые вы можете определить, передав классу PNG-изображение, представляющее включенное состояние и выключенное состояние.

  2. Класс можно переключать между этими состояниями, вызывая setOn() метод, либо с true или же false значение для параметра. Значение этого параметра будет определять, какой файл PNG рисуется в пользовательском классе paint() метод

  3. Оригинальный автор класса намеревается использовать setOn() а также getOnState() методы для изменения и доступа к текущему состоянию коммутатора. Вы должны изменить это

public boolean _on;

к этому:

private boolean _on;

Если вы хотите узнать, включен ли переключатель, спросите onImg.getOnState(),

Кстати, я бы порекомендовал другое имя для вашего коммутатора, чем onImg, Это очень запутанное имя. Это должно быть что-то вроде onOffSwitch, или же toggleSwitch, или же fooSwitch, если переключатель используется для выключения и включения чего-то, что называется foo. Называя это onImg сбивает с толку, в контексте переменной-члена _imageOn, который всегда должен представлять изображение, которое отображается при включенном переключателе.

Итак, подведем итог, вместо этого:

 if (booleanVal==true)
 {
     onImg=new LabeledSwitch(on,off,on,off,true);
 }
 else
 {
     onImg=new LabeledSwitch(off,on,off,on,false);
 }

используйте что-то вроде этого:

 onOffSwitch = new LabeledSwitch(on, off, on, off, true);
 onOffSwitch.setOn(booleanValue);        

или же

 onOffSwitch = new LabeledSwitch(on, off, on, off, booleanValue);

Прежде всего, я не вижу следующего необходимого кода для хранения вашего постоянного объекта:

persistentObject.commit();

Я надеюсь, что это всего лишь несколько дополнений из вашего кода, в противном случае вы всегда переписываете значение перед его чтением, что, вероятно, не ожидается. Таким образом, код "read" не должен оставаться после "write", потому что он не имеет никакого смысла.

Другие вопросы по тегам