Java - JPanel - 使用数组列表绘制文本文件的内容 - 仅在第一次有效

Java - JPanel - painting contents of a text file with an arraylist - Only works the first time

我有一个带有 JMenuBar 的程序。 JMenuBar 内部有一个 JButton,JButton 打开一个包含 2 个 JMenuItem 的 JMenu。当您单击其中一项时,它会打开第二个 JFrame,并逐行打印文本文件的内容。

如果您 select 其他选项(在同一个 session 中),它应该更改 JFrame 标题(这行得通),并打印其他文本文件的内容(这行不通)没用)。

我已经查明了问题所在,但我不知道为什么会出现这个问题。发生的事情是代码在第一次显示文本文件的内容时完美运行。但是,第二次它不会更改文本。

我第二次发现的东西在评论中有描述。从 setDocument 方法开始,然后转到 paintComponent 方法。

这是有问题的 class(该程序还有其他几个 class,但问题仅在这个 class 中)...

package PeriodicTable;

import javax.swing.JPanel;

import java.util.ArrayList;

import java.io.IOException;
import java.io.FileReader;
import java.io.BufferedReader;

import java.awt.Graphics;
import java.awt.Color;

import java.lang.Override;

class DocumentPanel extends JPanel {
private ArrayList<String> aryDocument;
DocumentPanel(){
    super();
    setBackground(Color.white);
}
@Override
protected void paintComponent(Graphics gr){
    super.paintComponent(gr);
    //aryDocument holds the contents of the old text file (should have the contents of the other text file)
    for(int index = 0; index < aryDocument.size(); index++){
        //enters loop, re-prints the old document
        gr.drawString(aryDocument.get(index), 5, (index + 1)*10);
    }
}
public void setDocument(String strFileDirectory){ //places contents of text file in an array (line by line)

    //aryDocument is null at this time
    aryDocument = new ArrayList<String>();
    //aryDocument is empty at this time
    try(BufferedReader reader = new BufferedReader(new FileReader(strFileDirectory))){
        for(String strLine; (strLine = reader.readLine()) != null; ){
            aryDocument.add(strLine);
        }
        reader.close();
    }catch(IOException ioe){
        ioe.printStackTrace();
    }
    //aryDocument holds the contents of the other text file
    this.revalidate();
}
}

以下方法在 class 中称为 Table(Table 实现 ActionListener)。此方法由 actionPerformed 调用,它使用 ActionCommand 值来确定什么操作执行什么操作。

private void loadTextFile(String strName, String strFileDirectory){
    DocumentPanel clsDocumentPanel = new DocumentPanel();
    if(frmDocument == null){
        frmDocument = new JFrame(strName);
        frmDocument.setPreferredSize(new Dimension(600, 700));
        clsDocumentPanel.setDocument(strFileDirectory);
        frmDocument.add(clsDocumentPanel);
        frmDocument.pack();
        frmDocument.setVisible(true);
    }else{
        if(!(frmDocument.getTitle().equals(strName))){
            frmDocument.setTitle(strName);
            clsDocumentPanel.setDocument(strFileDirectory);
            frmDocument.pack();
            frmDocument.setVisible(true);
        }
    }
}

我重新检查了 strFileDirectory 并确认它们是正确的值。

我在使用什么versions/programs/etc?

Java 8

记事本

命令提示符

我的问题说的很清楚了...

为什么 aryDocument 的值在进入 paintComponent 时没有改变(加载其他文本文件后)?我该如何解决?

这里,

DocumentPanel clsDocumentPanel = new DocumentPanel(); // <- yes, here!
if(frmDocument == null){
    frmDocument = new JFrame(strName);
    frmDocument.setPreferredSize(new Dimension(600, 700));
    clsDocumentPanel.setDocument(strFileDirectory);
    frmDocument.add(clsDocumentPanel);
    frmDocument.pack();
    frmDocument.setVisible(true);
}else{
    if(!(frmDocument.getTitle().equals(strName))){
        frmDocument.setTitle(strName);
        clsDocumentPanel.setDocument(strFileDirectory);
        frmDocument.pack();
        frmDocument.setVisible(true);
    }
}

每次执行该操作时,您都会创建一个 DocumentPanel 的新实例。第一次添加到 frmDocument。第二次你只需调用 setDocument 并让它被垃圾收集。第一个实例(实际上附加到显示的框架)永远不会更新。

所以,要么

  • 单独存储clsDocumentPanel,就像你存储frmDocument一样,不是作为局部变量;
  • 使 frmDocument 成为一个 JFrame 子类,公开对其文档面板的访问并调用 frmDocument.getDocumentPanel().setDocument(...)——但这违反了得墨忒尔定律;
  • 或使 frmDocument 成为一个 JFrame 子类,该子类具有 setDocument 方法,该方法仅委托给其面板的 setDocument,然后只需调用 frmDocument.setDocument(...)