所以我有一个可编辑的Jtable(实际上是TreeTable)和一个自定义模型。需要更新当前的setValueAt方法以防止大于某个数量的值(取决于行)。
这很容易防止(如果值无效,则不设置值)但是通知用户所选数量无效的最佳方法是什么?从模型中弹出一个对话框似乎很讨厌。
答案 0 :(得分:3)
从模型中弹出一个对话框似乎很讨厌。
同意。使用列的自定义编辑器。也许是这样的:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class TableEdit extends JFrame
{
TableEdit()
{
JTable table = new JTable(5,5);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollpane = new JScrollPane(table);
getContentPane().add(scrollpane);
// Use a custom editor
TableCellEditor fce = new FiveCharacterEditor();
table.setDefaultEditor(Object.class, fce);
}
class FiveCharacterEditor extends DefaultCellEditor
{
FiveCharacterEditor()
{
super( new JTextField() );
}
public boolean stopCellEditing()
{
JTable table = (JTable)getComponent().getParent();
try
{
String editingValue = (String)getCellEditorValue();
if(editingValue.length() != 5)
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
textField.selectAll();
textField.requestFocusInWindow();
JOptionPane.showMessageDialog(
null,
"Please enter string with 5 letters.",
"Alert!",JOptionPane.ERROR_MESSAGE);
return false;
}
}
catch(ClassCastException exception)
{
return false;
}
return super.stopCellEditing();
}
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
Component c = super.getTableCellEditorComponent(
table, value, isSelected, row, column);
((JComponent)c).setBorder(new LineBorder(Color.black));
return c;
}
}
public static void main(String [] args)
{
JFrame frame = new TableEdit();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
答案 1 :(得分:1)
一旦用户输入无效值,将典型单元格或文本的背景更改为一些引人注目的颜色(深红色或类似的东西)......我认为这将是最简单的。
答案 2 :(得分:0)
另一种解决方案是:
我将逐步完成以下几点:
您可以在下面找到我自定义CellEditor的完全可编辑代码。如果输入的值不在特定范围内,编辑器会向屏幕发布警告框。
import java.awt.Color;
import javax.swing.AbstractAction;
import javax.swing.DefaultCellEditor;
import javax.swing.JFormattedTextField;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.Component;
import java.awt.Toolkit;
import java.text.NumberFormat;
import java.text.ParseException;
import javax.swing.border.LineBorder;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.NumberFormatter;
/**
*
* This class ensures that the Mark entered
* in the Marks column is of the correct format
* and within the correct range.<p>
*
* In the event that there is an incorrect format/value entered,
* an alert box will appear instructing the user same.
* Implements a cell editor that uses a formatted text field
* to edit Integer values.<p>
*
* When instantiated, the object essentially is listening for
* any events with regards to it's associated table i.e.
* first 100 table etc.
*
* @author Mark Burleigh
* @version %I%, %G%
* @since 1.0
*/
public class MarksColumnEditor extends DefaultCellEditor
{
JFormattedTextField ftf;
NumberFormat integerFormat;
private Integer minimum, maximum;
private boolean DEBUG = false;
public MarksColumnEditor(int min, int max)
{
super(new JFormattedTextField());
ftf = (JFormattedTextField)getComponent();
minimum = new Integer(min);
maximum = new Integer(max);
//Set up the editor for the integer cells.
integerFormat = NumberFormat.getIntegerInstance();
NumberFormatter intFormatter = new NumberFormatter(integerFormat);
intFormatter.setFormat(integerFormat);
/**
*
* NumberFormatter inherits setMinimum and setMaximum
* from class Class InternationalFormatter
*
* setMinimum() - Sets the minimum permissible value.
* setMaximum() - Sets the maximum permissible value.
*
* @see https://docs.oracle.com/javase/7/docs/api/javax/swing/text/InternationalFormatter.html#setMaximum(java.lang.Comparable)
*
*/
//
intFormatter.setMinimum(minimum);
intFormatter.setMaximum(maximum);
ftf.setFormatterFactory(
new DefaultFormatterFactory(intFormatter));
ftf.setValue(minimum);
ftf.setHorizontalAlignment(JTextField.TRAILING);
ftf.setFocusLostBehavior(JFormattedTextField.PERSIST);
//React when the user presses Enter while the editor is
//active. (Tab is handled as specified by
//JFormattedTextField's focusLostBehavior property.)
ftf.getInputMap().put(KeyStroke.getKeyStroke(
KeyEvent.VK_ENTER, 0),
"check");
ftf.getActionMap().put("check", new AbstractAction()
{
public void actionPerformed(ActionEvent e) {
if (!ftf.isEditValid()) { //The text is invalid.
if (userSaysRevert()) { //reverted
ftf.postActionEvent(); //inform the editor
}
} else try { //The text is valid,
ftf.commitEdit(); //so use it.
ftf.postActionEvent(); //stop editing
} catch (java.text.ParseException exc) { }
}
});
}
/**
*
* This method is implicitly used as soon as
* a MarksColumnEditor object is instantiated
* e.g. inside in the Eas_Main.java
* somJTableColumn.setCellEditor(
* new MarksColumnEditor(aMinMark,aMaxMark));
* <p>
* It overrides the same method in the DefaultCellEditor
*
*
* @param table - the JTable that is asking the editor to edit; can be null
* @param value - the value of the cell to be edited; it is up to the specific
* editor to interpret and draw the value. For example, if value is the string
* "true", it could be rendered as a string or it could be rendered as a check
* box that is checked. null is a valid value
* @param isSelected - true if the cell is to be rendered with highlighting
* @param row - the row of the cell being edited
* @param column - the column of the cell being edited
*
* @return Component - the component for editing
*
* @see https://docs.oracle.com/javase/7/docs/api/javax/swing/table/TableCellEditor.html
*
*/
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected,
int row, int column)
{
JFormattedTextField ftf =
(JFormattedTextField)super.getTableCellEditorComponent(
table, value, isSelected, row, column);
ftf.setValue(value);
ftf.setFont(new java.awt.Font("Tahoma", 1, 15));
ftf.setBorder(new LineBorder(Color.BLUE));
// ftf.setBackground(Color.LIGHT_GRAY);
// ftf.setBackground(new Color(204,255,204));
ftf.setBackground(new Color(219,254,219));
return ftf;
}
/**
*
* This overrides the method located in DefaultCellEditor.
* This method is never implicitly called by the developer.
* The method ensures that the value entered is an integer
*
*
* @param
* @param
*
* @return Object - the integer value entered by the user
* into the particular cell
*
* @see https://docs.oracle.com/javase/7/docs/api/javax/swing/CellEditor.html#getCellEditorValue()
*
*/
public Object getCellEditorValue()
{
JFormattedTextField ftf = (JFormattedTextField) getComponent();
Object o = ftf.getValue();
if(o != null)
{
if (o instanceof Integer)
{
return o;
}
else if (o instanceof Number)
{
return new Integer(((Number)o).intValue());
}
else
{
if (DEBUG)
{
System.out.println("getCellEditorValue: o isn't a Number");
}
if(o == null)
{
System.out.println();
System.out.println("Object o = null");
System.out.println();
}
try
{
return integerFormat.parseObject(o.toString());
}
catch (ParseException exc)
{
System.err.println("getCellEditorValue: can't parse o: " + o);
return null;
}
}
}// end if o != null
return null; // if the value in the cell is null and is left unchanged
// then the value null is return to the cell
}
/**
* Override to check whether the edit is valid,
* setting the value if it is and complaining if
* away, we need to invoke the superclass's version
* of this method so that everything gets cleaned up.
*
*
* @return {boolean} true - let the editor go away
*
* @see
*
*/
public boolean stopCellEditing() {
JFormattedTextField ftf = (JFormattedTextField)getComponent();
if (ftf.isEditValid()) {
try {
ftf.commitEdit();
} catch (java.text.ParseException exc) { }
} else { //text is invalid
if (!userSaysRevert()) { //user wants to edit
return false; //don't let the editor go away
}
}
return super.stopCellEditing();
}
/**
* Lets the user know that the text they entered is
* bad. Returns true if the user elects to revert to
* the last good value. Otherwise, returns false,
* indicating that the user wants to continue editing.
*
* @return {boolean} true - referred to the previous Mark
*
*/
protected boolean userSaysRevert()
{
Toolkit.getDefaultToolkit().beep();
ftf.selectAll();
if (maximum !=0)
{
Object[] options = {"Edit",
"Revert"};
int answer = JOptionPane.showOptionDialog(
SwingUtilities.getWindowAncestor(ftf),
"The Mark must be an number between "+ minimum + " and "+ maximum + ".\n"
+"You can either continue editing or revert to the\n"
+"last valid Mark entered.",
"Invalid Mark",
JOptionPane.YES_NO_OPTION,
JOptionPane.ERROR_MESSAGE,
null,
options,
options[1]);
if (answer == 1) { //Revert!
ftf.setValue(ftf.getValue());
return true;
}
}
else
{
JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ftf),
"You must press the save button first",
"Alert",
JOptionPane.ERROR_MESSAGE
);
ftf.setValue(null);
ftf.repaint();
return true; //revert to empty mark
}
return false;
}
}
获取您想要使用自定义CellEditor的JTable的特定列。此代码在您的GUI类中实现,例如
TableColumn marks_column_A = first_100_Table.getColumnModel().getColumn(2);
将您的自定义CellEditor附加到JTable的特定列。此代码在您的GUI类中实现(setCellRenderer()方法位于Class TableColumn中)例如。
mark_column_A.setCellRenderer(new MarksColumnEditor(0,300));
产生的结果 您可以在下面找到使用上述代码的JTable的屏幕截图。每当用户输入一个小于0(最小值)或大于300(最大值)的数字时,就会出现一个警告框,勾勒出错误值的用户。
答案 3 :(得分:0)