Java: 尝试通过右键单击 JTable 弹出窗口打开文本文件

Java: trying to open a text file with a right-click on JTable popup

当我右键单击 JTable 中的一行时,我很难打开文本文件。我目前正在使用 JOptionPane.showMessageDialog 来显示文本文件,但它不起作用。

我遇到的错误是:

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
 at java.util.Arrays.copyOf(Unknown Source)
at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(Unknown Source)
at java.lang.AbstractStringBuilder.appendNull(Unknown Source)
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at RowPopup.actionPerformed(JtableTest.java:183)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access0(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)

这是我的代码:

import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class JtableTest {

public static void main(String[] args) {
    Runnable r = new Runnable() {

        public void run() {
            new JtableTest ().createUI();
        }
    };

    EventQueue.invokeLater(r);
}

void createUI() {

    try {
        JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());
        
        JTable table = new JTable();

        String readLine = null;

      
        File file = new File ("JtableTestDB.txt");

        FileReader reader = new FileReader(file);
        BufferedReader bufReader = new BufferedReader(reader);//Need to close this

        List<Dentry> dataList = new ArrayList<Dentry>();
        while ((readLine = bufReader.readLine()) != null) {
            String[] splitData = readLine.split(";");

            Dentry dentry = new Dentry();
            dentry.setName(splitData[0]);
            dentry.setNumbers(Arrays.copyOfRange(splitData, 1, splitData.length));
            dataList.add(dentry);
        }

        DatabaseTableModel tableModel = new DatabaseTableModel();
        tableModel.setList(dataList);////////////
        table.setModel(tableModel);
    
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JScrollPane(table));
        frame.setTitle("File to JTable");
        frame.pack();
        frame.setVisible(true);
        
        final RowPopup pop=new RowPopup(table);
        table.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent me)
            
            {
                //determine if right clicked
                if(SwingUtilities.isRightMouseButton(me))
                {
                    pop.show(me.getComponent(), me.getX(), me.getY());
                }
            }
        });
    } catch(IOException ex) {}
}

class Dentry {

    private String name;
    private String[] number;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNumber(int index) {
        String value = null;
        if (index >= 0 && index < number.length) {
            value = number[index];
        }
        return value;
    }

    public void setNumbers(String... number) {
        this.number = number;
    }
}

class DatabaseTableModel extends AbstractTableModel {

    
    private List<Dentry> list = new ArrayList<Dentry>();
    private String[] columnNames = {"1", "2", "3", "4", "5", "6"};

    public void setList(List<Dentry> list) {
        this.list = list;
        fireTableDataChanged();
    }

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

    public int getRowCount() {
        return list.size();
    }

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

    public Object getValueAt(int rowIndex, int columnIndex) {
        switch (columnIndex) {
            case 0:
                return list.get(rowIndex).getName();

         
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:                 
                return list.get(rowIndex).getNumber(columnIndex - 1);//return list.get(rowIndex).getNumber(columnIndex);

            default:
                return null;

        }
    }
}
    }
//public class PopupInRows extends JFrame {
//  public PopupInrows()

class RowPopup extends JPopupMenu {
 public RowPopup(JTable table) {
    JMenuItem view=new JMenuItem("View all Moves");
    
    //When View is clicked
    view.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            //JOptionPane.showMessageDialog(view, "View");
            try
            { 
            String filetext="",filecontent="";

            File file=new File("JtableTestDB2.txt");
            FileReader fr=new FileReader(file);
            BufferedReader br=new BufferedReader(fr);
            StringBuilder sb=new StringBuilder();
            while(fr !=null)
            {
                   filetext=br.readLine();
                   sb.append(filetext);
                   sb.append("\n");
            }
            filecontent=sb.toString();
            JOptionPane.showMessageDialog(null,"File is"+filecontent);

            }
            catch(Exception ex){}
        }
    });
    //Add Items to Popup
    add(view);
    //add(new Jseparator()); //this would make a line and sep 
 }
}

问题出在谓词 fr != null 上。因为 fr 不是 null,循环永远不会结束,直到内存耗尽。相反,检查 filetext,这将是 null "if the end of the stream has been reached."

Is there anyway to have it not display null after the text?

是的,使用阅读 TableModel 时使用的相同成语。

while ((filetext = br.readLine()) != null) {
    sb.append(filetext);
    sb.append("\n");
}

顺便说一句,不要丢弃异常;记录它们或至少打印它们。

} catch (Exception ex) {
    ex.printStackTrace(System.err);
}

而不是 MouseListener,将 TablePopupEditor 视为 CellEditor

Is there a limit on how many characters the message box can show?

使用滚动代替限制,example

]3