【发布时间】:2015-07-20 02:39:02
【问题描述】:
我正在开发一个使用 JTable 向用户显示信息的 Swing 程序。该表目前有 700 多个条目,但我发现了一个非常奇怪的错误,似乎可以随机重现。有时JTable 会导致IndexOutOfBoundsException 索引:0,大小:0。我已经多次编译并运行我的程序而没有改变任何东西,这个异常会随机出现,当异常没有出现时,程序行为正常。
我无法为这个问题提供代码,因为它需要超过 10 个文件才能运行。为什么JTable 会发生这种情况?我发现一个程序如何在程序的一次运行期间抛出异常并且在同一程序的另一次运行时不抛出异常而没有代码更改真的很奇怪......是否有任何众所周知的错误导致这种行为程序?
我不确定我应该包含代码的哪些部分,但这里有一些附加信息。
我创建了一个名为PlayerTableModel 的自定义TableModel,用于渲染JTable,数据存储在另一个类中的ArrayLists 中。这是TableModel的代码
public class PlayerTableModel extends AbstractTableModel {
ArrayList<User> users = FileHandler.getAllPlayers();
ArrayList<PlayerSummary.Player> summaries = FileHandler.getAllSummaries();
@Override
public int getColumnCount() {
return 7;
}
@Override
public int getRowCount() {
return users.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
User user = users.get(rowIndex);
switch (columnIndex) {
case 0:
if (user.getSteamId().equalsIgnoreCase(summaries.get(rowIndex).getSteamID())) { // This is line 39
return summaries.get(rowIndex).getPersonaName();
} else {
return null;
}
case 1:
return user.getDateAdded();
case 2:
return user.getDateUpdated();
case 3:
return user.getNumberOfBans();
case 4:
return user.getNumberOfGameBans();
case 5:
return user.getDaysSinceLastBan();
case 6:
return user.getSteamId();
}
return null;
}
public String getColumnName(int columnIndex) {
switch (columnIndex) {
case 0:
return "ID";
case 1:
return "Date added";
case 2:
return "Date updated";
case 3:
return "VAC bans";
case 4:
return "Game bans";
case 5:
return "Last ban (days)";
case 6:
return "64-Bit SteamID";
}
return null;
}
public boolean isCellEditable(int row, int column) {
return false;
}
}
在运行程序时,有时会出现这个异常,这似乎是某种线程问题?
线程“AWT-EventQueue-0”中的异常 java.lang.IndexOutOfBoundsException:索引:0,大小:0 在 java.util.ArrayList.rangeCheck(未知来源)在 java.util.ArrayList.get(未知来源)在 PlayerTableModel.getValueAt(PlayerTableModel.java:39) 在 javax.swing.JTable.getValueAt(Unknown Source) at javax.swing.JTable.prepareRenderer(未知来源)在 javax.swing.plaf.synth.SynthTableUI.paintCell(未知来源)在 javax.swing.plaf.synth.SynthTableUI.paintCells(未知来源)在 javax.swing.plaf.synth.SynthTableUI.paint(Unknown Source) at javax.swing.plaf.synth.SynthTableUI.update(未知来源)在 javax.swing.JComponent.paintComponent(Unknown Source) 在 javax.swing.JComponent.paint(Unknown Source) 在 javax.swing.JComponent.paintChildren(未知来源)在 javax.swing.JComponent.paint(Unknown Source) 在 javax.swing.JViewport.paint(未知来源)在 javax.swing.JComponent.paintChildren(未知来源)在 javax.swing.JComponent.paint(Unknown Source) 在 javax.swing.JComponent.paintChildren(未知来源)在 javax.swing.JComponent.paint(Unknown Source) 在 javax.swing.JComponent.paintChildren(未知来源)在 javax.swing.JComponent.paint(Unknown Source) 在 javax.swing.JComponent.paintChildren(未知来源)在 javax.swing.JComponent.paint(Unknown Source) 在 javax.swing.JComponent.paintToOffscreen(未知来源)在 javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(未知 来源)在 javax.swing.RepaintManager$PaintManager.paint(Unknown 源)在 javax.swing.RepaintManager.paint(未知源)在 javax.swing.JComponent._paintImmediately(Unknown Source) at javax.swing.JComponent.paintImmediately(Unknown Source) at javax.swing.RepaintManager$4.run(Unknown Source) at javax.swing.RepaintManager$4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知 来源)在 javax.swing.RepaintManager.paintDirtyRegions(未知 来源)在 javax.swing.RepaintManager.paintDirtyRegions(未知 来源)在 javax.swing.RepaintManager.prePaintDirtyRegions(未知 来源)在 javax.swing.RepaintManager.access$1300(未知来源)在 javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) at java.awt.event.InvocationEvent.dispatch(未知来源)在 java.awt.EventQueue.dispatchEventImpl(未知来源)在 java.awt.EventQueue.access$500(未知来源)在 java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at 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(Unknown Source) 在 java.awt.EventDispatchThread.run(未知来源)
使用FileHandler类从文件中写入和读取数据:
public class FileHandler implements Serializable {
private static ArrayList<User> tracked = new ArrayList<User>();
private static ArrayList<PlayerSummary.Player> trackedSummaries = new ArrayList<PlayerSummary.Player>();
private static ArrayList<PlayerSummary.Player> trackedSummariesUnsorted = new ArrayList<PlayerSummary.Player>();
private static ArrayList<String[]> games = new ArrayList<String[]>();
private static String savedString = "";
private static String APIKEY = "";
public static void writeToFile(String fileName, Object objToWrite) {
try {
// Write object to file.
FileOutputStream fOS = new FileOutputStream(fileName);
ObjectOutputStream oOS = new ObjectOutputStream(fOS);
oOS.writeObject(objToWrite);
oOS.close();
// Write string to text file so that it can be displayed.
if (fileName.equalsIgnoreCase("apikey.txt")) {
File file = new File(fileName);
PrintWriter pw = new PrintWriter(file);
pw.print(objToWrite);
pw.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void readFromFile(String fileName, String objType) {
FileInputStream fIS;
try {
fIS = new FileInputStream(fileName);
ObjectInputStream oIS = new ObjectInputStream(fIS);
if (objType.equalsIgnoreCase("ArrayList<User>")) {
tracked = (ArrayList<User>) oIS.readObject();
} else if (objType.equalsIgnoreCase("ArrayList<PlayerSummary.Player>")) {
if (fileName.equalsIgnoreCase("summaries.tmp")) {
trackedSummaries = (ArrayList<PlayerSummary.Player>) oIS.readObject();
}
if (fileName.equalsIgnoreCase("s_unsorted.tmp")) {
trackedSummariesUnsorted = (ArrayList<PlayerSummary.Player>) oIS.readObject();
}
} else if (objType.equalsIgnoreCase("ArrayList<String[]>")) {
games = (ArrayList<String[]>) oIS.readObject();
} else if (objType.equalsIgnoreCase("apikey")) {
APIKEY = (String) oIS.readObject();
}else {
System.out.println("Object type " + objType + " needs to be implemented!");
}
oIS.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static ArrayList<User> getAllPlayers() {
return tracked;
}
public static ArrayList<PlayerSummary.Player> getAllSummaries() {
return trackedSummaries;
}
public static ArrayList<PlayerSummary.Player> getAllSummariesUnsorted() {
return trackedSummariesUnsorted;
}
public static ArrayList<String[]> getGames() {
return games;
}
public static String getAPIKey() {
try {
BufferedReader br = new BufferedReader(new FileReader("apikey.txt"));
APIKEY = br.readLine();
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(BanTracker.getFrames()[0], "File not found! Did you save your API key?");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return APIKEY;
}
public static void updateArrayList(ArrayList<User> a) {
tracked = a;
}
}
【问题讨论】:
-
根据我的经验,发生这种情况是因为您正在从除 EDT 之外的线程中更改
TableModel。我在使用某种TableRowSorter时特别看到了这一点 -
“我觉得很奇怪一个程序如何在程序的一次运行期间抛出异常,而不在同一程序的另一次运行中抛出异常而无需更改代码” - 你能说“你好比赛条件”
-
如果没有 runnable example 来证明您的问题,这一切都是猜测,这不是代码转储,而是您正在做的一个示例,它突出了您遇到的问题。这将导致更少的混乱和更好的响应
-
@MadProgrammer 我以前没有使用过线程,我没有在我的程序中启动任何新线程。此外,我不确定如何使用代码的高亮部分重现此问题,因为我不确定是哪个部分导致它。
-
正如我所说,不知道错误是如何产生的或者你的代码是如何工作的,这一切都只是猜测。我们使用
JTableALOT(有时使用 1, 000 行)并且在人们开始从 EDT 外部弄乱模型/表格之前没有任何问题
标签: java swing exception jtable