Datenplotter Datei öffnen

schiese

Erfahrenes Mitglied
Hallo,

ich habe mein Plotprogramm um einen JFileChooser erweitert, um Dateien einlesen zu können. Die Dateien werden auch hochgeladen und auch angezeigt. Allerdings erscheint die JMenuBar dann doppelt. Wenn ich anfangs Daten plotte und dann eine Datei öffne, werden beide Datensätze angezeigt UND die JMenuBar ist doppelt gezeichnet, wie der Rest auch. Ich habe als Verduetlichung mal ein Screenshot angehängt.

Java:
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

public class Start extends JFrame implements ActionListener {
   private static final long serialVersionUID = -3330800293328098089L;
  
   JPanel panel;
   JMenuBar jmenubar;
   JMenu jmenu;
   JMenuItem jmenuitem;
  
   Inhalt inhalt;
  
   public Start()
   {
     inhalt = new Inhalt();
    
     jmenubar = new JMenuBar();
     jmenu = new JMenu("Datei");
     jmenubar.add(jmenu);
     jmenuitem = new JMenuItem("Datei Öffnen");
     jmenuitem.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e) {
         inhalt.dateiEinlesen();  
       }  
     });
     jmenu.add(jmenuitem);
     jmenuitem = new JMenuItem("Bild speichern");
     jmenu.add(jmenuitem);
     jmenuitem = new JMenuItem("Daten speichern");
     jmenu.add(jmenuitem);
     jmenuitem = new JMenuItem("Beenden");
     jmenuitem.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent e) {
         System.exit(0);  
       }  
     });
     jmenu.add(jmenuitem);
    
     jmenu = new JMenu("Bearbeiten");
     jmenubar.add(jmenu);
     jmenuitem = new JMenuItem("Fitten");
     jmenu.add(jmenuitem);

     this.setSize(new Dimension(800,600));
     this.setLocationRelativeTo(null);
     this.setBackground(Color.white);
     Container c = this.getContentPane();
     c.add(inhalt);
     this.setJMenuBar(jmenubar);
     this.setVisible(true);
   }

   public static void main(String[] args)
   {
     new Start();
   }
  
   public void actionPerformed(ActionEvent arg0) {}
}

Java:
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;

import javax.swing.JFileChooser;
import javax.swing.JPanel;

public class Inhalt extends JPanel {
   private static final long serialVersionUID = -1617380958931060319L;

   private double abstandWerteXAchse;
   private double abstandWerteYAchse;
  
   private final int abstandBeschriftungXAchse = 5;
  
   private double yMax = 0;
  
   private final int abstandGitterRand = 30;
   private final int minAbstandAchseJPanel = 20;
   private String beschriftungXAchse;
//   private String beschriftungYAchse;
//   private int laengeBeschriftungXAchse;
//   private int laengeBeschriftungYAchse;
  
// Variablen für das Einlesen von Dateien
   String zeile = "";
   double startwert;
   double endwert;
   double inkrement;
   String[] werte;
   int messwerte;
   final int beginnMesswerte = 38;
   int endeMesswerte;
   String datei = "C:/Bild/Datei.csv";
   private LinkedList<Daten> datenListe;
   Daten daten;
  
   public Inhalt()
   {
     this.beschriftungXAchse = "X-Achse";
//     this.beschriftungYAchse = "Y-Achse";
     this.datenListe = new LinkedList<Daten>();
   }
  
   public void paint(Graphics g)
   {
     zeichnenKoordinatensystem(g);    
     if (datei != null)
     {
       datenEinlesen();
       zeichnenPunkte(g);
     }
   }
  
   public void datenEinlesen()
   {
     int i;
     BufferedReader br = null;
     try
     {
     i = 1;
    
     br = new BufferedReader(new FileReader(datei));
     br.readLine();
     while (i < 7)
     {
       zeile = br.readLine();
       i++;
     }
    
     werte = zeile.split("\\s");
    
     startwert = Double.parseDouble(werte[5]);
     endwert = Double.parseDouble(werte[6]);
     inkrement = Double.parseDouble(werte[7]);
    
     messwerte = (int)((endwert - startwert) / inkrement) + 1; // Anzahl der Messwerte. Die +1 ist wichtig, da sonst ein MEsswert fehlt! Start- und Endwert identisch => Trotzdem ein Messwert
    
     endeMesswerte = messwerte + beginnMesswerte;
    
     }
     catch(IOException e)
     {
      
     }
     finally
     {
       try
       {
         br.close();
         i = 1;
       }
       catch(IOException e)
       {
        
       }

     }
    

     BufferedReader bufrea = null;
    
     try
     {
       bufrea = new BufferedReader(new FileReader(datei));
       i = 1;
       bufrea.readLine();
       while (i < endeMesswerte)
       {
        
         if (i >= beginnMesswerte)
         {
          
           String[] str = bufrea.readLine().trim().split("\\s+");
           datenListe.add(new Daten(Double.parseDouble(str[0]), Double.parseDouble(str[1])));
         }
         else
         {
           bufrea.readLine();
         }
         i++;
       }
     }
     catch(IOException e)
     {
      
     }
     finally
     {
       try
       {
         br.close();  
       }
       catch(IOException e)
       {
        
       }
     }

//     repaint();
   }
  
   public void zeichnenKoordinatensystem(Graphics g)
   {

    
     g.drawLine(0 + abstandGitterRand, 0 + minAbstandAchseJPanel, 0 + abstandGitterRand, (int)(this.getSize().getHeight() - abstandGitterRand)); // Zeichnen der y-Achse
     g.drawLine(0 + abstandGitterRand, (int)(this.getSize().getHeight() - abstandGitterRand), (int)(this.getSize().getWidth() - minAbstandAchseJPanel), (int)(this.getSize().getHeight() - abstandGitterRand)); // Zeichnen der x-Achse
    
    
     // Beschriften der Achsen
     FontMetrics fm = g.getFontMetrics();
    
     //X-Achse
     g.drawString(beschriftungXAchse, (int)((this.getSize().getWidth() - abstandGitterRand - minAbstandAchseJPanel) / 2 + abstandGitterRand - fm.stringWidth(beschriftungXAchse) / 2), (int)(this.getSize().getHeight()-abstandBeschriftungXAchse));
     //Y-Achse
    

    
   }
  
  
  
   public void zeichnenPunkte(Graphics g)
   {
     // Ermitteln der Abstaende zwischen zwei aufeinanderfolgenden X-Werten der Punkte
     abstandWerteXAchse = (((double)this.getSize().getWidth() - (double)abstandGitterRand - (double)minAbstandAchseJPanel) - ((double)this.getSize().getWidth() - (double)abstandGitterRand - (double)minAbstandAchseJPanel) % messwerte) / messwerte;
     this.abstandWerteXAchse = (this.getSize().getWidth() - abstandGitterRand - minAbstandAchseJPanel) / messwerte;
    
     // Bestimmung von Y-Max
     for(int i = 0; i < messwerte; i++)
     {
       if (datenListe.get(i).getYD() > yMax)
       {
         yMax = datenListe.get(i).getYD();
       }
     }
    
     // Ermitteln der Abstaende zwischen zwei aufeinanderfolgenden Y-Werten der Punkte
     abstandWerteYAchse = (this.getSize().getHeight() - abstandGitterRand - minAbstandAchseJPanel) / yMax;
    
    

     // Zeichnen der Punkte
     for (int i = 0; i < messwerte; i++)
     {
       g.drawOval((int)(abstandGitterRand + (i * abstandWerteXAchse) - 1), (int)((minAbstandAchseJPanel + (yMax - datenListe.get(i).getYD()) * abstandWerteYAchse) - 1), 2, 2); // Die Kreise haben einen Durchmesser von 2 Pixeln. Um sie genau auf dem Punkt zu zeichnen, muss von deren x- und y-Position jeweils 1 Pixel abgezogen werden!
     }

   }
  
   public void dateiOeffnen(String datei)
   {
     this.datei = datei;
     repaint();
   }
  
  
   public void dateiEinlesen()
   {
  JFileChooser chooser = new JFileChooser();
  int rueckgabeWert = chooser.showOpenDialog(null);
  if(rueckgabeWert == JFileChooser.APPROVE_OPTION)
  {
     dateiOeffnen(chooser.getSelectedFile().getAbsolutePath());
  }
   }
  
}

Was für Möglichkeiten habe ich, um den Inhalt des Panels vor dem Aufruf von repaint() zu löschen, um jetzt am Anfang den Datensatz der zu öffnenden Datei korrekt anzuzeigen? Allerdings möchte ich später auch die Möglichkeit haben, zwei und mehr Datensätze gleichzeitig anzuzeigen. Wie gehe cih da am Besten vor?

Viele Grüße
schiese


EDIT: Das Problem verschwindet nach einem resize des JFrames. Danach wird alles normal angezeigt.
 

Anhänge

  • Doppelbild.png
    Doppelbild.png
    40,9 KB · Aufrufe: 16
Hallo,
ich erstelle mal eine neue Frage zu dem Thema, da ich bisher bei dem Problem des "Fehlzeichnens" (siehe Bild im ersten Post) nicht weitergekommen bin und ich das Programm bis nächste Woche brauche.
Ich habe den wichtigen Code mal etwas abgespeckt, da ich es etwas übersichtlicher schreiben möchte:
Java:
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

public class Start extends JPanel {
   private static final long serialVersionUID = -3330800293328098089L;
   
   JFrame jframe;
   JMenuBar jmenubar;
   JMenu jmenu;
   JMenuItem jmenuitem;
   
   private int check;
   
   public Start()
   {
     jframe = new JFrame("Dateiplotter");
     jframe.setSize(new Dimension(800,600));
     jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     jframe.setLocationRelativeTo(null);
     jframe.setBackground(Color.WHITE);
     this.setBackground(Color.WHITE);
     
     jmenubar = new JMenuBar();
     jmenu = new JMenu("Datei");
     jmenubar.add(jmenu);
     jmenuitem = new JMenuItem("Datei Öffnen");
     jmenuitem.addActionListener(new JMenuActionListener(this));

     jmenu.add(jmenuitem);
     jmenuitem = new JMenuItem("Bild speichern");
     jmenu.add(jmenuitem);
     jmenuitem = new JMenuItem("Daten speichern");
     jmenu.add(jmenuitem);
     jmenuitem = new JMenuItem("Beenden");
     jmenuitem.addActionListener(new JMenuActionListener(this));
     jmenu.add(jmenuitem);
     
     jmenu = new JMenu("Bearbeiten");
     jmenubar.add(jmenu);
     jmenuitem = new JMenuItem("Fitten");
     jmenu.add(jmenuitem);


     Container c = jframe.getContentPane();
     c.add(this);
     jframe.setJMenuBar(jmenubar);
     jframe.setVisible(true);
     
     
     check = 0;
   }

   public static void main(String[] args)
   {
     new Start();
   }
   
   public void paint(Graphics g)
   {
     if (check == 0)
     {
       g.drawString("Starttext", 100, 200);
     }
     else if (check == 1)
     {
       g.drawString("Ich komme von der repaint-Methode des Menüs!", 100, 200);
     }
     else if (check == 2)
     {
       g.drawString("Ich komme von der repaint-Methode des DateiOeffnen-Dialogs!", 100, 200);
     }
   }
   
   public void setCheck()
   {
     this.check++;
   }
   
}

Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class JMenuActionListener implements ActionListener {
   
   private Start start;

   public JMenuActionListener(Start start)
   {
     this.start = start;
   }
   
   public void actionPerformed(ActionEvent e) {
     if (e.getActionCommand().equals("Datei Öffnen"))
     {
       start.setCheck();
       start.repaint();
       new DateiOeffnen(start);
     }
     else if(e.getActionCommand().equals("Beenden"))
     {
       System.exit(0);
     }
   }

}

Java:
import javax.swing.JFileChooser;
public class DateiOeffnen
{
   private Start start;
   public DateiOeffnen(Start start)
   {
     this.start = start;
  JFileChooser chooser = new JFileChooser();
  int rueckgabeWert = chooser.showOpenDialog(null);
  if(rueckgabeWert == JFileChooser.APPROVE_OPTION)
  {
     this.start.setCheck();
     this.start.repaint();
  }
   }
}

Was habe ich bisher neu probiert:
- ich habe einen Timer eingebaut, der den repaint 1s oder noch später ausführt, da ich dachte, dass es vllt. an der geringen zeitlichen Differenz zwischen dem Auswählen eines Files und dem repaint liegt. Problem bleibt aber bestehen
- ich habe in der Klasse DateiOeffnen() hinter dem Aufruf von repaint() die 2 Zeilen
this.start.jframe.setSize(new Dimension(801,601));
this.start.jframe.setSize(new Dimension(800,600));
eingefügt und es funktioniert einwandfrei (der angesprochene resize des JFrames im Beitrag 1). Dies ist allerdings eine unschöne Lösung.


Viele Grüße
schiese
 
Hallo,

ich bin kein großer Java Swing Experte, aber ich habe folgenden Beitrag im Internet gefunden: http://stackoverflow.com/a/9391382/603003
Anscheinend solltest du "paintComponent()" für dein JPanel nutzen. Probiere das mal aus.

Ansonsten würde ich das mit der Resize-Lösung nicht so schlimm finden (dokumentiere den Workaround aber!), da sind deine leeren Catch-Blöcke ohne Fehlerbehandlung viel schlimmer ;)
 

Neue Beiträge

Zurück