JComboBox с несколькими одинаковыми элементами всегда выбирает первый экземпляр элемента

У меня есть 6 полей со списком, использующих один и тот же DefaultListModel с 6 элементами. Я использую ActionListener, так что когда одно из полей со списком выбирает элемент из списка, который выбрал другой список со списком, они меняют местами тех, кто выбрал элементы. AKA, поле со списком 1, в котором был выбран элемент 1, выбирает элемент 2, который был выбран в поле со списком 3, и после того, как слушатель запустит поле со списком 3, будет выбран элемент 1.

ActionListener abilCBListener = new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent evt){
        JComboBox cb = (JComboBox)evt.getSource();
        int ind = abilCBArray.indexOf(cb);
        int num = 15;
        int dup = 7;

        if(abilCBArray.size() == 6 && abilCBBoo == true){
            abilCBBoo = false;// prevents another combobox's listener from firing
            for(int i = 0; i < abilCBArray.size();i++){
                //System.out.println("i = " + i + " index = "+abilCBArray.get(i).getSelectedIndex());
                if(i != ind){
                    num -= abilCBArray.get(i).getSelectedIndex();
                    System.out.println("i = "+ i+" num = "+ num+ " Index = "+abilCBArray.get(i).getSelectedIndex() );
                    if(abilCBArray.get(i).getSelectedIndex() == cb.getSelectedIndex()){
                        dup = i;
                    } 
                }
            }
            if(num < abilCBArray.size() && dup != 7){
                abilCBArray.get(dup).setSelectedIndex(num);
            }
        }else{
            System.out.println("Tried to run abilCBArrayChange without full array");            
        }          
        abilCBBoo = true;
    }
};

Проблема в том, что пользователь может поместить случайный набор чисел в DefaultListModel, и если какое-либо из чисел совпадает, поля со списком выберут индекс первого экземпляра числа, которое испортит мой ActionListener. Все, что я прочитал, похоже, указывает на то, что вы должны сделать каждый элемент в списке уникальным, чтобы обойти проблему выбора поля со списком, и я все равно не смогу использовать getSelectIndex(), потому что, если я это сделаю, он все равно вернет первый экземпляр числа.


person Richard    schedule 16.05.2017    source источник
comment
getSelectedIndex() должен дать вам индекс выбранного элемента   -  person XtremeBaumer    schedule 16.05.2017


Ответы (3)


@camickr

import java.awt.event.ActionEvent;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Vector;

public class TestDuplicatesItems {

    private Vector<String> vec = new Vector<String>();
    private String[] degrees = {"AAS1", "AAS2", "AAS1", "AAS1"};
    private JComboBox combo = new JComboBox(vec);
    private JComboBox combo1 = new JComboBox(degrees);
    private JTextField txt = new JTextField(10);
    private JFrame frame = new JFrame("JComboBox with Duplicates Items");
    private JPanel panel = new JPanel();

    public TestDuplicatesItems() {
        vec.add("AAS1");
        vec.add("AAS1");
        vec.add("AAS1");
        vec.add("AAS1");
        //combo.setEditable(true);
        //combo.setBackground(Color.gray);
        //combo.setForeground(Color.red);        
        //combo.setEditable(true);
        //combo1.setBackground(Color.gray);
        //combo1.setForeground(Color.red);        
        txt.setText("1");
        combo.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(combo.getSelectedIndex());
                System.out.println(combo.getSelectedItem().toString());
                txt.setText(String.valueOf(combo.getSelectedIndex()));
            }
        });
        combo1.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if ((e.getStateChange() == ItemEvent.SELECTED)) {
                    System.out.println(combo1.getSelectedIndex());
                    System.out.println(combo1.getSelectedItem().toString());
                    txt.setText(String.valueOf(combo1.getSelectedIndex()));
                }
            }
        });
        panel.add(combo);
        panel.add(combo1);
        panel.add(txt);
        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                TestDuplicatesItems tdi = new TestDuplicatesItems();
            }
        });
    }
}

и на основе примитивного массива

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

public class SelectedComboBoxID {

    private JComboBox combo = new JComboBox();
    private JFrame frame = new JFrame("MyComboEg");
    private JTextField txt = new JTextField(10);
    private JPanel panel = new JPanel();

    public SelectedComboBoxID() {
        combo.addItem(new Item(1, "-"));
        combo.addItem(new Item(2, "Snowboarding"));
        combo.addItem(new Item(3, "Rowing"));
        combo.addItem(new Item(4, "Knitting"));
        combo.addItem(new Item(5, "Speed reading"));
        combo.addItem(new Item(6, "Pool"));
        combo.addItem(new Item(7, "None of the above"));
        //comboBox.setMaximumRowCount(3);
        combo.setPrototypeDisplayValue(" None of the above ");
        combo.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JComboBox comboBox = (JComboBox) e.getSource();
                Item item = (Item) comboBox.getSelectedItem();
                System.out.println(item.getId() + " : " + item.getDescription());
                txt.setText(String.valueOf(combo.getSelectedIndex()));
            }
        });
        //comboBox.setRenderer(new ItemRenderer());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        panel.add(combo);
        panel.add(txt);
        frame.add(panel);
        frame.pack();
        //frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private class ItemRenderer extends BasicComboBoxRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            if (value != null) {
                Item item = (Item) value;
                setText(item.getDescription().toUpperCase());
            }
            if (index == -1) {
                Item item = (Item) value;
                setText("" + item.getId());
            }
            return this;
        }
    }

    private class Item {

        private int id;
        private String description;

        public Item(int id, String description) {
            this.id = id;
            this.description = description;
        }

        public int getId() {
            return id;
        }

        public String getDescription() {
            return description;
        }

        @Override
        public String toString() {
            return description;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                SelectedComboBoxID selectedComboBoxID = new SelectedComboBoxID();
            }
        });
    }
}
person mKorbel    schedule 16.05.2017
comment
(1+) Да, это решение для создания пользовательского объекта, который будет храниться в модели поля со списком. (Я не был уверен, что вы подразумеваете под примитивным массивом). - person camickr; 16.05.2017
comment
POJO - это примитивный массив для меня, объект объектов, который возвращает toString(), возможно, моя (одна из) неверная интерпретация (ы) - person mKorbel; 16.05.2017
comment
Спасибо, пришлось немного повозиться, чтобы он работал с пользовательским объектом. - person Richard; 17.05.2017
comment
@mKorbel запоздало поздравляю с достижением 100K! :) - person Reimeus; 07.06.2017
comment
@Reimeus и тебе, несмотря на то, что я здесь просто турист, долгое время :-) - person mKorbel; 07.06.2017

Вы можете вызвать метод getSelectedItem(). Он вернет выбранное значение.

JComboBox имеет базовую модель ComboBoxModel. Вы можете установить его тип при его объявлении.

 JComboBox<String> j = new JComboBox();

Итак, этот comboBox использует Strings в качестве своей модели. Когда вы хотите получить выбранный предмет, вы можете позвонить:

 j.getSelectedItem()

и вы получите из него выбранную строку. Если вы позвоните

 j.getSelectedIndex()

вы получите индекс выбранной строки в модели, и вам нужно отобразить ее обратно, чтобы получить выбранное значение. Следовательно, getSelectedItem() — правильный путь.

person Stimpson Cat    schedule 16.05.2017
comment
Теперь лучше ;-) теперь мы очищаем наши комментарии и все в порядке ;-) - person GhostCat; 16.05.2017

У меня есть 6 полей со списком, использующих один и тот же DefaultListModel с 6 элементами.

Если поле со списком использует одну и ту же модель, то при выборе в одном поле со списком все поля со списком будут обновлены одним и тем же выбором.

Вам нужно создать 6 разных DefaultListModels, каждая из которых содержит одни и те же данные.

, поля со списком выберут индекс первого экземпляра числа

Проблема в том, что «выбрать элемент» хранится в модели поля со списком, а не в индексе выбранного элемента.

Когда вы вызываете метод `getSelectedIndex(), он перебирает все элементы модели, пока не найдет объект, равный выбранному объекту.

Если объект, добавленный в модель, реализует метод equals, это всегда будет первый найденный объект.

Таким образом, решение состоит в том, чтобы создать собственный объект, который будет храниться в модели.

См. ответ, предоставленный @mKorbel.

person camickr    schedule 16.05.2017
comment
Насколько я знаю, он должен быть основан на примитивном массиве, иначе он никогда не будет работать правильно, ошибка или функция из Java6, - person mKorbel; 16.05.2017
comment
пожалуйста, посмотрите мое объяснение кода, размещенное здесь в качестве ответа - person mKorbel; 16.05.2017
comment
Вот как я обошел поля со списком, выбирая один и тот же элемент всего с 1 набором данных ссылка - person Richard; 17.05.2017
comment
@Richard, да, 1 набор данных и 6 моделей — это нормально, но это не то, о чем говорилось в вашем первоначальном вопросе. Вот почему я сделал комментарий, что вам нужно 6 разных моделей. - person camickr; 17.05.2017