Как сохранить данные JTable на JMenuItem нажмите - PullRequest
0 голосов
/ 12 января 2019

У меня уже есть JTable с прикрепленной к нему табличной моделью MyTableModel. У меня есть метод tableChanged(), который записывает данные таблицы в файл data.csv во время изменения ячейки таблицы. Это означает, что данные таблицы записываются в файл каждый раз, когда пользователь вводит новые данные. Вместо этого я хочу, чтобы был пункт меню, в котором пользователь нажимает «Сохранить», а затем переходит к коду, который сохраняется в файл.

@Override
public void tableChanged(TableModelEvent e) {
    int row = e.getFirstRow();
    int column = e.getColumn();
    TableModel model = (TableModel) e.getSource();
    String columnName = model.getColumnName(column);
    Object data = model.getValueAt(row, column);

    BufferedWriter bw = null;
    FileWriter fw = null;
    String rivi = "";
    try {
        fw = new FileWriter("data.csv");
        bw = new BufferedWriter(fw);

        for (int i = 0; i < model.getRowCount(); i++) {
            for (int j = 0; j < model.getColumnCount(); j++) {
                if (j == 69) {
                    rivi += model.getValueAt(i, j);
                } else {
                    rivi += model.getValueAt(i, j) + ",";
                }
            }
            if (i != 69) {
                rivi += "\n";
            }
        }
        bw.write(rivi);
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        try {
            if (bw != null) {
                bw.close();
            }
            if (fw != null) {
                fw.close();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

Мне нужно, если я правильно понял, переместить код сохранения файла из метода tableChanged() в метод actionPerformed(), но я не знаю, как получить параметр TableModelEvent e из tableChanged() метод и использовать его в методе actionPerformed(), чтобы я мог получить данные таблицы через TableModel model = (TableModel) e.getSource() и сохранить их в файл.

@Override
public void actionPerformed(ActionEvent e) {
    // File saving code here?
}

Полный код здесь:

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedWriter;
import java.io.FileWriter;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import static sun.misc.ClassFileTransformer.add;



public class DesktopEsimerkki extends JPanel
        implements TableModelListener, ActionListener {

    protected JTable table = null;
    protected TableModel model = null;

    public DesktopEsimerkki() {
        super(new GridLayout(1, 0));

        table = new JTable(new MyTableModel());
        table.setFillsViewportHeight(true);
        table.getModel().addTableModelListener(this);

        add(new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

        this.model = table.getModel();
    }

    @Override
    public void tableChanged(TableModelEvent e) {}

    @Override
    public void actionPerformed(ActionEvent e) {
        BufferedWriter bw = null;
        String rivi = "";
        FileWriter fw = null;
        try {
            fw = new FileWriter("data.csv");
            bw = new BufferedWriter(fw);

            for (int i = 0; i < model.getRowCount(); i++) {
                for (int j = 0; j < model.getColumnCount(); j++) {
                    if (j == 69) {
                        rivi += model.getValueAt(i, j);
                    } else {
                        rivi += model.getValueAt(i, j) + ",";
                    }
                }
                if (i != 69) {
                    rivi += "\n";
                }
            }
            System.out.println(rivi);
            bw.write(rivi);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (bw != null) {
                    bw.close();
                }
                if (fw != null) {
                    fw.close();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    public JMenuBar luoValikkoPalkki() {
        JMenuBar valikkopalkki = new JMenuBar();
        JMenu valikko = new JMenu("File");
        valikko.setMnemonic(KeyEvent.VK_F);
        valikko.getAccessibleContext().setAccessibleDescription(
                "File Saving MEnu");
        valikkopalkki.add(valikko);

        JMenuItem valikkoitem = new JMenuItem("Save", KeyEvent.VK_S);
        valikkoitem.setAccelerator(KeyStroke.getKeyStroke(
                java.awt.event.KeyEvent.VK_S, ActionEvent.CTRL_MASK));
        valikko.add(valikkoitem);
        valikkoitem.addActionListener(this);
        return valikkopalkki;
    }

    class MyTableModel extends AbstractTableModel {

        private String[] columnNames = {"Col 1", "Col 2", "Col 3"};
        private Object[][] data = {{"Data 1", "Data 2", "Data 3"}};

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public int getRowCount() {
            return data.length;
        }

        @Override
        public String getColumnName(int col) {
            return columnNames[col];
        }

        @Override
        public Object getValueAt(int row, int col) {
            return data[row][col];
        }

        @Override
        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        @Override
        public boolean isCellEditable(int row, int col) {
            return true;
        }

        @Override
        public void setValueAt(Object value, int row, int col) {
            data[row][col] = value;
            fireTableCellUpdated(row, col);
        }
    }
    private static void createAndShowGUI() {
        JFrame frame = new JFrame("DesktopEsimerkki");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        DesktopEsimerkki desim = new DesktopEsimerkki();
        frame.setJMenuBar(desim.luoValikkoPalkki());

        DesktopEsimerkki newContentPane = new DesktopEsimerkki();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

1 Ответ

0 голосов
/ 12 января 2019

Ваш код работает, и ваша проблема гораздо более проста: вы создаете слишком много DesktopEsimerkki объектов, один из которых вы изменяете, а другой - значения, которые вы отображаете. Изменить это:

    JFrame frame = new JFrame("DesktopEsimerkki");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // this guy creates the menu
    DesktopEsimerkki desim = new DesktopEsimerkki();
    frame.setJMenuBar(desim.luoValikkoPalkki());

    // but this separate guy is used as the GUI
    DesktopEsimerkki newContentPane = new DesktopEsimerkki();
    newContentPane.setOpaque(true);
    frame.setContentPane(newContentPane);

к этому:

    JFrame frame = new JFrame("DesktopEsimerkki");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // use only one instance for **both**
    DesktopEsimerkki desim = new DesktopEsimerkki();
    frame.setJMenuBar(desim.luoValikkoPalkki());

    // DesktopEsimerkki newContentPane = new DesktopEsimerkki();
    // newContentPane.setOpaque(true);
    // frame.setContentPane(newContentPane);

    // *********** here ***********
    frame.setContentPane(desim);

Просто ради ухмылки я создал собственную программу, которая делает это, что-то вроде:

enter image description here

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Formatter;
import java.util.Scanner;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

@SuppressWarnings("serial")
public class TableFun extends JPanel {
    public static final String DATA_FILE_PATH = "data.csv";
    private MyTableModel model = new MyTableModel();
    private JTable table = new JTable(model);
    private JTextField fileNameField = new JTextField(DATA_FILE_PATH, 30);
    private JMenuBar menuBar;
    private Action writeModelAction = new WriteModelAction(table, "Write to File", this);
    private Action readModelAction = new ReadModelAction(table, "Read from File", this);

    public TableFun() {
        JPanel btnPanel = new JPanel();
        btnPanel.add(new JLabel("File:"));
        btnPanel.add(fileNameField);
        btnPanel.add(new JButton(writeModelAction));
        btnPanel.add(new JButton(readModelAction));

        table.getColumnModel().getColumn(0).setCellRenderer(new TimeColumnRenderer());
        JScrollPane scrollpane = new JScrollPane(table);
        setLayout(new BorderLayout());
        add(scrollpane);
        add(btnPanel, BorderLayout.PAGE_START);
    }

    public String getFileName() {
        return fileNameField.getText();
    }

    public JMenuBar getMenuBar() {
        if (menuBar == null) {
            menuBar = new JMenuBar();
            JMenu fileMenu = new JMenu("File");
            fileMenu.setMnemonic(KeyEvent.VK_F);
            menuBar.add(fileMenu);

            fileMenu.add(new JMenuItem(readModelAction));
            fileMenu.add(new JMenuItem(writeModelAction));
        }
        return menuBar;
    }    

    private static void createAndShowGui() {
        TableFun mainPanel = new TableFun();

        JFrame frame = new JFrame("TableFun");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.setJMenuBar(mainPanel.getMenuBar());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

@SuppressWarnings("serial")
class WriteModelAction extends AbstractAction {
    private ReadWriteTableData readWriteTableData;
    private TableFun tableFun;

    public WriteModelAction(JTable table, String name, TableFun tableFun) {
        super(name);
        int mnemonic = name.charAt(0);
        putValue(MNEMONIC_KEY, mnemonic);
        readWriteTableData = new ReadWriteTableData(table);
        this.tableFun = tableFun;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        File file = new File(tableFun.getFileName());
        if (file.exists()) {
            String message = "File " + tableFun.getFileName() + " already exists -- do you wish to overrite?";
            String title = "File Already Exists";
            int optionType = JOptionPane.YES_NO_OPTION;
            int response = JOptionPane.showConfirmDialog(tableFun, message, title, optionType);
            if (response != JOptionPane.YES_OPTION) {
                return;
            }
        }
        try {
            readWriteTableData.write(file);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }
}

@SuppressWarnings("serial")
class ReadModelAction extends AbstractAction {
    private ReadWriteTableData readWriteTableData;
    private TableFun tableFun;

    public ReadModelAction(JTable table, String name, TableFun tableFun) {
        super(name);
        int mnemonic = name.charAt(0);
        putValue(MNEMONIC_KEY, mnemonic);
        readWriteTableData = new ReadWriteTableData(table);
        this.tableFun = tableFun;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        File file = new File(tableFun.getFileName());
        if (!file.exists()) {
            String message = "File " + tableFun.getFileName() + " cannot be found -- aborting read";
            String title = "File Cannot Be Found";
            int optionType = JOptionPane.WARNING_MESSAGE;
            JOptionPane.showMessageDialog(tableFun, message, title, optionType);
            return;
        }
        try {
            readWriteTableData.read(file);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }
}

class ReadWriteTableData {
    private JTable table;

    public ReadWriteTableData(JTable table) {
        this.table = table;
    }

    public void read(File file) throws FileNotFoundException {
        MyTableModel tableModel = (MyTableModel) table.getModel();
        tableModel.setRowCount(0);
        Scanner scanner = new Scanner(file);
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                String[] tokens = line.split("\\|");
                String[] trimmedTokens = new String[tokens.length];
                for (int i = 0; i < tokens.length; i++) {
                    String text = tokens[i];
                    if (text == null || text.trim().equals("null")) {
                        text = "";
                    } else {
                        text = text.trim();
                    }
                    trimmedTokens[i] = text;
                }
                tableModel.addRow(trimmedTokens);
            }
        }
        table.setModel(tableModel);
        scanner.close();
    }

    public void write(File file) throws IOException {
        FileWriter fileWriter = new FileWriter(file);
        Formatter formatter = new Formatter(fileWriter);
        MyTableModel model = (MyTableModel) table.getModel();
        for (int row = 0; row < model.getRowCount(); row++) {
            for (int col = 0; col < model.getColumnCount(); col++) {
                String value = (String) model.getValueAt(row, col);
                value = value == null ? "" : value;
                formatter.format("%25s ", value);
                if (col != model.getColumnCount() - 1) {
                    formatter.format(" | ");
                }
            }
            formatter.format("%n");
        }
        if (formatter != null) {
            formatter.close();
        }        
    }

}

class MyTableModel extends DefaultTableModel {
    public static final String[] COLUMNS = {"Time", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
    private static final int START_TIME = 8;
    private static final int END_TIME = 17;

    public MyTableModel() {
        super(COLUMNS, 0);
        for (int i = START_TIME; i < END_TIME + 1; i++) {
            Object[] rowData = {String.valueOf(i), "", "", "", "", ""};
            addRow(rowData);
        }
    }

    @Override
    public boolean isCellEditable(int row, int column) {
        return column != 0;
    }
}

class TimeColumnRenderer extends DefaultTableCellRenderer {
    public TimeColumnRenderer() {
        setHorizontalAlignment(SwingConstants.TRAILING);
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column) {
        int time = Integer.parseInt(value.toString());
        time = time > 12 ? time % 12 : time;
        String timeText = String.format("%d:00", time);
        return super.getTableCellRendererComponent(table, timeText, isSelected, hasFocus, row, column);
    }
}

В качестве разделителя csv используется символ канала |, поэтому типичный текстовый файл может выглядеть следующим образом:

                8  |                            |                      judy  |                            |                            |                           
                9  |                      John  |                            |                      Bill  |                            |                     Frank 
               10  |                            |                     Hello  |                            |                   Goodbye  |                           
               11  |               Donald duck  |               Frank Nitti  |                 Al Capone  |                   Johnson  |                           
               12  |                            |                            |                            |                            |                        ss 
               13  |                            |                            |                            |                            |                           
               14  |              Bill Clinton  |              Donald Trump  |                     Hello  |                     Fresh  |                           
               15  |                            |                  What the  |                      heck  |                            |                       Yes 
               16  |                            |                            |                            |                            |                           
               17  |                      Here  |                        we  |                       are  |                            |                           
...