Измените значение записи JComboBox без запуска изменения выбора [дубликат]

Другой общий случай, когда можно получить это исключение, включает в себя насмешливые классы во время модульного тестирования. Независимо от используемой насмешливой структуры, вы должны убедиться, что все соответствующие уровни иерархии классов должным образом высмеиваются. В частности, все свойства HttpContext, на которые ссылается тестируемый код, должны быть изделены.

См. « Исключение NullReferenceException при проверке пользовательского AuthorizationAttribute » для несколько подробного примера.

4
задан jzd 10 March 2011 в 13:32
поделиться

8 ответов

Вы можете удалить прослушиватель действий, прежде чем добавлять новые элементы, и добавить его обратно, как только вы закончите. Качание однопоточное, поэтому нет необходимости беспокоиться о других потоках, требующих увольнения слушателя.

Ваш слушатель, вероятно, также может проверить, что что-то выбрано, и предпринять соответствующие действия, если нет. Лучше, чем получить NPE.

10
ответ дан objects 24 August 2018 в 10:28
поделиться

, хотя его поздняя, ​​лучшей альтернативой было бы отключить выпадающее поле, которое должно быть изменено до того, как оно будет изменено. при этом вы предотвращаете события стрельбы из измененного поля со списком, когда, например, вы используете методы like removeAllItems () или addItem ()

String orderByOptions[] = {"smallest","highest","longest"};

JComboBox<String> jcomboBox_orderByOption1 = new JComboBox<String(orderByOptions);
JComboBox<String> jcomboBox_orderByOption2 = new JComboBox<String(orderByOptions);
JComboBox<String> jcomboBox_orderByOption3 = new JComboBox<String(orderByOptions);

jcomboBox_orderByOption1.addItemListener(new ItemListener()
{
    public void itemStateChanged(ItemEvent itemEvent)
    {
            int eventID = itemEvent.getStateChange();

            if (eventID == ItemEvent.SELECTED)
            {
                Object selectedItem = jcomboBox_orderByOption1.getSelectedItem();

                jcomboBox_orderByOption2.setEnabled(false);
                jcomboBox_orderByOption2.removeAllItems();

                for (String item: string_orderByOptions)
                {
                    if (!item.equals(selectedItem))
                    {
                        jcomboBox_orderByOption2.addItem(item);
                    }
                }

                jcomboBox_orderByOption2.setEnabled(true);
            }
        }
    });



    jcomboBox_orderByOption2.addItemListener(new ItemListener()
    {
        public void itemStateChanged(ItemEvent itemEvent)
        {
            int eventID = itemEvent.getStateChange();

            if (eventID == ItemEvent.SELECTED)
            {
                Object selectedItem1 = jcomboBox_orderByOption1.getSelectedItem();
                Object selectedItem2 = jcomboBox_orderByOption2.getSelectedItem();

                jcomboBox_orderByOption3.setEnabled(false);

                jcomboBox_orderByOption3.removeAllItems();

                for (String item: string_orderByOptions)
                {
                    if (!item.equals(selectedItem1) && !item.equals(selectedItem2))
                    {
                        jcomboBox_orderByOption3.addItem(item);
                    }
                }

                jcomboBox_orderByOption3.setEnabled(true);

            }
        }
    });
2
ответ дан johnny 24 August 2018 в 10:28
поделиться

Я как-то пошел глупый простой маршрут с этой проблемой для своей программы, так как я новичок в программировании.

Я изменил прослушиватели действий на наличие счетчика if:

if(stopActionlistenersFromFiringOnLoad != 0){//action performed ;}

Затем в конце создания программы java я добавил 1 к счетчику:

topActionlistenersFromFiringOnLoad += 1;

-1
ответ дан kam1l 24 August 2018 в 10:28
поделиться

Что я делаю вместо добавления и удаления прослушивателей действий, у меня есть логическая переменная в моих обработчиках действий, которая истинна, если она должна разрешить действие через или false, если оно должно заблокировать его.

Затем я устанавливаю его в false, когда я делаю некоторые изменения, которые срабатывают при прослушивании действий

JComboBox test = new JComboBox();
test.addActionListener(new ActionListener()
{
  @Override
  public void actionPerformed(ActionEvent e)
  {
    if(testActionListenerActive)
    {
      //runn your stuff here
    }
  }
});

//then when i want to update something where i want to ignore all action evetns:
testActionListenerActive = false;
//do stuff here like add 

SwingUtilities.invokeLater(() -> testActionListenerActive = false);
//and now it is back enabled again
//The reason behind the invoke later is so that if any event was popped onto the awt queue 
//it will not be processed and only events that where inserted after the enable 
//event will get processed.
6
ответ дан LudgerP 24 August 2018 в 10:28
поделиться

Это работает:

/** Implements a Combo Box with special setters to set selected item or
  * index without firing action listener. */
public class MyComboBox extends JComboBox {

/** Constructs a ComboBox for the given array of items. */
public MyComboBox(String[] items) {
  super(items);
}

/** Flag indicating that item was set by program. */
private boolean isSetByProgram;

/** Do not fire if set by program. */
protected void fireActionEvent() {
  if (isSetByProgram)
    return;
  super.fireActionEvent();
}

/** Sets selected Object item without firing Action Event. */
public void setSelection(Object item) {
  isSetByProgram = true;
  setSelectedItem(item);
  isSetByProgram = false;
}

/** Sets selected index without firing Action Event. */
public void setSelection(int index) {
  isSetByProgram = true;
  setSelectedIndex(index);
  isSetByProgram = false;
}

}

Примечание. Вы не можете просто переопределить setSelectedItem(...) или setSelectedIndex(...), поскольку они также используются внутри, когда элементы фактически выбраны с помощью действий клавиатуры или мыши пользователя, когда вы не хотите препятствовать запуску слушателей.

1
ответ дан Martin Serrano 24 August 2018 в 10:28
поделиться

Чтобы определить, следует ли выполнять различные методы в действии. Методы интерфейса интерфейса (actionPerformed () блоков кода) используют setActionCommand () для исходных компонентов (combo1 или combo2).

Для вашего примера перед добавлением элементов в combo2 вызовите setActionCommand («doNothing») и защитите свой метод comboBoxActionPerformed ().

Вот компилируемый пример, который использует этот принцип для того, чтобы один комбо установил выбранный индекс комбо, также отображая String в JTextField. Используя setActionCommand () и защищая блок кода comboActionPerformed (), JTextField будет циклически перебирать каждое слово в wordBank. Если метод comboActionPerformed () не был защищен или если actionCommand String не была изменена, будет активировано 2 actionEvents, а textField пропустит слова.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

/** @author PianoKiddo */
public class CoolCombos extends JPanel {
    JComboBox<String> candyCombo;
    JComboBox<String> flavorCombo;
    JTextField field;
    String[] wordBank;
    int i = 0;

CoolCombos() {
    super();
    initComponents();
    addComponentsToPanel();
}

private void initComponents() {
    initCombos();
    initTextField();
}

private void initCombos() {
    ActionListener comboListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            comboActionPerformed(e);
        }
    }; 
    String[] candyList = {"Sourpatch", "Skittles"};
    String[] flavorList = {"Watermelon", "Original"};
    candyCombo = new JComboBox<>(candyList);
    candyCombo.addActionListener(comboListener);
    flavorCombo = new JComboBox<>(flavorList);
    flavorCombo.addActionListener(comboListener);
}

private void initTextField() {
    wordBank = new String[]{"Which", "Do", "You", "Like", "Better?"};
    field = new JTextField("xxxxx");
    field.setEditable(false);
    field.setText(wordBank[i]);
}

private void addComponentsToPanel() {
    this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    this.add(candyCombo);
    this.add(flavorCombo);
    this.add(field);
}

public void comboActionPerformed(ActionEvent e) {
    String command = e.getActionCommand();
    if (!command.equals("doNothing")) {
        JComboBox combo = (JComboBox) e.getSource();
        if (combo.equals(candyCombo)) {
            setOtherComboIndex(candyCombo, flavorCombo); }
        else {
            setOtherComboIndex(flavorCombo, candyCombo); }
        displayText(); //replace here for toDo() code
    }
}

private void setOtherComboIndex(JComboBox combo, JComboBox otherCombo) {
    String command = otherCombo.getActionCommand();
    otherCombo.setActionCommand("doNothing"); //comment this line to skip words.
    otherCombo.setSelectedIndex(combo.getSelectedIndex());
    otherCombo.setActionCommand(command);
}

private void displayText() {
    i++; 
    String word;
    if (i > 4) { i = 0; }
    word = wordBank[i]; 
    field.setText(word);
    this.repaint();
}

/**
 * Create the GUI and show it.  For thread safety,
 * this method should be invoked from the
 * event-dispatching thread.
 */
private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("CoolCombos");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Create and set up the content pane.
    JComponent newContentPane = new CoolCombos();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);

    //Display the window.
    frame.pack();
    frame.setMinimumSize(frame.getSize());
    frame.setVisible(true);
}

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}

}
0
ответ дан PianoKiddo 24 August 2018 в 10:28
поделиться

Более чистый способ заключается в использовании лямбда-выражений следующим образом:

do(comboBox, () -> comboBox.setSelectedItem("Item Name"));

Для того, чтобы вышеприведенное работало, вам нужен следующий метод:

public static void do(final JComboBox<String> component, final Runnable f) {
    final ActionListener[] actionListeners = component.getActionListeners();
    for (final ActionListener listener : actionListeners)
        component.removeActionListener(listener);
    try {
        f.run();
    } finally {
        for (final ActionListener listener : actionListeners)
            component.addActionListener(listener);
    }
}
2
ответ дан Saeid Nourian 24 August 2018 в 10:28
поделиться

попробуйте следующее:

       indicatorComboBox = new JComboBox() {

        /**
         * Do not fire if set by program.
         */
        protected void fireActionEvent() {
            // if the mouse made the selection -> the comboBox has focus
            if(this.hasFocus())
                super.fireActionEvent();
        }
    };
0
ответ дан slowbear 24 August 2018 в 10:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: