2015-05-01 1 views
0

Я написал графический интерфейс с использованием SWING API.Как избежать исключения IndexOutOfBounds при динамическом обновлении JComboBox

Я получил набор форм, каждая форма помогает пользователю создать предопределенный тип объекта. По завершении пользователь подтверждает создание нажатием кнопки JButton.

У меня есть класс (DataManager), который следует за одноэлементным рисунком. Кроме того, класс следует за наблюдателем и фабрикой. DataManager является наблюдаемым объектом. Данные, которые наблюдаются в следующем формате:

public static List<Target> targets = new ArrayList<Target>(); 

DataManager класс содержит набор методов для создания типа предварительного определения объекта.
Пример:

public static final void createTarget(String id, double x, double y, double z){ 
    targets.add(new Target(id,x,y,z)); 
    notifyTargetObservers(); 
} 

Одной из форм является объектом наблюдатель, который наблюдает DataManager за обновлениями в любой из данных, содержащихся в его списках (Ex список целей ....).

IObserve:

public interface IObserve { 
public void updateTargets(); 
public void updateSources(); 
public void updateFluids(); 
} 

Наблюдатель реализует методы, введенные в IObserver.
Пример:

@Override 
public void updateTargets(){ 
cbAnalysisTargets.addItem(DataManager.targets.get(DataManager.targets.size()-1)); 
    } 

В cbAnalysisTargets является JComboBox, который требует, чтобы быть динамически обновляется, как новые объекты вводятся в окружающую среду.
IObservable:

public abstract class IObservable { 
private static Set<IObserve> targetObservers = new HashSet<IObserve>(); 
private static Set<IObserve> sourceObservers = new HashSet<IObserve>(); 
private static Set<IObserve> fluidObservers = new HashSet<IObserve>(); 

public final void addTargetObserver(IObserve o){ 
    targetObservers.add(o); 
} 

public final void addSourceObserver(IObserve o){ 
    sourceObservers.add(o); 
} 

public final void addFluidObserver(IObserve o){ 
    fluidObservers.add(o); 
} 


public static final void notifyTargetObservers(){ 
    for(IObserve observer : targetObservers){ 
     observer.updateTargets(); 
    } 
} 

public static final void notifySourceObservers(){ 
    for(IObserve observer : sourceObservers){ 
     observer.updateSources(); 
    } 
} 

public static final void notifyFluidObservers(){ 
    for(IObserve observer : fluidObservers){ 
     observer.updateFluids(); 
    } 
    } 
} 

Проблема лежит в IndexOutOfBounds Exception. Исключение возникает в следующем сценарии:
1. Пользователь открывает первую форму и успешно инициирует создание 2 заранее определенных объектов одного и того же типа.
2. Пользователь открывает вторую форму; заполняет форму и после подтверждения (щелчок кнопки) получает исключение, указанное ниже.

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

Исключение:

Исключение в потоке "АВТ-EventQueue-0" java.lang.IndexOutOfBoundsException: Индекс: 1, размер: 1 в java.util.ArrayList.rangeCheck (Unknown Source) в java.util.ArrayList.get (Неизвестный источник) at fprof.application.data.frame.manager.content.AnalysisCreatorPanel.updateSources (AnalysisCreatorPanel.java:99) at fprof.application.utility.IObservable.notifySourceObservers (IObservable.java : 32) at fprof.application.data.manager.IDataManager.createSource (IDataManager.java:29) at fprof.application.dat a.frame.manager.content.SourceCreatorPanel $ 1.actionPerformed (SourceCreatorPanel.java:127) в javax.swing.AbstractButton.fireActionPerformed (Unknown Source) в javax.swing.AbstractButton $ Handler.actionPerformed (Unknown Source) в javax.swing.DefaultButtonModel.fireActionPerformed (Unknown Source) в javax.swing.DefaultButtonModel.setPressed (Unknown Source) в javax.swing.plaf.basic.BasicButtonListener.mouseReleased (Unknown Source) в java.awt.Component.processMouseEvent (Unknown Source) в javax.swing.JComponent. processMouseEvent (Неизвестный источник) at java.awt.Component.processEvent (Неизвестный источник) at java.awt.Container.processEvent (Неизвестный источник) at java.awt.Component.dispatchEventImpl (Неизвестный источник)в java.awt.Container.dispatchEventImpl (Unknown Source) в java.awt.Component.dispatchEvent (Unknown Source) в java.awt.LightweightDispatcher.retargetMouseEvent (Unknown Source) в java.awt.LightweightDispatcher.processMouseEvent (Неизвестно Источник) на java.awt.LightweightDispatcher.dispatchEvent (Unknown Source) в java.awt.Container.dispatchEventImpl (Unknown Source) в java.awt.Window.dispatchEventImpl (Unknown Source) в java.awt.Component.dispatchEvent (Неизвестный источник) at java.awt.EventQueue.dispatchEventImpl (Неизвестный источник) at java.awt.EventQueue.access $ 500 (Неизвестный источник) at java.awt.EventQueue $ 3.run (Неизвестный источник) на java.awt.EventQueue $ 3.run (Unknown Source) в java.security.AccessController.doPrivileged (Native Method) в java.security.ProtectionDomain $ 1.doIntersectionPrivilege (Unknown Source) в java.security.ProtectionDomain $ 1. doIntersectionPrivilege (Unknown Source) в java.awt.EventQueue $ 4.run (Unknown Source) в java.awt.EventQueue $ 4.run (Unknown Source) в java.security.AccessController.doPrivileged (метод родной) на Java. security.ProtectionDomain $ 1.doIntersectionPrivilege (Unknown Source) в java.awt.EventQueue.dispatchEvent (Unknown Source) в java.awt.EventDispatchThread.pumpOneEventForFilters (Unknown Source) в java.awt.EventDispatchThread.pumpEventsForFilt эр (Unknown Source) в java.awt.EventDispatchThread.pumpEventsForHierarchy (Unknown Source) в java.awt.EventDispatchThread.pumpEvents (Unknown Source) в java.awt.EventDispatchThread.pumpEvents (Unknown Source) в java.awt. EventDispatchThread.run (Unknown Source)

EDIT 1: updateSource Метод:

@Override 
    public void updateSources(){ 
     cbAnalysisSources.addItem(DataManager.sources.get(DataManager.sources.size()-1)); 
    } 

ответ

0

Некоторые введение в основной отладки в Eclipse, потому что это очень важно и будет так почти все ваши ошибки и ошибки. Очень много Eclipse может вам помочь, но я покажу вам только основы, и вы можете читать и исследовать оттуда. Тем не менее это будет полезно.

Я сделал простой кусок кода для работы на:

public class Example { 

    public static void main(String[] args) { 

     int[] array = new int[] {12, 14, 523, 5423, 12, 0 ,14, -3, 521, 2}; 
     int pos = 0; 
     for (int i = 0; i < 16; i++) { 
      array[i] = -1; 
      pos = increment(pos); 
     } 
    } 

    static int increment(int pos) { 

     int num = pos + 1; 
     return num; 
    } 
} 

Если вы запустите его, он будет бросать ArrayIndexOutOfBoundsException. Чтобы отлаживать, нам нужно установить точку останова где-то в коде, где мы думаем, что проблема начинается, возможно, рядом с строкой, которая выбрала исключение. Идея точки останова заключается в том, что код перестанет работать, когда он достигнет линии, которая была отмечена точкой останова.Точки останова вводятся двойным щелчком на левой панели в редакторе рядом с соответствующей строкой (см. Красный круг). Вы можете ввести несколько точек останова в разных местах. Затем нажмите кнопку Debug (желтый круг). Убедитесь, что это не кнопка Run, потому что это будет игнорировать точки останова.

enter image description here

Вам будет принято на перспективу Debug, которая предлагает различные точки зрения (мои взгляды перестраиваются от значения по умолчанию):

enter image description here

То, что вы видите здесь:

  1. Просмотреть список всех переменных (включая поля, массивы и т. Д.) И их значение. Для объектов (экземпляров классов и массивов) у вас будет стрелка расширения, чтобы отобразить их классы и свойства. Всякий раз, когда происходит смена одного из этих значений, он будет выделен желтым цветом.
  2. Отображает значения выбранной линии, как показано выше. Некоторые объекты длинны и сложны, поэтому удобно видеть их там.
  3. Обычный редактор, но с маркером, который показывает вам, где находится код. Скоро мы поговорим об этом. Здесь код находится в точке останова, потому что здесь он остановится в первый раз.
  4. Просто консоль, чтобы увидеть отпечатки.
  5. Информация о потоках. Когда вы запускаете многопоточные программы, он будет перечислять все потоки и их состояние. Здесь вы увидите, что нить main равна suspended по причине breakpoint at line 9, что и должно быть.

Теперь на «самой отладочной». Вы найдете много опции в меню Run, но полезные из них являются:

  • F6 - step over: это будет перейти к следующей строке в коде в то время как метод пропуск вызовов.
  • F5 - step into: это перейдет к следующей строке кода и будет вводить вызовы методов. Обратите внимание, что если у вас есть JDK (или JRE с подключенным источником), то будет шаг в библиотеки Oracle, который обычно не является чем-то, что вы хотите. Иногда их код очень сложный, и если вы продолжаете входить в него, вы, возможно, никогда не вернетесь ...
  • F8 - resume: это запустит код до достижения следующей точки останова. Например, это может быть одна и та же точка останова в редакторе, если вы работаете в цикле.
  • F7 - step return: это запустит код до тех пор, пока не вернется текущий метод (если применимо).
  • Ctrl-R - run to line: это запустит код до линии, на которой вы разместили каретку.

Демонстрация:

  1. Нажмите F5 из F6, вы увидите, что в силу 1, переменная i была добавлена, так как он создавал в то время цикла. Его значение равно 0.
  2. Нажмите F5 из F6, вы увидите желтый блик на [0] из array с его новым значением -1, присвоенным в коде (вы должны иметь переменный массив расширены).
  3. Нажмите F6 (сделайте F5 следующую итерацию), теперь pos подсвечивается, так как метод присвоил ему новое значение. Отладчик вернется в цикл.
  4. Повторите шаги 1 и 2, i и array[1] изменится.
  5. Нажмите F5, вы будете приняты в increment. Обратите внимание, что отображается только локальная переменная pos, так как все остальные переменные выходят за рамки.
  6. Нажмите F5 из F6, пока не дойдете до петли (линия 9) еще раз. Вы будете исключены из метода. Обратите внимание, как изменился pos.
  7. Нажмите F8, код запустит полную итерацию и снова остановится в точке останова. Обратите внимание, что значения изменены.
  8. Поместите свою каретку по строке 17 и нажмите Ctrl+R. Код будет работать до строки 17, как бы перешагнув все, пока не будет достигнуто.
  9. Press F7, код будет работать до increment. pos не будет обновляться до следующего шага, но i подсвечивается, так как это первый раз, когда у вас есть возможность увидеть изменения, сделанные в цикле for (строка 9).
  10. Продолжайте выполнение кода с F8, в конце концов вы заметите, что он останавливается в строке 10. Это связано с тем, что исключение будет выбрано в этой строке, если вы продвигаетесь дальше. Это автоматическая точка останова, чтобы предупредить вас об исключении.
  11. Нажмите F6 один раз, если у вас есть код, вы попадете в код Oracle в классе Thread метод dispatchUncaughtException.
  12. Снова нажмите F6, исключение будет выброшено, и программа завершится. Это тот этап, на котором вы были бы, если бы вы просто запускали код нормально. Теперь, однако, вы сможете точно определить, какие переменные изменились, когда и как, так понимая, почему выбрано исключение, и где проблема намного проще.

Попробуйте запустить отладчик в более сложных ситуациях, пока вы не почувствуете себя комфортно с ним. Вы можете изменить pos на номер i, чтобы сделать программу более интересной. Это

Как избежать исключения IndexOutOfBounds.

Если у вас есть какие-либо вопросы, оставьте комментарий.

Смежные вопросы