2016-03-27 60 views
1

我創建什麼基本上我是副本的Excel。用戶將數據輸入到JTable中,然後對數據進行分析,處理,然後顯示適當類型的Cell的toString()方法,這是我爲其創建了幾個子類的接口。顯示備用toString()與自定義單元格編輯器的方法

當用戶開始編輯FormulaCell時,我希望單元格顯示由getFormula()方法檢索的公式,而不是由toString()方法檢索的評估公式。

我探討了自定義單元格編輯器,但我找不出要覆蓋哪種方法。我覺得代碼將是這樣一個自定義單元格編輯器或任何我需要內部創建:

if (cell instanceof FormulaCell) { 
    startingText = (FormulaCell) cell).getFormula(); 
} 

JTable中每個單元都有不同的類,所以我真的不能覆蓋的DefaultTableModel的getColumnClass中()方法併爲公式單元格類設置一個自定義單元格編輯器。

供參考,這是我計劃的主要部分:

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); 
      } 
     } 
    } 
} 

如何創建所需的行爲的任何指導,將不勝感激。

回答

4

定義一個方法,例如getDetailedText(),在Cell接口中返回將在單元格編輯器中使用的文本。然後在FormulaCell中返回此方法的公式。對於其他單元格,您可以返回toString()

電池接口:

public interface Cell { 

    public String getDetailedText(); 
} 

FormulaCell:

public class FormulaCell implements Cell { 

    public String getDetailedText() { 
     return formula; 
    } 
} 

其他細胞(如果你想顯示每個小區的其他文字只是回到這裏):

public class OtherCell implements Cell { 

    public String getDetailedText() { 
     return toString(); 
    } 
} 

然後創建一個單元格編輯器並將其設置爲表格的默認編輯器。

默認單元格編輯:

public class MyDefaultCellEditor extends DefaultCellEditor { 
    public MyDefaultCellEditor() { 
     super(new JTextField()); 
    } 

    @Override 
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, 
      int column) { 
     JTextField textField = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column); 
     Cell cell = (Cell) value; 

     textField.setText(cell.getEditorText()); 
     return textField; 
    } 
} 

設置表:

table.setDefaultEditor(Object.class, new MyDefaultCellEditor()); 
+0

當我運行它時,getTableCellEditorComponent(...)方法不休自稱,造成的StackOverflowError。這可能也可能沒有幫助,但我使用了一個名爲TableCellListener的自定義單元偵聽器,我在Java Tips Weblog上找到了這個偵聽器。 – traviata

+0

我只是忘了添加'super.'。現在更新了該部分。 – rdonuk

+1

太棒了;修復它!唯一的另一個複雜情況是,對super的調用需要被轉換爲JTextField。 – traviata

相關問題