2016-06-10 4 views
0

J'ai un programme avec un JMenuBar. À l'intérieur du JMenuBar a un JButton, le JButton ouvre un JMenu qui a 2 JMenuItems. Lorsque vous cliquez sur l'un des éléments, il ouvre une deuxième JFrame et imprime le contenu d'un fichier texte ligne par ligne.Java - JPanel - peindre le contenu d'un fichier texte avec un arraylist - Ne fonctionne que la première fois

Si vous sélectionnez l'autre option (dans la même session), il devrait changer le titre JFrame (cela fonctionne), et imprimer le contenu de l'autre fichier texte (cela ne fonctionne pas).

J'ai repéré le problème, mais je n'ai aucune idée de la raison de ce problème. Ce qui se passe est que le code fonctionne parfaitement la première fois qu'il affiche le contenu du fichier texte. Cependant, la deuxième fois, cela ne change pas le texte.

Ce que j'ai trouvé pendant la deuxième fois est décrit dans les commentaires. Commencez par la méthode setDocument, puis passez à la méthode paintComponent.

Voici la classe la question (il y a plusieurs autres classes pour le programme, mais la question est uniquement dans cette classe) ...

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

La méthode suivante est dans une classe appelée Table (Table implémente ActionListener). Cette méthode est appelée par actionPerformed, qui utilise la valeur ActionCommand pour déterminer quelle action fait quoi.

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

J'ai revérifié strFileDirectory et confirmé que les valeurs sont correctes.

Quelles versions/programmes/etc utilisez-vous?

Java 8

Bloc-notes

invite de commande

Ma question clairement ...

Pourquoi ne pas la valeur de aryDocument changer quand il passe en paintComponent (après le chargement de l'autre fichier texte)? Comment puis-je le réparer?

+0

Qui (quel thread) appelle 'setDocument'? –

+0

Le système de threads par défaut, je n'ai rien fait en utilisant des threads avec ce programme. En ce qui concerne le chemin qui mène à setDocument, lorsque vous cliquez sur JMenuItem, une méthode actionPerformed trie ActionCommands pour déterminer ce qu'il faut faire. Ceci est fait dans une classe différente. – Tyler

+0

Attendez, vous dites que vous appelez 'setDocument', * puis * paintComponent' est appelé et il a l'ancienne valeur de' setDocument', tout dans un seul thread? –

Répondre

3

Ici,

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

vous créez une nouvelle instance de DocumentPanel chaque fois que l'action est effectuée. La première fois que vous l'ajoutez à frmDocument. La deuxième fois que vous appelez simplement setDocument dessus et laissez-le être ramassé. La première instance (réellement attachée à l'image affichée) n'est jamais mise à jour.

Alors, que ce soit

  • magasin clsDocumentPanel quelque part séparément, comme vous stockez frmDocument, pas comme une variable locale;
  • faire frmDocument une sous-classe JFrame qui expose l'accès à son panneau de document et appelle frmDocument.getDocumentPanel().setDocument(...) - mais cela enfreint la loi de Demeter;
  • ou de faire frmDocument une sous-classe JFrame qui a une méthode setDocument qui délègue simplement à setDocument de son panneau, alors il suffit d'appeler frmDocument.setDocument(...).
+0

J'ai déplacé la création de la référence DocumentPanel en dehors de la méthode, et la création de l'instance dans le constructeur de Table, mais le problème persiste. Je continuerai à obtenir System.outs et les résultats de la commande dans l'OP. – Tyler

+0

Annuler ce dernier commentaire, une modification que j'ai effectuée précédemment a interféré avec le correctif. Après avoir annulé cette modification, ça fonctionne bien maintenant.Merci pour l'aide! – Tyler