Ich erstelle, was ich im Grunde Kopie von Excel bin. Der Benutzer gibt Daten in eine JTable ein, dann werden diese Daten analysiert, verarbeitet und es wird die toString() - Methode für den entsprechenden Zellentyp angezeigt, bei dem es sich um eine Schnittstelle handelt, für die ich mehrere Unterklassen erstellt habe.Anzeige alternative toString() -Methode mit benutzerdefinierten Zelle Editor
Wenn ein Benutzer beginnt, ein FormulaCell zu bearbeiten, möchte ich, dass die Zelle die Formel anzeigt, die von einer getFormula() - Methode abgerufen wird, und nicht die ausgewertete Formel, die von der toString() -Methode abgerufen wird.
Ich erkunde benutzerdefinierte Zelleditoren, aber ich konnte nicht herausfinden, welche Methode zu überschreiben. Ich denke, dass der Code so etwas wie dieses innerhalb eines benutzerdefinierten Zellen-Editor sein würde oder was ich schaffen müssen:
if (cell instanceof FormulaCell) {
startingText = (FormulaCell) cell).getFormula();
}
Jede Zelle in der JTable eine andere Klasse hat, so kann ich nicht wirklich überschreiben DefaultTableModel des getColumnClass() Methode und legen Sie einen benutzerdefinierten Zelleneditor für die Formula Cell-Klasse fest.
als Referenz, hier ist der Hauptteil meines Programms:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import cell.*;
public class Program extends JPanel {
private DefaultTableModel model;
private JTable table;
public static final int ASCII_SHIFT = 64, HEIGHT = 10, WIDTH = 7, ROW_HEIGHT = 40;
public static final Dimension BUTTON_SIZE = new Dimension(70,30),
TABLE_SIZE = new Dimension(780, 400);
//makes program runnable
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
//sets title and does everything necessary to
//create and show the GUI
JFrame frame = new JFrame("TextExcel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Program contentPane = new Program();
contentPane.setOpaque(true);
frame.setContentPane(contentPane);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
public Program() {
//sets the layout
super(new BorderLayout());
//creates a String[] for column headers
String[] letter = new String[WIDTH];
for (int i = 0; i < letter.length; i++) {
byte[] character = {(byte) (i + ASCII_SHIFT + 1)};
letter[i] = new String(character);
}
//creates the table
model = new DefaultTableModel(letter, HEIGHT);
table = new JTable(model);
//makes a cell parse the input when enter is pressed
Action action = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
TableCellListener tcl = (TableCellListener)e.getSource();
int row = tcl.getRow();
int column = tcl.getColumn();
String input = (String) model.getValueAt(row, column);
parse(input, row, column);
}
};
@SuppressWarnings("unused")
TableCellListener tcl = new TableCellListener(table, action);
//centers the headers
JTableHeader header = table.getTableHeader();
header.setDefaultRenderer(new HeaderRenderer(table));
header.setReorderingAllowed(false);
//centers text in cells
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
table.setDefaultRenderer(Object.class, centerRenderer);
//sets the height of rows
for (int i = 0; i < HEIGHT; i++) {
table.setRowHeight(i, ROW_HEIGHT);
}
//creates a scroll-pane for the table and numbers the rows
JScrollPane scrollPane = new JScrollPane(table);
JTable rowTable = new RowNumberTable(table);
scrollPane.setRowHeaderView(rowTable);
scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, rowTable.getTableHeader());
add(scrollPane);
//sizes the table
table.setFillsViewportHeight(true);
table.setPreferredScrollableViewportSize(TABLE_SIZE);
//creates a panel to place buttons
JPanel buttonPanel = new JPanel(new FlowLayout());
//creates a button to clear the table
JButton clearButton = new JButton("clear");
clearButton.setPreferredSize(BUTTON_SIZE);
clearButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
clearTable();
}
});
buttonPanel.add(clearButton);
//message displayed when help button is pressed
String helpMessage = "To construct a Cell, double click a cell, "
+ "enter the argument, and press enter.\n"
+ "To clear a Cell, press the \"clear\" button.\n\n"
+ "There are 5 subclasses of Cell:\n"
+ "StringCell, DateCell, NumberCell, "
+ "FormulaCell, and SumAvgCell.\n"
+ "All numbers are displayed as Fractions and all Cells displaying numbers extend\n"
+ "NumberCell. Any double entered will be converted to a Fraction.\n\n"
+ "* StringCells display text and are simply typed into the cell. If an input is\n"
+ "invalid for all other types of Cell, it will become a StringCell.\n"
+ "* DateCells display dates in the form (Month Day, Year). They are constructed\n"
+ "in the form (m/d/yy) or (m/d/yyyy). Extra zeroes in m and d are not necessary.\n"
+ "* NumberCells simply display Fractions and can be constructed from a double,\n"
+ "int, standard fraction, or mixed fraction.\n"
+ "* FormulaCells are constructed from any combination of operations(+-*/%),\n"
+ "values, parantheses, and references. Order of operations is supported. An\n"
+ "example of a valid input would be \"(A1 + 4.4 * b3) % C2 - 3_6/8\".\n"
+ "* SumAvgCells can be used to find the sum or average of a rectangular area of\n"
+ "cells. They are constructed in the form (command reference - reference).\n"
+ "The first reference is the top-left corner and the second reference is the\n"
+ "bottom-right corner. An example of a valid input would be \"sum A1 - B2\".\n"
+ "Another valid input would be \"avg C1 - C8\".";
//creates a help button to display a helpful message
JButton helpButton = new JButton("help");
helpButton.setPreferredSize(BUTTON_SIZE);
helpButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(getComponent(0), helpMessage, "HelpBox", 1);
}
});
buttonPanel.add(helpButton);
//creates a panel to place the table
JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.add(scrollPane, BorderLayout.CENTER);
//adds the button and table panels
add(tablePanel, BorderLayout.NORTH);
add(buttonPanel, BorderLayout.SOUTH);
}
//parses user input to set a cell value
public void parse(String input, int row, int column) {
//initializes cell to be set
Cell cell = null;
//helpful variables
String ref = "([a-g]\\d*)";
String dub = "([-+]?\\d*\\.?\\d*)";
String frac = "((\\d+_\\d+/\\d+)|(\\d+/\\d+))";
//parses the input according to regular expressions
input = input.toLowerCase();
if (input.matches("(" + ref + "|" + dub + "|" + frac + ")"
+ "([-+*/%] (" + ref + "|" + dub + "|" + frac + "))+")) {
cell = new FormulaCell(input, model);
}
else if (input.matches("((sum)|(avg)) " + ref + " - " + ref)) {
cell = new SumAvgCell(input, model);
}
else if (input.matches(dub + "|" + frac)) {
cell = new NumberCell(input);
}
else if (input.matches("(\\d{1}|\\d{2})/(\\d{1}|\\d{2})/(\\d{2}|\\d{4})")) {
cell = new DateCell(input);
}
else {
cell = new StringCell(input);
}
//sets the cell value
model.setValueAt(cell, row, column);
}
//sets all cell values to null
public void clearTable() {
for (int i = 0; i < HEIGHT; i++) {
for(int j = 0; j < WIDTH; j++) {
model.setValueAt(null, i, j);
}
}
}
}
Alle Hinweise, wie das gewünschte Verhalten erzeugen würden sehr geschätzt werden.
Als ich es lief, die getTableCellEditorComponent (...) Methode selbst endlos genannt, in einem Stackoverflow führt. Dies kann hilfreich sein oder nicht, aber ich verwende einen benutzerdefinierten Cell Listener namens TableCellListener, den ich im Java Tips Weblog gefunden habe. – traviata
Ich habe gerade den Zusatz "Super" vergessen. Jetzt aktualisiert diesen Teil. – rdonuk
Großartig; das hat es behoben! Die einzige andere Komplikation war, dass der Aufruf von super in ein JTextField umgewandelt werden musste. – traviata