Jidesoft DocumentPane中的java.lang.IndexOutOfBoundsException:索引:1,大小:1
Edit3:这个问题没有重复一般的“我的代码中有indexoutofboundsexception”问题,因为正如答案中明确指出的,这是一个广泛使用的第三方库Jidesoft DocumentPane中的java.lang.IndexOutOfBoundsException:索引:1,大小:1,java,indexoutofboundsexception,repaint,jide,repaintmanager,Java,Indexoutofboundsexception,Repaint,Jide,Repaintmanager,Edit3:这个问题没有重复一般的“我的代码中有indexoutofboundsexception”问题,因为正如答案中明确指出的,这是一个广泛使用的第三方库jide common中的错误,经开发人员确认,下面有一个链接。这个bug最近被修复了(在这个问题发布之后),并且该库的许多旧版本仍然受到影响。因此,这些信息可能对其他开发人员有用,因为他们偶然发现jide common存在同样的问题 我在Java中面临GUI编程问题。我不确定问题的具体来源(仍然无法找到它)-可能是我的错误、jide组件中
jide common
中的错误,经开发人员确认,下面有一个链接。这个bug最近被修复了(在这个问题发布之后),并且该库的许多旧版本仍然受到影响。因此,这些信息可能对其他开发人员有用,因为他们偶然发现jide common存在同样的问题
我在Java中面临GUI编程问题。我不确定问题的具体来源(仍然无法找到它)-可能是我的错误、jide组件中的错误代码,甚至是awt/swing focus或事件处理的错误
以下代码取决于
- jidesoft:jide grids:3.5.1
- com.jidesoft:jide组件:3.5.1
- com.jidesoft:jide common:3.5.1
package com.example;
import com.jidesoft.document.DocumentComponent;
import com.jidesoft.document.DocumentPane;
import com.jidesoft.grid.JideTable;
import com.jidesoft.grid.TableModelWrapperUtils;
import com.jidesoft.grid.TextFieldCellEditor;
import com.jidesoft.swing.JideTabbedPane;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.math.BigDecimal;
import java.util.Random;
/**
* Dependends on:
* com.jidesoft:jide-grids:3.5.1
* com.jidesoft:jide-components:3.5.1
* com.jidesoft:jide-common:3.5.1
*/
public class ModalPopupFailure {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JComponent panel = new ModalPopupFailure().buildPanel();
frame.setContentPane(panel);
frame.setBounds(450, 300, 700, 500);
frame.setVisible(true);
}
/**
* @return table editor panel
*/
private JPanel tableTab() {
JPanel result = new JPanel(new BorderLayout());
DefaultTableModel model = new DefaultTableModel(1, 1);
model.setValueAt(new BigDecimal(0L), 0, 0);
JideTable table = new JideTable(model);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
final int actualCol0 = TableModelWrapperUtils.getActualColumnAt(table.getModel(), 0);
CustomCellEditor bdce = new CustomCellEditor(Integer.class);
table.getColumnModel().getColumn(actualCol0).setCellEditor(bdce);
result.add(table, BorderLayout.CENTER);
return result;
}
/**
* @return Main panel with tabs
*/
private JComponent buildPanel() {
JPanel mainPanel = new JPanel(new BorderLayout());
final DocumentPane documentPane = new DocumentPane();
DocumentComponent dc1 = new DocumentComponent(new JLabel("tab1 label"), "aaa");
documentPane.openDocument(dc1);
DocumentComponent dc2 = new DocumentComponent(tableTab(), "TABLETAB");
documentPane.openDocument(dc2);
documentPane.setActiveDocument("TABLETAB");
documentPane.setTabbedPaneCustomizer(new DocumentPane.TabbedPaneCustomizer() {
@Override
public void customize(final JideTabbedPane tabbedPane) {
tabbedPane.setShowCloseButton(true);
tabbedPane.setUseDefaultShowCloseButtonOnTab(false);
tabbedPane.setShowCloseButtonOnTab(true);
}
});
documentPane.setTabPlacement(SwingConstants.TOP);
mainPanel.add(documentPane, BorderLayout.CENTER);
mainPanel.add(new JButton(new AbstractAction("New tab") {
@Override
public void actionPerformed(ActionEvent e) {
Integer randInt = new Random().nextInt();
DocumentComponent newdc = new DocumentComponent(
new JLabel("Generated tab label " + randInt),
Integer.toString(randInt));
documentPane.openDocument(newdc);
}
}),
BorderLayout.NORTH);
JLabel decription = new JLabel("<html>Steps to reproduce:<br />" +
"TABLETAB should be the last tab<br />" +
"The \"correct\" value for cell editor is 777.<br />" +
"Enter any \"incorrect\" number, then close any tab standing before TABLETAB.<br />" +
"An exception caused by window repaint should be raised by now.<br />" +
"If dialog would not be modal, there would be no window repaint triggered.</html>");
mainPanel.add(decription, BorderLayout.SOUTH);
return mainPanel;
}
private class CustomCellEditor extends TextFieldCellEditor {
boolean firstTime = true;
public CustomCellEditor(Class<?> aClass) {
super(aClass);
_textField.setInputVerifier(new InputVerifier() {
@Override
public boolean verify(JComponent input) {
boolean valid = "777".equals(_textField.getText());
if (valid) return true;
final JDialog dialog = new JDialog();
dialog.setTitle("Exception expected");
dialog.setContentPane(new JLabel("<html>If one of previous tabs was closed, an exception should be raised by now.</html>"));
dialog.setLocationRelativeTo(null);
dialog.setModal(true); // Switching to false seems to fix the problem
dialog.setSize(new Dimension(300, 100));
dialog.setVisible(true);
return true;
}
});
}
@Override
public boolean stopCellEditing() {
System.out.println("Stopping cell edit " + new Random().nextInt() + "in edt: " + SwingUtilities.isEventDispatchThread());
if (firstTime) {
firstTime = false;
return false;
}
return _textField.getInputVerifier().shouldYieldFocus(_textField) && super.stopCellEditing();
}
}
}
这是一个添加了一些调试信息的程序。
我仍然无法找出问题的根源,更不用说修复了。提前谢谢
编辑:好的,我现在知道的一件事是在verify()方法中显示一个对话框:
verify方法的存在只是为了确定输入是否有效,它不应弹出对话框或引起任何其他副作用。shouldYieldFocus方法调用verify,如果值无效,则将其设置为最小值或最大值。应力聚焦法允许产生副作用
因此,我将所有未实际验证的代码移到shouldYieldFocus()。这并没有解决问题,但进一步延迟了带有SwingUtilities.invokeLater()的dialog.show(),似乎工作正常,没有陷阱。。。然而
public CustomCellEditor(Class<?> aClass) {
super(aClass);
_textField.setInputVerifier(new InputVerifier() {
@Override
public boolean shouldYieldFocus(JComponent input) {
boolean inputOK = verify(input);
if (!inputOK) {
final ru.esc.erp.core.components.Dialog dialog = new ru.esc.erp.core.components.Dialog();
dialog.setTitle("Exception may be raised");
dialog.setContentPane(new JLabel("<html>Modal dialog opened with yet another delay.</html>"));
dialog.setLocationRelativeTo(null);
dialog.setModal(true); // false "fixes" the problem
dialog.setSize(new Dimension(300, 100));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
dialog.setVisible(true);
}
});
}
return inputOK;
}
@Override
public boolean verify(JComponent input) {
return "777".equals(_textField.getText());
}
});
}
公共CustomCellEditor(类aClass){
超级(aClass);
_setInputVerifier(新的InputVerifier(){
@凌驾
公共布尔值shouldYieldFocus(JComponent输入){
布尔输入=验证(输入);
如果(!inputOK){
final ru.esc.erp.core.components.Dialog=new ru.esc.erp.core.components.Dialog();
对话框.setTitle(“可能引发异常”);
setContentPane(新的JLabel(“模式对话框再次延迟打开”);
对话框.setLocationRelativeTo(空);
dialog.setModal(true);//false“修复”问题
设置尺寸(新尺寸(300100));
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
对话框.setVisible(true);
}
});
}
返回inputOK;
}
@凌驾
公共布尔验证(JComponent输入){
返回“777”。等于(_textField.getText());
}
});
}
编辑2:好的,那是在吉德塔贝德帕内伊。
我已经用我的示例测试了修补过的jide oss,没有任何例外(不过,现在在关闭选项卡时出现了一些非关键的UI故障)。
找到了问题的根源
编辑:他们后来在3.6.17中修复了此错误:
由JIDE Support提供»2017年2月1日星期三上午12:10
正如你所知,这个bug在刚刚发布的3.6.17中被修复
我更进一步。不再使用DocumentPane、表和单元格编辑器。在JideTabbedPane上只有一个简单的文本字段(如果验证失败,它会显示一个模式对话框)。现在只使用oss库,所以任何人都可以运行这个示例。但是jide-oss-3.5.1的bug仍然存在。jide-oss-3.6.16也是如此。
public CustomCellEditor(Class<?> aClass) {
super(aClass);
_textField.setInputVerifier(new InputVerifier() {
@Override
public boolean shouldYieldFocus(JComponent input) {
boolean inputOK = verify(input);
if (!inputOK) {
final ru.esc.erp.core.components.Dialog dialog = new ru.esc.erp.core.components.Dialog();
dialog.setTitle("Exception may be raised");
dialog.setContentPane(new JLabel("<html>Modal dialog opened with yet another delay.</html>"));
dialog.setLocationRelativeTo(null);
dialog.setModal(true); // false "fixes" the problem
dialog.setSize(new Dimension(300, 100));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
dialog.setVisible(true);
}
});
}
return inputOK;
}
@Override
public boolean verify(JComponent input) {
return "777".equals(_textField.getText());
}
});
}