Problem mit JPanel...

Alles was mit Swing und AWT zu tun hat

Moderatoren: wegus, Olek77

Lennarttw
Beiträge: 9
Registriert: 25.02.2014, 15:12

Problem mit JPanel...

Beitrag von Lennarttw » 25.02.2014, 15:41

Hallo Community,
Ich schreibe im Moment meine Facharbeit in Informatik über das Thema Sortieralgorithmen. Die Sortieralgorithmen funktionieren soweit, nur muss ich diese nun grafisch darstellen. Orientieren sollte ich mich an dem Programm VisuSort, welches die zu sortierenden Zahlen so darstellt (siehe Anhang). Ich habe mich informiert und habe für jeden Algorithmus als Grundfläche wie bei VisuSort ein eigenes JPanel erstellt (ist das richtig?). Weiterhin habe ich von der paintComponent Methode gelesen und java.awt.Graphics und java.swing.JPanel importiert. Mein Ziel war es letztendlich die Zahlen aus meinem Array Zahlen[] nacheinander einem Balken zuzuweisen und so ca die gleiche Visualisierung wie bei VisuSort zu kriegen. Die Linien zeichne ich mit der Methode .drawLine(). So kam ich zu folgendem Code:

Code: Alles auswählen

import java.awt.Graphics;
import javax.swing.JPanel;

public class DrawPanel extends JPanel{            
    
    public void paintComponent ( Graphics g){
        super.paintComponent(g);
        
        int x = 10;
        int y= 0;
        for(int i = 0; i < zahlen.length; i++){
            int zahl = zahlen[i];
            
            g.drawLine(x, y, x, zahl*y);
            x = x+5;
        
        }
    }
    
}
Nun hab ich aber das Problem, dass ich überhaupt nicht weiß wie ich diesen Code einem bestimmten JPanel zuweisen kann. :roll: Falls ihr noch generelle Verbesserungen habt, werden die auch gerne angenommen :D
ich entschuldige mich schon mal für die dumme Frage aber ist mein erstes Projekt mit NetBeans^^
MfG Lennarttw
Dateianhänge
visu.PNG
VisuSort.png
visu.PNG (18.17 KiB) 17509 mal betrachtet

Breebo
Beiträge: 9
Registriert: 23.05.2013, 08:24
Wohnort: NRW

Re: Problem mit JPanel...

Beitrag von Breebo » 27.02.2014, 08:49

Hi, der Code sieht ja ganz gut aus, allerdings werden deine Linien nie gezeichnet werden, weil y = 0 ist und 0*zahl = 0 :)
Aber nichts destotrotz brauchst du das DrawPanel keinem JPanel zuweisen, denn es ist ja selbst eins. Was du machen muss ist das DrawPanel in irgendeiner Art und Weise auf ein javax.swing.JFrame zu packen, d.h. entweder direkt, oder erst in ein JScrollPane packen und das ScrollPane dann auf das JFrame.
Also zb. sowas:
Das fenster in das alles rein kommt

Code: Alles auswählen

public class MeinFrame extends JFrame
{
  private static final long serialVersionUID = 6229555920013197755L;

  private CardLayout cards;
  private JComboBox<String> cb_algorithmen;
  private JPanel cardPanel;
  //Algorithmus ist ein Interface was alle Sortieralgorithmen implementieren, 
  //damit man sie z.B. so in einer ComboBox behandeln kann
  private Map<String, Algorithmus> sortierAlgorithmen;

  public MeinFrame() throws HeadlessException
  {
    cards = new CardLayout();
    cardPanel = new JPanel();
    cb_algorithmen = new JComboBox<>();
    sortierAlgorithmen = new HashMap<>();
    initialize();
  }

  private void initialize()
  {
    setLayout(new BorderLayout());
    cardPanel.setLayout(cards);
    erzeugeAlgorithmen();
    int[] zahlen =
    {
      10, 20, 30, 40, 50, 60, 70, 80, 90, 100
    };
    for(String key : sortierAlgorithmen.keySet())
    {
      cb_algorithmen.addItem(key);
      JPanel panel = new DrawPanel(sortierAlgorithmen.get(key), zahlen);
      //Das DrawPanel auf sein parent legen, mit der LayoutConstraint 'key'
      cardPanel.add(panel, key);
      panel.repaint();
    }

    //Sobald sich der Wert der ComboBox ändert soll auch eine andere Karte 
    //gezeigt werden
    cb_algorithmen.addActionListener(new ActionListener()
    {

      @Override
      public void actionPerformed(ActionEvent e)
      {
        //Zeigt die Karte, die unter dem Namen getSelectedItem().toString() 
        //registriert ist, auf scrollPane an
        cards.show(cardPanel, cb_algorithmen.getSelectedItem().toString());
      }

    });
    //Nachdem alles nötige erzeugt ist müssen die Komponenten noch auf 
    //das JFrame gepackt werden
    add(cardPanel, BorderLayout.CENTER);
    add(cb_algorithmen, BorderLayout.SOUTH);
  }

  private void erzeugeAlgorithmen()
  {
    sortierAlgorithmen.put("BubbleSort", new BubbleSort());
    sortierAlgorithmen.put("HeapSort", new HeapSort());
  }
Die Klasse Draw Panel würde dann ungefähr so aussehen;

Code: Alles auswählen

  private class DrawPanel extends JPanel
  {
    private static final long serialVersionUID = -4156020704181116194L;
    private Algorithmus algo;
    private int[] zahlen;

    //das Panel sollte den Algorithmus kennen, da es diesen ja auch ausführen 
    //muss sow wie ich das verstanden hab
    public DrawPanel(Algorithmus algo, int... werte)
    {
      this.algo = algo;
      this.zahlen = werte; //besser wegen Kapselung Arrays.copyOf(werte, werte.length)
    }

    @Override
    protected void paintComponent(Graphics g)
    {
      //malen des ganzen Krams
    }

  }
Ich hoffe das hilft dir zumindest en bischen weiter

Schöne Grüße und Alaaf :D
Daniel

Lennarttw
Beiträge: 9
Registriert: 25.02.2014, 15:12

Re: Problem mit JPanel...

Beitrag von Lennarttw » 27.02.2014, 21:55

Nachdem ich eine Nacht drüber geschlafen hab viel mir das auch auf, aber trotzdem danke. :D Jedoch tut sich ein neues Problem auf. Da diese Methode mehrmals mit verschiedenen Werten ausgeführt werden muss und sich diese nicht überschreiben dürfen muss das jPanel nach jedem Durchlauf gelöscht werden. Wie geht das?
Hier ist nochmal mein überarbeiteter Code:

Code: Alles auswählen

    public void paintComponent (){
        
        
        Graphics g = Panel1.getGraphics();
        int x = 8;
        int y= 1;
        
        for(int i = 0; i < zahlen.length; i++){
            int zahl = zahlen[i];
            g.drawLine(x, 233-(zahl*2), x, 233);
            x = x+3;
            
            
        }
    }
Angeblich sollte das mit Panel1.removeAll() funktionieren, aber bei mir klappt es nicht :evil: Habt ihr Lösungsvorschläge?

Benutzeravatar
nigjo
Beiträge: 632
Registriert: 08.09.2009, 09:43
Wohnort: Aachen
Kontaktdaten:

Re: Problem mit JPanel...

Beitrag von nigjo » 28.02.2014, 07:17

Hi

Du hast in deiner paintComponent den super-Aufruf vergessen. Einfach super.paintComponent(g); als erstes in deiner eigenen paintComponent() Implementierung eintragen und schon sollte dein "löschen" automatisch passieren.

Gruß
Jens
Man sollte seine Werkzeuge kennen. Ansonsten haut man sich mit dem Hammer nur auf die Finger.

--
NetBeans Certified Engineer - Java Getriebe

Lennarttw
Beiträge: 9
Registriert: 25.02.2014, 15:12

Re: Problem mit JPanel...

Beitrag von Lennarttw » 28.02.2014, 16:52

Danke für die Hilfe, das Überschreiben klappt. Nur nachdem ich die Methode wieder aufrufe, werden komischerweise nicht nur die Balken neu eingefügt sondern auch andere Sachen?! :shock: Ich hatte die modifizierte Methode dann in einer anderen Methode mit paintComponent(Panel1.getGraphics()); aufgerufen. Ist das richtig?
Sieht dann wie im Anhang gezeigt aus:
Problem.PNG
Problem.PNG (23.03 KiB) 17434 mal betrachtet

Benutzeravatar
nigjo
Beiträge: 632
Registriert: 08.09.2009, 09:43
Wohnort: Aachen
Kontaktdaten:

Re: Problem mit JPanel...

Beitrag von nigjo » 28.02.2014, 22:18

Hi

Ich glaube da haben wir etwas aneinander vorbei geredet.

Wenn du etwas in einem JPanel zeichnen möchtest, dann erzeugst du dir eine neue Klasse, die du einfach von JPanel ableitest. In DIESER Klasse überschreibst du die paintComponent Methode und zeichnest deinen eigenen Kram nach dem super-Aufruf. Eigentlich genau so, wie du es in deinem ersten Post geschrieben hast.

Diese von dir geschriebenen Klassen packst du dann wie von Daniel geschrieben in ein JFrame, zusammen mit den restlichen UI-Elementen, die du anzeigen möchtest.

Sich das Graphics von einem anderen Panel holen ist schlechter Stil und wie du selbser siehst, kommt man mehr durcheinander als sonst was.

Gruß
Jens
Man sollte seine Werkzeuge kennen. Ansonsten haut man sich mit dem Hammer nur auf die Finger.

--
NetBeans Certified Engineer - Java Getriebe

Lennarttw
Beiträge: 9
Registriert: 25.02.2014, 15:12

Re: Problem mit JPanel...

Beitrag von Lennarttw » 01.03.2014, 11:07

Ok, habe jetzt eine eigne Klasse für die Darstellung in den JPanels geschrieben, nur ist mein Problem das sich die beiden Klassen untereinander nicht kennen und der Button nur Methoden aus der anderen Klasse nimmt. Wie kann ich das ändern? So hab ich die Klasse erstellt, kommt halt dasselbe nochmal nur für die drei anderen Panels:
JPanel.PNG
JPanel.PNG (11.33 KiB) 17422 mal betrachtet

Benutzeravatar
nigjo
Beiträge: 632
Registriert: 08.09.2009, 09:43
Wohnort: Aachen
Kontaktdaten:

Re: Problem mit JPanel...

Beitrag von nigjo » 01.03.2014, 14:20

Da steht ja schon wieder der aufruf "anderesPanel.getGraphics()" drin. Löschen. Sofort! Ein Panel zeichnet immer nur sich selbst. Niemals ein anderes Panel.

Mein Aufbau der Anwendung wäre eventuell:
  • Ein DrawPanel welches das zeichnen übernimmt. (Sichwort: paintComponent())
  • Dieses Panel hat eine Methode setZahlen(int[]) und eigentlich nicht mehr.
  • Es gibt ein JFrame mit einem JPanel als "ContentPane"
  • im "ContentPane" sind die Eingabefelder, Buttons und auch die DrawPanel "enthalten".
  • Die ActionListener (ihres Zeichens "annonyme Klassen" im "ContentPane") der Buttons starten die Sortieralgorithmen (im eigenen Thread) und rufen immer wieder "setZahlen" und "repaint" der Zeichenpanel auf.
Gruß
Jens
Man sollte seine Werkzeuge kennen. Ansonsten haut man sich mit dem Hammer nur auf die Finger.

--
NetBeans Certified Engineer - Java Getriebe

Lennarttw
Beiträge: 9
Registriert: 25.02.2014, 15:12

Re: Problem mit JPanel...

Beitrag von Lennarttw » 01.03.2014, 20:05

Nachdem ich mit über die Sache mit dem ContentPanel informiert hatte, hab ich es jetzt so geschrieben:
ContentPanel.PNG
ContentPanel.PNG (18.59 KiB) 17409 mal betrachtet
Nur ist mir jetzt noch nicht klar wie ich meine Panels mit der paintComponent() Methode verknüpfen soll. Die Klasse DrawPanel erweitert ja JPanel, was bedeuten würde, dass ich woanders einfach Panel1.paintComponent(); schreiben kann, das funktioniert aber nicht. :(

Benutzeravatar
nigjo
Beiträge: 632
Registriert: 08.09.2009, 09:43
Wohnort: Aachen
Kontaktdaten:

Re: Problem mit JPanel...

Beitrag von nigjo » 01.03.2014, 20:27

Lennarttw hat geschrieben:Nur ist mir jetzt noch nicht klar wie ich meine Panels mit der paintComponent() Methode verknüpfen soll. Die Klasse DrawPanel erweitert ja JPanel, was bedeuten würde, dass ich woanders einfach Panel1.paintComponent(); schreiben kann, das funktioniert aber nicht. :(
Das musst und sollst du ja auch gar nicht.

paintComponent wird automatisch aufgerufen, sobald das System es für richtig hält. Das passiert zum Beispiel, wenn du die Fenster wechselst oder mein verändern der Fenstergröße. Du kannst dieses "Neuzeichnen" aber auch programmatisch erzwingen, in dem du die (in meinem vorherigen Post erwähnte) repaint()-Methode aufrufst.

Will heißen: Jedes mal, wenn dein Sortieralgorithmus die aktuellen Zahlen neu an das GraphPanel (siehe mein vorheriger Post) weiter gegeben hat, rufst du im Anschluss daran ein repaint() vom Panel auf, fertig.

Der Rest mit dem ContentPanel sieht (technisch gesehen) ganz OK aus.

Gruß
Jens
Man sollte seine Werkzeuge kennen. Ansonsten haut man sich mit dem Hammer nur auf die Finger.

--
NetBeans Certified Engineer - Java Getriebe

Lennarttw
Beiträge: 9
Registriert: 25.02.2014, 15:12

Re: Problem mit JPanel...

Beitrag von Lennarttw » 02.03.2014, 11:29

Das würde heißen, dass repaint() in diesem Fall die Methode paintComponent() aufruft? Dann müsste dieser Code doch eigentlich funktionieren:
y.PNG
y.PNG (15.13 KiB) 17398 mal betrachtet
Das JPanel zeichnet durch den Aufruf von .repaint() die momentanen Zahlen durch die Methode .paintComponent(). Dann läuft der Sortieralgorithmus drüber und danach werden die sortierten Zahlen gezeichnet. Bei mir bleibt das JPanel jedoch leer.
So wie ich das gelesen habe, aktualisiert die repaint() doch nur, d.h. sie aktualisiert nur das leere Panel und es wird nie etwas reingeschrieben oder?
Und ich hab noch eine etwas nebensächliche Frage: Muss ich meine komplette Gui im Quellcode mit dem JFrame und dem ContentPanel schreiben? Weil ich kann doch einfach alles im Design Reiter erstellen und anordnen?
Zuletzt geändert von Lennarttw am 02.03.2014, 11:58, insgesamt 1-mal geändert.

Benutzeravatar
nigjo
Beiträge: 632
Registriert: 08.09.2009, 09:43
Wohnort: Aachen
Kontaktdaten:

Re: Problem mit JPanel...

Beitrag von nigjo » 02.03.2014, 11:44

Screenshots von irgendwelchen aus dem Zusammenhang gerissenem Quellcode hilft glaube ich an dieser Stelle nicht mehr weiter. mit dem "Code"-Button hier über dem Eingabefeld für deinen Postings kannst du wunderbar Sourcecode "einrahmen".

Was mich bei dir da jetzt stört ist, dass du da ein new DrawPanel stehen hast. Warum erzeugst du ein neues Objekt? Das ist dann doch ein komplett anderes als das, welches du schon im Frame eingefügt hast(haben solltest). Natürlich bleibt dieses dann "leer". Du kaufst dir doch auch nicht ein neues Regal, wenn du in dein aktuelles eine neue Vase stellen möchtest.

Wenn der Hinweis nicht hilft, solltest du vielleicht mal dein Projekt hier hochladen (In NetBeans gibt es unter "File / Export Project / As Zip", welches nur die notwendigen Daten exportiert!)

Gruß
Jens
Man sollte seine Werkzeuge kennen. Ansonsten haut man sich mit dem Hammer nur auf die Finger.

--
NetBeans Certified Engineer - Java Getriebe

Lennarttw
Beiträge: 9
Registriert: 25.02.2014, 15:12

Re: Problem mit JPanel...

Beitrag von Lennarttw » 02.03.2014, 12:06

Hier mein Projekt:
JavaApplication1.rar
(18.1 KiB) 416-mal heruntergeladen

Lennarttw
Beiträge: 9
Registriert: 25.02.2014, 15:12

Re: Problem mit JPanel...

Beitrag von Lennarttw » 03.03.2014, 18:10

Hat schon jemand eine Lösung gefunden? :?

Lennarttw
Beiträge: 9
Registriert: 25.02.2014, 15:12

Re: Problem mit JPanel...

Beitrag von Lennarttw » 03.03.2014, 21:55

Ich hab das ganze nochmal überarbeitet und das Layout im Quellcode gestaltet, jedoch kriege ich wieder das selbe Problem.
Hier diese Version:
Facharbeit.rar
(15.52 KiB) 391-mal heruntergeladen

Antworten