LWUIT的List运用系列(五)

在前四节中,我们实现了给List绑定数据,动态加载数据,处理List的一些事件,以及解决了List一些让用户感觉不舒服的默认显示问题,也许这样使用List已经符合我们的基本需求了,功能都能通过前面几节的内容实现。但是现在又有这样一个需求:用户希望能够通过改变选中项的Label颜色来标识这一项是选中的,可能这样说有点拗口。我举个例子,一个web页面中有很多超链接,当用户移上超链接时,超链接的颜色会改变,而手机用户同样希望达到这种效果。
前面的例子中,每个List的项都有两个Label,一个显示图片,一个显示名字,我们这里简单点,只对显示名字的Label的样式进行改变。
也许你认为,有了前面的例子,这实现起来有什么难度,只要获取Renderer类中的Label就可以了,然后你可能举出两种途径:
1、直接在SelectionListener事件中做选中的效果。
2、在ListCellRender中进行判断。
如果直接把前面的代码拿过来,然后通过上面两种途径是不能实现上面那种效果的。
首先,我证明一下为什么不能够通过上述两种方法实现那种效果。
途径1:

        personList.addFocusListener(new FocusListener() {

            public void focusGained(Component c) {
                oldCon = (Renderer)(personList.getSelectedItem());
                //当List获得焦点时,改变第一项的name颜色
                oldCon.name.getStyle().setFgColor(0xCC0000);
            }

            public void focusLost(Component c) {

            }
        });

        personList.addSelectionListener(new SelectionListener() {

            public void selectionChanged(int oldSelection, int newSelection) {
                //当更改List的选项时,把上一项的name改为默认颜色(黑色),把当前选中的改为红色
                oldCon.name.getStyle().setFgColor(0x000000);
                newCon = (Renderer)personList.getSelectedItem();
                newCon.name.getStyle().setFgColor(0xCC0000);
                oldCon = newCon;
            }
        });

其中oldCon,newCon被声明为字段,它们的类型是Renderer类型。
虽然上述代码在编译时是没有错误,但是在执行时却报错了。错误的原因在于:无法把personList.getSelectedItem()转换成Renderer类型,因为我们在createList方法中,传入的Model是Person数组,它只能转换成Person类型,这条路明显是行不通的。
途经2:

    class Renderer extends Container implements ListCellRenderer {

        public Label name = new Label("");
        public Label pic = new Label("");
        public Label focus = new Label("");

        public Renderer() {
            setLayout(new BorderLayout());
            addComponent(BorderLayout.WEST, pic);
            name.getStyle().setBgTransparency(0);
            addComponent(BorderLayout.CENTER, name);
        }

        public Component getListCellRendererComponent(List list, Object value,
                int index, boolean isSelected) {
            Person person = (Person) value;
            name.setText(person.getName());
            pic.setIcon(person.getPhoto());
            //在这里做判断
            if(isSelected){
                name.getStyle().setFgColor(0xCC0000);
            }else{
                name.getStyle().setFgColor(0x000000);
            }
            return this;
        }

        public Component getListFocusComponent(List list) {
            return focus;
        }
    }

注意红色部分的代码,看起来这一部分是没有逻辑错误,不仅编译通过,而且还能够执行,但是执行的结果却不是我们所期望的,它竟然把List中的所有name的颜色都改变了!具体原因:在这里面首先我们的返回值是this,this是什么,是Container,而那个boolean Selected的选中并不是针对Container的,而是Person,从途经1中我们就知道在createList的时候,我们的Model部分是Person数组,选中的状态与否都是针对Person类的。那一句name.getStyle().setFgColor(0xCC0000),List的每一项都有name,而Renderer类它本身根本就不知道这个name是属于哪个Container的,所以显示的结果就是所有的name颜色都会变成红色。

 

既然以上两种途经都不可行,但我们解决问题的思路仍然是:找到List中的每一项的Container,然后再找到Container中的name Label。关键的问题是以上两种途径的Model部分都是Person数组,而我们要获取的是Container,这样问题就迎刃而解了,我们何不把Container作为Model的部分呢?这样我们获取List的selectedItem的时候,取到的就是Container类型,取得Container中的Label就很容易了。class Renderer extends Container implements ListCellRenderer,既然要取得Container,那我们完全可以把这一个类拆分为两个类,一个类继承Container类(这是我们想要的,而且这个Container不是复合类型),另一个类继承ListCellRenderer接口。
然后看看实现这些的关键代码:

   //模拟数据
    public Person[] getContacts() {
        Person[] personArray = new Person[5];
        Image photo = null;
        try {
            photo = Image.createImage("/smallphoto.jpg");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        for (int i = 0; i < personArray.length; i++) {
            personArray[i] = new Person("Sunny Peng" + (++start), photo);
        }
        return personArray;
    }

    //传入Person数组,然后创建一个ContactContainer数组
    private ContactContainer[] createContainers(Person[] persons) {
        ContactContainer[] cons = new ContactContainer[persons.length];
        for (int i = 0; i < cons.length; i++) {
            Person p = persons[i];
            ContactContainer con = new ContactContainer(p);
            cons[i] = con;

        }
        return cons;
    }

    //这里虽然变化不大,但是Model变了,以ContactContainer数组作为Model
    private List createList(ContactContainer[] cons) {
        List list = new List(cons);
        list.setListCellRenderer(new ContactRenderer());
        return list;
    }

    //Container类,作为Model
    class ContactContainer extends Container {

        private Label pic;
        private Label name;

        //传入Person数据,给Label赋值
        public ContactContainer(Person p) {
            setLayout(new BoxLayout(BoxLayout.X_AXIS));
            pic = new Label(p.getPhoto());
            name = new Label(p.getName());
            addComponent(pic);
            addComponent(name);
        }
    }

    class ContactRenderer implements ListCellRenderer {

        private Label focus = new Label();

        public ContactRenderer() {
        }

        public Component getListCellRendererComponent(List list, Object value, int index, boolean selected) {
            //这个方法返回的不再是this了,而是ContactContainer
            return (ContactContainer) value;
        }

        public Component getListFocusComponent(List list) {
            return focus;
        }
    }

上面的Person类我没写,前面的例子中有。
然后再看看调用部分:

    public ListForm(){
        setLayout(new BorderLayout());
        Person[] persons = getContacts();
        final ContactContainer[] conArr = createContainers(persons);
        final List personList = createList(conArr);
        addComponent(personList);
        
        personList.addFocusListener(new FocusListener() {

            public void focusGained(Component c) {
                int index = personList.getSelectedIndex();
                conArr[index].name.getStyle().setFgColor(0xCC0000);
            }

            public void focusLost(Component c) {
                
            }
        });
        
        personList.addSelectionListener(new SelectionListener() {

            public void selectionChanged(int oldIndex, int newIndex) {
                conArr[oldIndex].name.getStyle().setFgColor(0x000000);
                conArr[newIndex].name.getStyle().setFgColor(0xCC0000);
            }
        });
    }

效果图我就不发了。

Technorati 标签: LWUIT list的运用



 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值