动态更新 JComboBox 时如何避免 IndexOutOfBounds 异常(调试帮助) [英] How-to avoid IndexOutOfBounds Exception when Dynamically Updating JComboBox (Debugging help)

查看:33
本文介绍了动态更新 JComboBox 时如何避免 IndexOutOfBounds 异常(调试帮助)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 SWING API 编写了一个 GUI.

I wrote a GUI using SWING API.

我得到了一组表单,每个表单都帮助用户创建一个预定义类型的对象.完成后,用户通过单击 JButton 来确认创建.

I got a set of forms, each form assists the user to create a pre-defined type of object. Upon completion, the user confirms creation by a click of a JButton.

我有一个遵循单例模式的类 (DataManager).此外,该类遵循观察者和工厂模式.DataManager 是一个可观察对象.观察到的数据格式如下:

I got a class (DataManager) that follows a singleton pattern. Additionally, the class follows an observer and factory patterns. The DataManager is an observable object. The data which is observed is in following format:

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

DataManager 类包含一组方法来创建对象的预定义类型.
示例:

DataManager class holds a set of methods to create a pre-define type of an object.
Example:

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

其中一种形式是观察者对象,它观察 DataManager 以获取其列表中保存的任何数据(例如列表目标...)的更新.

One of the forms is an observer object which observes DataManager for updates in any of the data held in its lists (Ex. list targets...).

IObserve:

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

观察者实现了IObserver中介绍的方法.
示例:

The observer implements the methods introduced in IObserver.
Example:

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

cbAnalysisTargets 是一个 JComboBox,需要在新对象引入环境时动态更新.
IObservable:

The cbAnalysisTargets is a JComboBox which requires to be updated dynamically as new objects are introduced into the environment.
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 异常.在以下情况下会出现异常:
1. 用户打开第一个表单并成功创建 2 个相同类型的预定义对象.
2. 用户打开第二个表单;填写表格并在确认后(单击按钮)收到如下所述的例外情况.

The issue lays in IndexOutOfBounds Exception. The exception crops up in a following scenario:
1. The user opens first form and successfuly initiates creation of 2 pre-defined objects of the same type.
2. The user opens second form; fills out the form and upon confirmation (click of a button) receives an exception stated bellow.

理想情况下,我希望在解决以下问题和解决下面所述的异常方面得到协助.

Ideally, I would like to be assisted in addressing following issue and resolving the exception stated bellow.

异常:

线程AWT-EventQueue-0"中的异常java.lang.IndexOutOfBoundsException:索引:1,大小:1在 java.util.ArrayList.rangeCheck(Unknown Source)在 java.util.ArrayList.get(Unknown Source)在 fprof.application.data.frame.manager.content.AnalysisCreatorPanel.updateSources(AnalysisCreatorPanel.java:99)在 fprof.application.utility.IObservable.notifySourceObservers(IObservable.java:32)在 fprof.application.data.manager.IDataManager.createSource(IDataManager.java:29)在 fprof.application.data.frame.manager.content.SourceCreatorPanel$1.actionPerformed(SourceCreatorPanel.java:127)在 javax.swing.AbstractButton.fireActionPerformed(来源不明)在 javax.swing.AbstractButton$Handler.actionPerformed(来源不明)在 javax.swing.DefaultButtonModel.fireActionPerformed(来源不明)在 javax.swing.DefaultButtonModel.setPressed(来源不明)在 javax.swing.plaf.basic.BasicButtonListener.mouseReleased(来源不明)在 java.awt.Component.processMouseEvent(Unknown Source)在 javax.swing.JComponent.processMouseEvent(Unknown Source)在 java.awt.Component.processEvent(来源不明)在 java.awt.Container.processEvent(来源不明)在 java.awt.Component.dispatchEventImpl(未知来源)在 java.awt.Container.dispatchEventImpl(未知来源)在 java.awt.Component.dispatchEvent(来源不明)在 java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)在 java.awt.LightweightDispatcher.processMouseEvent(来源不明)在 java.awt.LightweightDispatcher.dispatchEvent(来源不明)在 java.awt.Container.dispatchEventImpl(未知来源)在 java.awt.Window.dispatchEventImpl(未知来源)在 java.awt.Component.dispatchEvent(来源不明)在 java.awt.EventQueue.dispatchEventImpl(未知来源)在 java.awt.EventQueue.access$500(来源不明)在 java.awt.EventQueue$3.run(未知来源)在 java.awt.EventQueue$3.run(未知来源)在 java.security.AccessController.doPrivileged(Native Method)在 java.security.ProtectionDomain$1.doIntersectionPrivilege(来源不明)在 java.security.ProtectionDomain$1.doIntersectionPrivilege(来源不明)在 java.awt.EventQueue$4.run(未知来源)在 java.awt.EventQueue$4.run(未知来源)在 java.security.AccessController.doPrivileged(Native Method)在 java.security.ProtectionDomain$1.doIntersectionPrivilege(来源不明)在 java.awt.EventQueue.dispatchEvent(来源不明)在 java.awt.EventDispatchThread.pumpOneEventForFilters(来源不明)在 java.awt.EventDispatchThread.pumpEventsForFilter(未知来源)在 java.awt.EventDispatchThread.pumpEventsForHierarchy(来源不明)在 java.awt.EventDispatchThread.pumpEvents(来源不明)在 java.awt.EventDispatchThread.pumpEvents(来源不明)在 java.awt.EventDispatchThread.run(Unknown Source)

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 at java.util.ArrayList.rangeCheck(Unknown Source) at java.util.ArrayList.get(Unknown Source) 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.data.frame.manager.content.SourceCreatorPanel$1.actionPerformed(SourceCreatorPanel.java:127) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.setPressed(Unknown Source) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$500(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)

编辑 1:更新源方法:

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

推荐答案

对 Eclipse 中基本调试的一些介绍,因为这非常重要并且可以解决您几乎所有的错误和错误.Eclipse 可以为您提供很多帮助,但我只会向您展示基础知识,您可以从那里阅读和探索.尽管如此,它还是很有用的.

Some introduction to basic debugging in Eclipse, because this is super important and would solve almost all of your errors and bugs. There is a lot Eclipse can help you with, but I'll show you just the basics and you can read and explore from there. It will be useful nonetheless.

我编写了一段简单的代码来处理:

I made a simple piece of code to work on:

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 按钮,因为它会忽略断点.

If you run it, it will throw an ArrayIndexOutOfBoundsException. To debug, we will need to set a breakpoint somewhere in the code where we think the problem starts at, possibly close to the line that thrown the exception. The idea behind a breakpoint, is that the code will stop running when it reaches the line which was marked with a breakpoint. Breakpoints are entered by doubleclicking on the left bar in the editor next to the appropriate line (see red circle). You can enter several breakpoints at different places. Then, click on the Debug button (yellow circle). Make sure it's not the Run button, because that will ignore breakpoints.

然后您将进入调试透视图,它提供了不同的视图(我的视图是从默认视图重新排列的):

You will then be taken to the Debug perspective, which offers different views (my views are rearranged from the default):

您在这里看到的是:

  1. 查看列出所有变量(包括字段、数组等)及其值.对于对象(类实例和数组),您将有一个展开箭头来显示它们的类成员和属性.每当其中一个值发生 c 变化时,它就会以黄色突出显示.
  2. 在上面的视图中显示所选行的值.有些对象又长又复杂,所以在那里查看很方便.
  3. 普通编辑器,但带有一个高亮显示代码所在的位置.很快我们就会谈到这个.此处代码位于断点处,因为这是它第一次停止的地方.
  4. 只需控制台即可查看打印件.
  5. 有关线程的信息.当您运行多线程程序时,它会列出所有线程及其状态.在这里,您将看到线程 main挂起,原因是 breakpoint at line 9,这就是它应该的样子.
  1. View listing all the variables (including fields, arrays etc.) and their value. For objects (class instances and arrays), you will have an expand arrow to show their class members and properties. Whenever there is a c change in one of those values, it will be highlighted in yellow.
  2. Displays the values of the selected line the view above. Some objects are long and complicated, so it's handy to see it there.
  3. The normal editor, but with a highlighter that shows you where the code is at. Soon we will talk about that. Here the code is at the breakpoint, because this is where it will stop for the first time.
  4. Just the console to see prints.
  5. Information about threads. When you run multi-thread programs, it will list all the threads and their state. Here you will see that the thread main is suspended with the reason breakpoint at line 9, which is what it's supposed to be.

现在进入调试本身".您会在 Run 菜单下找到许多选项,但有用的是:

Now onto the "debugging itself". You will find many option under the Run menu, but the useful ones are:

  • F6 - step over:这将前进到代码中的下一行同时跳过方法调用.
  • F5 - step into:这将前进到代码中的下一行,将进入方法调用.请注意,如果您有 JDK(或附带源代码的 JRE),它进入 Oracle 的库,这通常不是您想要的.有时他们的代码非常复杂,如果你继续深入下去,你可能永远不会回来......
  • F8 - resume:这将运行代码直到到达下一个断点.例如,如果您在循环中运行,它可以是编辑器中的相同断点.
  • F7 - step return:这将运行代码直到当前方法返回(如果适用).
  • Ctrl-R - run to line:这将运行代码直到您放置插入符号的行.
  • F6 - step over: this will advance to the next line in the code while skipping method calls.
  • F5 - step into: this will advance to the next line in the code and will enter method calls. Note that if you have the JDK (or the JRE with source attached), it will step into Oracle's libraries, which is usually not something you want. Sometimes their code is very complicated and if you continue stepping into it you might never come back...
  • F8 - resume: this will run the code until the next breakpoint is reached. It can be the same breakpoint in the editor if you are running in a loop, for example.
  • F7 - step return: this will run the code until the current method returns (if applicable).
  • Ctrl-R - run to line: this will run the code until the line where you placed the caret at.

演示:

  1. F6F5,你会看到在视图1中,变量i被添加,因为它是在while循环中创建的.其值为 0,如分配.
  2. F6F5,你会看到array[0]有黄色高亮它的新值 -1 在代码中分配(您必须扩展数组变量).
  3. F6(将执行F5 下一次迭代),现在pos 突出显示,因为该方法为其分配了一个新值.调试器将运行回循环.
  4. 重复步骤 1 和 2,iarray[1] 会发生变化.
  5. F5,进入增量.请注意,仅显示了 局部变量 pos,因为所有其他变量都超出了范围.
  6. F6F5 直到再次到达循环(第 9 行).您将被带出该方法.观察 pos 如何改变.
  7. F8,代码将运行一次完整的迭代并再次停在断点处.请注意值已更改.
  8. 将插入符号放在第 17 行,然后按 Ctrl+R.代码将一直运行到第 17 行,就像遍历所有内容直到到达.
  9. F7,代码会一直运行直到increment返回.pos 直到下一步才会更新,但是 i 被突出显示,因为这是您第一次有机会看到 for 中所做的更改代码> 循环(第 9 行).
  10. 继续使用F8 运行代码,最终您会注意到它停在第 10 行.这是因为如果继续前进,将在该行抛出异常.这是一个自动断点,用于提醒您有关异常的信息.
  11. 按一次F6,如果您附加了代码,您将被带到Thread 类方法dispatchUncaughtException 中的Oracle 代码.
  12. 再次按F6,将抛出异常并终止程序.如果您只是正常运行代码,这就是您所处的阶段.但是,现在您将能够准确地看到哪些变量在何时以及如何更改,因此更容易了解抛出异常的原因以及问题所在.
  1. Press F5 of F6, you will see that in view 1, the variable i was added since it was creating in the while loop. Its value is 0 as assigned.
  2. Press F5 of F6, you will see a yellow highlight on the [0] of array with its new value -1 as assigned in the code (you have to have the array variable expanded).
  3. Press F6 (will do F5 next iteration), now pos is highlighted since the method assigned a new value to it. The debugger will run back to the loop.
  4. Repeat steps 1 and 2, i and array[1] will change.
  5. Press F5, you will be taken into increment. Note that the only the local variable pos is shown since all other variables are out of scope.
  6. Press F5 of F6 until you reach the loop (line 9) again. You will be taken out of the method. Observe how pos changed.
  7. Press F8, the code will run a full iteration and stop at the breakpoint again. Note the values changed.
  8. Put your caret at line 17 and press Ctrl+R. The code will run until line 17 as if stepping over everything until it is reached.
  9. Press F7, the code will run until increment returns. pos will not be updated until the next step, but i is highlighted since it's the first time you have an opportunity to see the change made in the for loop (line 9).
  10. Continue running the code with F8, eventually you will notice that it stops at line 10. This is because an exception will be thrown at this line if you advance any further. It is an automatic breakpoint to alert you about the exception.
  11. Press F6 once, if you have code attached you will be taken to Oracle's code in class Thread method dispatchUncaughtException.
  12. Press F6 again, the exception will be thrown and the program will terminate. This is the stage you would be at if you just ran the code normally. Now, however, you will be able to see exactly which variables changed when and how, so understanding why the exception is thrown and where the problem is is much easier.

尝试在更复杂的情况下运行调试器,直到您对它感到满意为止.您可以将 pos 更改为 i 以使程序更有趣.这是

Try running the debugger in more complicated situations until you feel comfortable with it. You can change pos to i to make the program a bit more interesting. This is

如何避免 IndexOutOfBounds 异常.

How-to avoid IndexOutOfBounds Exception.

如果您有任何问题,请发表评论.

If you have any questions leave a comment.

这篇关于动态更新 JComboBox 时如何避免 IndexOutOfBounds 异常(调试帮助)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆