Swing Dynamischer Graph zum anzeigen Perfomance Daten

ralfb1105

Bekanntes Mitglied
Hallo Community,

ich programmiere gerade an einem kleinen Programm (mit Swing GUI) um eine Oracle DB zu testen bzw. unter Last zu setzen.

Im Zuge dieser Arbeit würde ich gerne während der Testlaufzeit, in der z.B. eine Tabelle mit Daten gefüllt wird oder Daten abgerufen werden, verschiedene Performance Indikatoren, wie z.B. IOPS (IOs Per Second), dynamisch in einer Art Graph anzeigen.

Meine erste Idee hierzu ist zyklisch Linien in ein Koordinaten System zu zeichnen, wobei die Y-Koordinate der Linie den IOPs Wert angibt/widerspiegelt.

Ich habe das mal folgendermaßen probiert, erst einmal unabhängig von meinem Oracle Test Programm:
shape.java
Java:
import javax.swing.*;

public class shapes {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Performance Graph");
        frame.setVisible(true);
        frame.setSize(450, 250);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        draw object = new draw();
        frame.add(object);
        object.drawing();
    }
}
draw.java
Java:
import javax.swing.JPanel;
import java.awt.*;
import java.util.Random;

@SuppressWarnings("serial")

public class draw extends JPanel {
   
    public void drawing() {
        repaint();
    }
   
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
       
        //Draw the x-y Coordinate Lines
        g.setColor(Color.BLACK);
        g.drawLine(20, 180, 380, 180);
        g.drawLine(30, 20, 30, 190);
       
        int i=0;
        while (i < 300) {
            Random rnd = new Random();
            int IOPS = rnd.nextInt(150);
            i += 1;
            g.setColor(Color.RED);
            g.drawLine(32+i, 178, 32+i, 178-IOPS);
        }
    }
}

Jetzt fehlt mir allerdings das Know-How und die Idee, wie ich dynamisch, oder anders ausgedrückt über einen bestimmten Zeitraum (Testlaufzeit) in mein fest definiertes Koordinatensystem, "fließend" die kommenden Daten (z.B. IOPs) darzustellen.

Es soll vereinfacht ausgedrückt ein Performance Graph sein.

Über eine Idee wie ich so etwas realisieren kann wäre ich sehr dankbar. Ich habe im Netz nichts passendes dazu gefunden, bin mir aber auch nicht sicher ob Java für so etwas ggf. fertige Klassen/Bibliotheken zur Verfügung stellt.

Wie gesagt, bin für jede Idee und Hilfe dankbar!!

Gruß

Ralf
 

httpdigest

Top Contributor
Vielleicht möchtest du dafür lieber eine Bibliothek wie etwa JFreeChart einsetzen. Um z.B. ein Dataset über einen gegebenen Zeitraum von 1 Minute anzuzeigen, kannst du folgendes verwenden:
Java:
import java.awt.*;
import javax.swing.*;
import org.jfree.chart.*;
import org.jfree.chart.ui.*;
import org.jfree.data.time.*;
public class JFreeChartDemo extends ApplicationFrame {
    public JFreeChartDemo() {
        super("Demo");
        final DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(1, 60, new Second());
        dataset.setTimeBase(new Second());
        dataset.addSeries(new float[] { 0.0f }, 0, "1");
        JFreeChart chart = ChartFactory.createTimeSeriesChart("Test", "Time", "Value", dataset, true, true, false);
        chart.getXYPlot().getDomainAxis().setAutoRange(true);
        final ChartPanel chartPanel = new ChartPanel(chart);
        final JPanel content = new JPanel(new BorderLayout());
        content.add(chartPanel);
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
        setContentPane(content);
        Timer timer = new javax.swing.Timer(200, (e) -> {
            dataset.advanceTime();
            dataset.appendData(new float[] { (float) Math.random() });
        });
        timer.setRepeats(true);
        timer.start();
        this.pack();
        this.setVisible(true);
    }
    public static void main(final String[] args) {
        new JFreeChartDemo();
    }
}
Benötigt JFreeChart als Abhängigkeit, z.B. downloadbar als JAR über: http://central.maven.org/maven2/org/jfree/jfreechart/1.5.0/jfreechart-1.5.0.jar
 

ralfb1105

Bekanntes Mitglied
Hallo,

vielen Dank für den nützlichen Tip und Dein Beispiel Code :) Da ich Java Anfänger bin werde ich mal versuchen mich in das JFreeChart API einzuarbeiten um Deinen Code zu verstehen und danach zu versuchen das ganze in mein Projekt zu implementieren.

Ich hoffe es ist OK wenn ich dann ggf. in diesem Thread noch ein paar Fragen stelle :rolleyes:

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo Community,

ich habe das Tets Programm von httpdigest getestet und es läuft super und entspricht in etwa auch dem was ich mir vorstelle bei meinem Graph. Man kann die Graphen ja auch vielfältig verändern :)

Wie ich aber schon angekündigt habe ;) fehlt mir anscheinend mal wieder das Know How um einen solchen Grap in mein bestehendes "GUI" einzubauen. Als erstes habe ich mal versucht nur das Test Programm, sprich ohne Daten von der DB, in einem JPanel darzustellen welches ich vorher in meinem GUI definiert habe. Leider wird jedoch nichts in dem JPanel angezeigt - es kommt aber auch keine Fehlermeldung oder ein Syntax error in Eclipse!?

Hier mal den Code den ich verwendet habe, mit der Hoffnung das Ihr mir weiter helfen könnt.

1. Definition des JPanel

Java:
private JPanel getJPanel_IOPs() {
        if(jPanel_IOPs == null) {
            jPanel_IOPs = new JPanel();
            jPanel_IOPs.setBounds(12, 394, 534, 199);
            jPanel_IOPs.setLayout(null);
            jPanel_IOPs.setBorder(BorderFactory.createEtchedBorder(BevelBorder.LOWERED));
            jPanel_IOPs.setBackground(new java.awt.Color(238,238,238));
            jPanel_IOPs.add(getJLIOPs());
        }
        return jPanel_IOPs;
    }

2. Da ich ja in diesem Forum gelernt habe das ma so etwas nebenläufig ausführen sollte um den EDT nicht zu blockieren, habe ich die folgende ProcessWorker Klasse geschrieben, an Hand des Beispiels den ich schon an anderen Stellen in meinem "GUI" verwende. Dieser Klasse übergebe ich das JPanel Objekt und darin wird dann der Code für den Chart ausgeführt .. oder auch nicht :confused:

Java:
public class ProcessWorkerIOPs extends SwingWorker<Void, String>
    {
        private JPanel jPanel_IOPs;
       
        public ProcessWorkerIOPs(JPanel IOPs)
        {
            this.jPanel_IOPs = IOPs;
        }

       
        @Override
        protected Void doInBackground() throws Exception
        {
            //hier l�uft alles in einem eigenen Thread (nebenl�ufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert.
           
            System.out.println("Reached ProcessWorkerIOPs");
           
            final DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(1, 60, new Second());
            dataset.setTimeBase(new Second());
            dataset.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
           
            JFreeChart chart = ChartFactory.createTimeSeriesChart("OraSimpleBench IOPs Chart", "Time", "IOPs", dataset, true, true, false);
            chart.getXYPlot().getDomainAxis().setAutoRange(true);
            final ChartPanel chartPanel = new ChartPanel(chart);
           
            jPanel_IOPs.add(chartPanel);
            //chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
            //setContentPane(jPanel_IOPs);
           
            Timer timer = new javax.swing.Timer(2000, (e) -> {
                dataset.advanceTime();
                dataset.appendData(new float[] { (float) Math.random() });
            });
            timer.setRepeats(true);
            timer.start();
            return null;
        }
       
        @Override
        protected void process(List<String> chunks)
        {
            //hier l�uft alles auf dem EDT (Event Dispatch Thread). Darum k�nnen (und sollten) wir hier die GUI Komponenten manipulieren.
           
        }
    }

In der Methode process() wird in meinen anderen Klasse z.B. Ausgaben in eine jTextArea verarbeitet die vorher mit publish "gesetzt" werden. An diser Stelle weiß ich auch nicht wo genau ich den Code für den Chart platzieren soll, ich habe den Code auch mal innerhalb der process Methode definiert, hat aber keine Änderung gebracht.

Die Klasse wird dann beim drücken eines Button folgendermaßen aufgerufen:

Java:
    private void jBTestDBconnectActionPerformed(ActionEvent evt) {
        clearOutputArea();
        // Disable Start Test Button when Test DB Connect is in progress
        jBStartTest.setEnabled(false);
        ProcessWorkerDbConnect p = new ProcessWorkerDbConnect(jTAOutput);
        p.execute();
       
        ProcessWorkerIOPs iops = new ProcessWorkerIOPs(jPanel_IOPs);
        iops.execute();
    }

Zum testen habe ich ja die Zeile "System.out.println("Reached ProcessWorkerIOPs");" in "doInBackground()" eingefügt und diese wird auch auf der Konsole ausgegeben, also wird der Code bis dahin schon mal ausgeführt.

Hat jemand eine Idee wo mein Fehler liegt das in dem jPanel der Chart nicht angezeigt wird?

Danke schon mal für Eure Tips!

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo zusammen,

leider gibt es noch keine Tips zu dem Thema, bin mir jetzt nicht sicher ob es an meiner Beschreibung des Problems liegt oder am Thema selbst :rolleyes:

Ich habe in der Zwischenzeit auch noch im WWW gestöbert aber auch keine Lösung gefunden. Im Prinzip, so wie ich es bei z.B. Stackoverflow gefunden habe, scheint es möglich zu sein, aber ich vermute das ich in meinem "GUI" wahrscheinlich irgendetwas falsch gemacht habe !!??

Was ich auch noch probiert habe, und was auch funktioniert, ich habe eine eigene Klasse eingefügt, so wie von httpdigest beschrieben, und die dann aufgerufen, was dann neben meinem GUI ein eigenes Frame öffnet.

Somit schient der Code zu JFreeChart zu funktionieren, nur die Einbettung in ein, bzw. mein, bestehendes JPanel will mir nicht gelingen :(

Falls ich das Problem nicht genau genug beschrieben habe, oder aber jemand den komplette GUI Code zum testen haben möchte, bitte einfach kurz melden - ich bin zu jeder Tat bereit ;)

Ich hoffe dann weiter auf Beiträge/Hinweise und wünsche Euch bis dahin ein schönes Pfingstwochenende.

Gruß

Ralf
 

mrBrown

Super-Moderator
Mitarbeiter
1. Definition des JPanel
Naja, da sieht man nicht irgendwas, wozu man was sagen könnte. Aller relevante Code fehlt.


2. Da ich ja in diesem Forum gelernt habe das ma so etwas nebenläufig ausführen sollte um den EDT nicht zu blockieren, habe ich die folgende ProcessWorker Klasse geschrieben, an Hand des Beispiels den ich schon an anderen Stellen in meinem "GUI" verwende. Dieser Klasse übergebe ich das JPanel Objekt und darin wird dann der Code für den Chart ausgeführt .. oder auch nicht :confused:

In der Methode process() wird in meinen anderen Klasse z.B. Ausgaben in eine jTextArea verarbeitet die vorher mit publish "gesetzt" werden. An diser Stelle weiß ich auch nicht wo genau ich den Code für den Chart platzieren soll, ich habe den Code auch mal innerhalb der process Methode definiert, hat aber keine Änderung gebracht.
Das Erstellen des (leeren) Charts sollte schon im EDT passieren - es ist ja ein GUI-Event.
Außerhalb des EDT sollte das Abfragen neuer Daten passieren, damit das nicht den EDT blockiert. Die neuen Daten würdest du dann publishen und in process dem Chart hinzufügen (möglicherweise gibt es aber bessere Lösungen)

Falls ich das Problem nicht genau genug beschrieben habe, oder aber jemand den komplette GUI Code zum testen haben möchte, bitte einfach kurz melden - ich bin zu jeder Tat bereit ;)
Zumindest wäre es gut, mal zu sehen, wo du das denn Panel hinzufügst
 

ralfb1105

Bekanntes Mitglied
Hallo mrBrown,

erst einmal vielen Dank das Du dir mein Problem/Frage angeschaut hast!

Zu 1. Definition des JPanel.
Auch wenn ich jetzt bestimmt wieder "Prügel" beziehe, ja, ich habe das GUI mit Jiglioo "gebaut". Hier der Code zu dem Panel in dem ich den Graph anzeigen möchte:
Java:
private JPanel jPanel_IOPs;

Java:
private JPanel getJPanel_IOPs() {
        if(jPanel_IOPs == null) {
            jPanel_IOPs = new JPanel();
            jPanel_IOPs.setBounds(12, 394, 534, 199);
            jPanel_IOPs.setLayout(null);
            jPanel_IOPs.setBorder(BorderFactory.createEtchedBorder(BevelBorder.LOWERED));
            jPanel_IOPs.setBackground(new java.awt.Color(238,238,238));
            jPanel_IOPs.add(getJLIOPs());
        }
        return jPanel_IOPs;
    }

Java:
getContentPane().add(getJPanel_IOPs());

Zu 2. und folgend.
Ich muss zugeben das ich das mit dem EDT anscheinend noch nicht so richtig verstanden habe.
Wie geschrieben war meine Idee über eine Klasse "ProcessWorkerIOPs extends SwingWorker" den Chart zu erstellen. Wie geschrieben habe ich das folgende Klasse geschrieben, in der Hoffnung das dies auf dem EDT passiert und damit das restliche GUI nicht blockiert wird:

Java:
public class ProcessWorkerIOPs extends SwingWorker<Void, String>
    {
        private JPanel jPanel_IOPs;
       
        public ProcessWorkerIOPs(JPanel IOPs)
        {
            this.jPanel_IOPs = IOPs;
        }

       
        @Override
        protected Void doInBackground() throws Exception
        {
            //hier l�uft alles in einem eigenen Thread (nebenl�ufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert.
           
            System.out.println("Reached ProcessWorkerIOPs");
           
            final DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(1, 60, new Second());
            dataset.setTimeBase(new Second());
            dataset.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
           
            JFreeChart chart = ChartFactory.createTimeSeriesChart("OraSimpleBench IOPs Chart", "Time", "IOPs", dataset, true, true, false);
            chart.getXYPlot().getDomainAxis().setAutoRange(true);
            final ChartPanel chartPanel = new ChartPanel(chart);
           
            jPanel_IOPs.add(chartPanel);
            jPanel_IOPs.validate();
            chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
            //setContentPane(jPanel_IOPs);
           
            Timer timer = new javax.swing.Timer(2000, (e) -> {
                dataset.advanceTime();
                dataset.appendData(new float[] { (float) Math.random() });
            });
            timer.setRepeats(true);
            timer.start();
            return null;
        }
       
        @Override
        protected void process(List<String> chunks)
        {
            //hier l�uft alles auf dem EDT (Event Dispatch Thread). Darum k�nnen (und sollten) wir hier die GUI Komponenten manipulieren.
           
        }
    }

Der Aufruf erfolgt dann z.B. innerhalb eines Button Action Event:

Java:
 ProcessWorkerIOPs iops = new ProcessWorkerIOPs(jPanel_IOPs);
iops.execute();

Wie Du dem Code entnehmen kannst habe ich, da ich es nicht besser weiß, den komplette Code zum erstellen des Chart, in die Methode doInBackground() gepackt, wobei die process() Methode leer ist.

Wenn Du schreibst:
Das Erstellen des (leeren) Charts sollte schon im EDT passieren - es ist ja ein GUI-Event.

Könntest Du mir bitte an Hand meines Codes erklären wo in der ProcessWorker Klasse, sprich in welche Methode ich welchen Code des JFreeChart einbinden muss?

Des Weiteren gibst Du den Tipp die Daten außerhalb des EDT bereit zu stellen. Ich muss die Daten, z.B. über ein SQL aus einer DB, doch zyklisch abfragen und bereitstellen, und das passiert doch in dem einfachen Beispiel mit der Random Nummer innerhalb des Timer, der dann alle 2 Sekunden die Daten an das Dataset übergibt. Wie soll ich das SQL Statement zur Abfrage der IOPs aus der DB denn zyklisch aufrufen um es dann innerhalb des Timer bereitzustellen damit es dann dem dataset übergebe wird??

Da fehlt mir die Verbindung im Kopf um das umzusetzen :-(

Ich weiß, vermutlich zu viel für einen Anfänger, ich wäre trotzdem sehr froh und dankbar wenn Du die Zeit finden würdest mir hier zu helfen.

DANKE schon mal!

LG Ralf
 

mrBrown

Super-Moderator
Mitarbeiter
Auch wenn ich jetzt bestimmt wieder "Prügel" beziehe, ja, ich habe das GUI mit Jiglioo "gebaut". Hier der Code zu dem Panel in dem ich den Graph anzeigen möchte:
Da sieht auch alles richtig aus...

Ich muss zugeben das ich das mit dem EDT anscheinend noch nicht so richtig verstanden habe.
Wie geschrieben war meine Idee über eine Klasse "ProcessWorkerIOPs extends SwingWorker" den Chart zu erstellen. Wie geschrieben habe ich das folgende Klasse geschrieben, in der Hoffnung das dies auf dem EDT passiert und damit das restliche GUI nicht blockiert wird:
EDT = GUI-Thread.
Alles, was im EDT passiert, blockiert die GUI - gleichzeitig muss alles, was die GUI verändert, im EDT stattfinden.

Könntest Du mir bitte an Hand meines Codes erklären wo in der ProcessWorker Klasse, sprich in welche Methode ich welchen Code des JFreeChart einbinden muss?

Des Weiteren gibst Du den Tipp die Daten außerhalb des EDT bereit zu stellen. Ich muss die Daten, z.B. über ein SQL aus einer DB, doch zyklisch abfragen und bereitstellen, und das passiert doch in dem einfachen Beispiel mit der Random Nummer innerhalb des Timer, der dann alle 2 Sekunden die Daten an das Dataset übergibt. Wie soll ich das SQL Statement zur Abfrage der IOPs aus der DB denn zyklisch aufrufen um es dann innerhalb des Timer bereitzustellen damit es dann dem dataset übergebe wird??

Du musst Chart-Erstellung, Abfragen der Daten und Anzeigen der Daten trennen.

Die Chart-Erstellung (mit leerem Datenset) und das hinzufügen zum Panel kannst du vor dem SwingWorker machen, das ist vom Rest unabhängig - sollte aber im EDT passieren.

Im SwingWorker lässt du dann in doInBackground in einer Schleife die Daten abfragen - das läuft dann unabhängig vom EDT im Hintergrund. Mit den neuen Daten rufst du dann publish auf.

Die Daten, die du an publish übergibst, kommen dann in process an - dort übergibst du sie dann dem Chart, was schon angezeigt wird, was ja im EDT passieren muss, weil sich die GUI verändern soll.
 

ralfb1105

Bekanntes Mitglied
Hallo mrBrown,

ich versuche gerade Deine nützlichen Infos zu verstehen und umzusetzen, das ganze Schritt für Schritt.
Als erstes gemäß Deiner Aussage

Die Chart-Erstellung (mit leerem Datenset) und das hinzufügen zum Panel kannst du vor dem SwingWorker machen, das ist vom Rest unabhängig - sollte aber im EDT passieren.

Leider muss ich zugeben das ich schon an dieser Hürde scheitere, obwohl es sich einfach und logisch anhört.
Ich habe versucht den Code zum erstellen des Graph aus dem Testprogramm von httpdigest zu Extrahören um es dann wie von Dir vorgeschlagen separat als "Chart Erstellung" einzubauen.

Ich war der Meinung das der SwingWorker den EDT repräsentiert, also habe ich den Code zum erstellen des Graph in die Methode "initGUI()" eingebaut, dort wo auch mein jPanel dem GUI hinzugefügt wird. das Ganze sieht dann so aus, funktioniert aber leider nicht :-(

Java:
//getContentPane().add(getJPanel_IOPs());
                   
                    final DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(1, 60, new Second());
                    dataset.setTimeBase(new Second());
                    dataset.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
                   
                    JFreeChart chart = ChartFactory.createTimeSeriesChart("OraSimpleBench IOPs Chart", "Time", "IOPs", dataset, true, true, false);
                    chart.getXYPlot().getDomainAxis().setAutoRange(true);
                    final ChartPanel chartPanel = new ChartPanel(chart);
                    chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
                   
                    final JPanel contentIOPs = new JPanel(new BorderLayout());
                    contentIOPs.add(chartPanel);
                    getContentPane().add(contentIOPs);
                   
                    getContentPane().add(getJPanel_TPS());

Könntest Du mir noch einen Tipp geben wo im Code bzw. im EDT ich den Code zu erstellen des Graph einbinden muss. Ist es denn prinzipiell richtig das ich erst im Code, so wie ich es gemacht habe ein jPanel Object erstelle und dieses dann in dem JFreeChart Code verwende und anschließend das JFreeChart Objekt dem GUI hinzufüge?

Oder darf ich mein jPanel dem GUI gar nicht hinzufügen, wie mit der folgenden Zeile:

Java:
getContentPane().add(getJPanel_IOPs());

und muss "nur" das erstellte JFreeChart Objekt dem GUI hinzufügen?

Bevor ich dann mit Datenbereitstellung und publish weiter mache muss ich erst diese Baustelle verstehen/lösen und das ist für mich schon eine große Hürde, und daher bin ich auch sehr dankbar das Du hier Hilfestellung gibst!

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo mrBrown,

ich habe noch einmal nachgedacht und ich glaube bezogen auf meinen letzten Post ist das vermutlich etwas verwirrend und nicht ganz eindeutig was ich probiert habe :rolleyes:
Daher habe ich mir überlegt das erst einmal in einem einfachen Test Programm zu probieren, dann ist es auch einfacher für Dich mir Tipps zu geben ;)

Ich habe folgendes Programm erstellt, so wie ich es am Anfang bei meinem GUI gemacht habe.
  • Ein Frame
  • 2 Buttons - Start und Exit. Beim Start Button soll dann im zweiten Schritt der Graph mit Daten versorgt werden.
  • 1 jPanel in dem der Chart angezeigt werden soll.
Hier der komplette Code dazu:
Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;

import javax.swing.WindowConstants;
import javax.swing.border.LineBorder;
import javax.swing.SwingUtilities;


/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/
public class TestGraph extends javax.swing.JFrame {

    {
        //Set Look & Feel
        try {
            javax.swing.UIManager.setLookAndFeel("com.jgoodies.looks.plastic.Plastic3DLookAndFeel");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private JButton jBStart;
    private JButton jBExit;
    private JPanel jPanelGraph;

    /**
    * Auto-generated main method to display this JFrame
    */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                TestGraph inst = new TestGraph();
                inst.setLocationRelativeTo(null);
                inst.setVisible(true);
            }
        });
    }
   
    public TestGraph() {
        super();
        initGUI();
    }
   
    private void initGUI() {
        try {
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            getContentPane().setLayout(null);
            {
                jBStart = new JButton();
                getContentPane().add(jBStart);
                jBStart.setText("Start");
                jBStart.setBounds(23, 301, 75, 25);
                jBStart.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBStartActionPerformed(evt);
                    }
                });
            }
            {
                jBExit = new JButton();
                getContentPane().add(jBExit);
                jBExit.setText("Exit");
                jBExit.setBounds(480, 304, 64, 22);
                jBExit.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBExitActionPerformed(evt);
                    }
                });
            }
            {
                jPanelGraph = new JPanel();
                getContentPane().add(jPanelGraph);
                jPanelGraph.setBounds(23, 30, 521, 262);
                jPanelGraph.setBackground(new java.awt.Color(255,212,120));
                jPanelGraph.setBorder(new LineBorder(new java.awt.Color(0,0,0), 1, false));
            }
            pack();
            this.setSize(566, 369);
        } catch (Exception e) {
            //add your error handling code here
            e.printStackTrace();
        }
    }
   
    private void jBStartActionPerformed(ActionEvent evt) {
        System.out.println("jBStart.actionPerformed, event="+evt);
        //TODO add your code for jBStart.actionPerformed
    }
   
    private void jBExitActionPerformed(ActionEvent evt) {
        System.exit(0);
        //TODO add your code for jBStart.actionPerformed
    }

}

Wenn ich es richtig verstanden habe, sollte der folgende Code einen "leeren" Chart erstellen:
Java:
final DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(1, 60, new Second());
        dataset.setTimeBase(new Second());
        dataset.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
        JFreeChart chart = ChartFactory.createTimeSeriesChart("OraSimpleBench IOPs Chart", "Time", "IOPs", dataset, true, true, false);
        chart.getXYPlot().getDomainAxis().setAutoRange(true);
        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));

An welcher Stelle in dem Test Programm (1. Code Teil oben) würdest Du denn jetzt das erstellen des Chart ohne Daten hinzufügen?

Welcher Teil in dem Code ist denn der EDT?

Ich hoffe das es damit etwas verständlicher wird :)

DANKE schon mal - ich weiß, immer diese Anfänger :D

LG

Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo mrBrown,

Bezug nehmend auf mein einfaches Test Programm habe ich es nun hinbekommen den leeren Graph im Panel anzuzeigen :)

Hier der Code:

Java:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;

import javax.swing.WindowConstants;
import javax.swing.border.LineBorder;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.time.DynamicTimeSeriesCollection;
import org.jfree.data.time.Second;

import javax.swing.SwingUtilities;


/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/
public class TestGraph extends javax.swing.JFrame {

    {
        //Set Look & Feel
        try {
            javax.swing.UIManager.setLookAndFeel("com.jgoodies.looks.plastic.Plastic3DLookAndFeel");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private JButton jBStart;
    private JButton jBExit;
    private JPanel jPanelGraph;

    /**
    * Auto-generated main method to display this JFrame
    */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                TestGraph inst = new TestGraph();
                inst.setLocationRelativeTo(null);
                inst.setVisible(true);
            }
        });
    }
   
    public TestGraph() {
        super();
        initGUI();
    }
   
    private void initGUI() {
        try {
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            getContentPane().setLayout(null);
            {
                jBStart = new JButton();
                getContentPane().add(jBStart);
                jBStart.setText("Start");
                jBStart.setBounds(23, 301, 75, 25);
                jBStart.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBStartActionPerformed(evt);
                    }
                });
            }
            {
                jBExit = new JButton();
                getContentPane().add(jBExit);
                jBExit.setText("Exit");
                jBExit.setBounds(480, 304, 64, 22);
                jBExit.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBExitActionPerformed(evt);
                    }
                });
            }
            {
                jPanelGraph = new JPanel();
                getContentPane().add(jPanelGraph);
                jPanelGraph.setBounds(23, 30, 521, 262);
                //jPanelGraph.setBackground(new java.awt.Color(255,212,120));
                //jPanelGraph.setBorder(new LineBorder(new java.awt.Color(0,0,0), 1, false));
            }
            [B]{
                final DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(1, 60, new Second());
                dataset.setTimeBase(new Second());
                dataset.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
                JFreeChart chart = ChartFactory.createTimeSeriesChart("OraSimpleBench IOPs Chart", "Time", "IOPs", dataset, true, true, false);
                chart.getXYPlot().getDomainAxis().setAutoRange(true);
                final ChartPanel chartPanel = new ChartPanel(chart);
                chartPanel.setPreferredSize(new java.awt.Dimension(521, 262));
                jPanelGraph.add(chartPanel);   
            }[/B]
            pack();
            this.setSize(566, 369);
        } catch (Exception e) {
            //add your error handling code here
            e.printStackTrace();
        }
    }
   
    private void jBStartActionPerformed(ActionEvent evt) {
        System.out.println("jBStart.actionPerformed, event="+evt);
        //TODO add your code for jBStart.actionPerformed
    }
   
    private void jBExitActionPerformed(ActionEvent evt) {
        //System.exit(0);
        //TODO add your code for jBStart.actionPerformed
    }

}

Der Unterschied zu meinem "großen" GUI besteht darin das das Panel über eine Methode "getJPanelxyz" und einem getContentPane in der Methode initGUI() erzeigt wird. In dem obigen Code wird das jPanel direkt im initGUI() erzeugt.

Ich werde Morgen noch ein wenig weiter testen, wäre über Deine Meinung dankbar.

Gruß

Ralf
 

mrBrown

Super-Moderator
Mitarbeiter
Was ist denn jetzt der aktuelle Stand?

Welcher Teil in dem Code ist denn der EDT?
Alles, was entweder durch GUI-Events ausgelöst wird (zb ActionListener) oder explizit in diesem Aufgerufen wird (mit SwingUtilities.invokeLater) läuft im EDT.
Außerdem zB so Dinge wie process und done beim SwingWorker.

Ich war der Meinung das der SwingWorker den EDT repräsentiert
Jein - SwingWorker dient ja extra dazu, Berechnungen und GUI voneinander zu trennen.
doInBackground wird nicht im EDT ausgeführt (sondern in einem beliebigem anderem Thread), process und done dienen dagegen dazu, Dinge an die GUI weiterzugeben und laufen deshalb im EDT
 

ralfb1105

Bekanntes Mitglied
Hallo mrBrown,

vorab schon mal Danke für die Erklärungen!
Hier nun der aktuelle Stand:

1. Darstellung des Chart im JPanel

Ich habe nun folgenden Code in meinem "GUI" verwendet und damit wird der leere Chart im GUI, oder besser im JPanel des GUI, dargestellt:

Java:
private JPanel jPanelGraph_IOP;

Innerhalb der initGUI() Methode:

Java:
            {
                jPanelGraph_IOP = new JPanel();
                getContentPane().add(jPanelGraph_IOP);
                jPanelGraph_IOP.setBounds(12, 394, 534, 199);
                jPanelGraph_IOP.setBackground(new java.awt.Color(238,238,238));
            }
            {
                final DynamicTimeSeriesCollection datasetIOP = new DynamicTimeSeriesCollection(1, 60, new Second());
                datasetIOP.setTimeBase(new Second());
                datasetIOP.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
                JFreeChart chartIOP = ChartFactory.createTimeSeriesChart("IOP", "Time", "IOP", datasetIOP, true, true, false);
                chartIOP.getXYPlot().getDomainAxis().setAutoRange(true);
                final ChartPanel chartPanelIOP = new ChartPanel(chartIOP);
                chartPanelIOP.setPreferredSize(new java.awt.Dimension(534, 199));
                jPanelGraph_IOP.add(chartPanelIOP);  
            }

Mit dem oben gezeigten Code wird das Chart ohne Datenaktualisierung im GUI initialisiert und dargestellt.

Im nächsten Schritt, vermutlich erst Morgen, werde ich versuchen Deinen Tipp bzgl. der Datenaktualsierung

Außerhalb des EDT sollte das Abfragen neuer Daten passieren, damit das nicht den EDT blockiert. Die neuen Daten würdest du dann publishen und in process dem Chart hinzufügen (möglicherweise gibt es aber bessere Lösungen)

umzusetzen.
Meine theoretische Idee im groben wäre dann folgende:

1. Erstellen einer Klasse "ProcessWorkerIOPs extends SwingWorker" der das dataset_IOP übergeben wird
2. In der doInBackground() Methode werden in einer Schleife die Daten für das Dataset ermittelt, erst einmal zum testen nur Random Zahlen, später dann die SQL DB Abfragen zum ermitteln der IOPs aus der DB. Dies läuft dann außerhalb des EDT.
3. Die ermittelten Werte werden dann mittels publish(value) der Methode process() übergeben, in der dann die Daten im dataset gesetzt werden: "datasetIOP.appendData(new float[] { (float) <value> });"

Beim Punkt 3. wäre ich mir allerdings nicht sicher wie genau die Datenübergabe passiert.

  1. Ich ermittle einen Float Wert und rufe dann "publish((float) value)" auf - richtig?
  2. Wie würde denn dann die process Methode definiert? Bisher habe ich nur String Listen verarbeitet mit folgendem Code:
    Java:
    protected void process(List<String> chunks)
            {
                for(int i = 0; i < chunks.size(); i++)
                {
                    jLCreateTestTableExecTimeCounter.setText(chunks.get(i));
                }
            }
Wäre toll wenn Du Dir meinen "Plan" mal anschauen könntest und einen Tipp zu meiner Frage bzgl. der Datenübergabe hättest.

Gruß

Ralf
 

mrBrown

Super-Moderator
Mitarbeiter
Beim Punkt 3. wäre ich mir allerdings nicht sicher wie genau die Datenübergabe passiert.

  1. Ich ermittle einen Float Wert und rufe dann "publish((float) value)" auf - richtig?
  2. Wie würde denn dann die process Methode definiert? Bisher habe ich nur String Listen verarbeitet mit folgendem Code:
Du musst den Typ des SwingWorkers passend angeben - aktuell müsste da String drin vorkommen, dass musst du dann auf Float oder Double ändern.
Daraus ergibt sich dann auch die Signatur für process, die wäre dann List<Float>
 

ralfb1105

Bekanntes Mitglied
OK, dann wäre die Klasse folgendermassen deklariert:
Java:
public class ProcessWorkerIOPs extends SwingWorker<Void, Float>
Die Übergabe dann über:
Java:
process((float) value);
Die process Methode sieht dann so aus??
Java:
protected void process(List<Float> chunks)
        {
            //hier l�uft alles auf dem EDT (Event Dispatch Thread). Darum k�nnen (und sollten) wir hier die GUI Komponenten manipulieren.
           
           for(int i = 0; i < chunks.size(); i++)
           {
               datasetIOP.appendData(new float[] { (float) (chunks.get(i) });
           }
           
        }

Habe ich das so richtig interprtiert?

Gruß

Ralf
 

Blender3D

Top Contributor
Bezug nehmend auf mein einfaches Test Programm habe ich es nun hinbekommen den leeren Graph im Panel anzuzeigen :)

Hier der Code:
Ich habe Dir Deinen Code etwas in Form gebracht.
1) Erben von JFrame ist keine gute Idee. Besser ein JPanel (GraphPanel ) der in den JFrame eingesetzt wird.
2) Du verwendtest null als Layout --> Die Dimensionen deiner Elemente sollten sich prozentuell von Breite und Höhe berechnen. z.B. wenn die Größe des Fensters warum auch immer verändert wird, kann man darauf reagieren.
Die Standardlayouts sind hier einfacher in der Benutzung weil sie das für dich erledigen. Vorteil vom null Layout ( deshalb wichtig, dass es existiert ). Die GUI lässt sich Punktgenau einrichten. Also ein Funktion wie
Java:
private void updateDimensions(int width, int height)
einbauen. ( kann z.B.bei resize() aufgerufen werden )
3) Du erzeugst 2 ActionListener die den Listener dann an private Funktionen weiterleiten. Besser GraphPanel implementiert den ActionListener und du reagierst dort auf die Ereignisse. --> Viel übersichtlicher im Code.

Wenn Dein Projekt wächst, wirst Du damit Probleme bekommen. ;)
Hier meine kleinen Verbesserungen.
Java:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.time.DynamicTimeSeriesCollection;
import org.jfree.data.time.Second;

@SuppressWarnings("serial")
public class GraphPanel extends JPanel implements ActionListener {
    private JButton jBStart = new JButton("start");
    private JButton jBExit = new JButton("exit");
    private JPanel jPanelGraph = new JPanel();
    private JFreeChart chart;
    private ChartPanel chartPanel;
    private DynamicTimeSeriesCollection dataset;

    public GraphPanel(int width, int height) {
        setPreferredSize(new Dimension(width, height));
        setLayout(null);
        // add GUI Components
        add(jBStart);
        add(jBExit);
        add(jPanelGraph);
        // add Listeners
        jBStart.addActionListener(this);
        jBExit.addActionListener(this);
        // setSize
        updateDimensions(width, height);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        if (source == jBStart) {
            System.out.println("start");
        }

        if (source == jBExit) {
            System.out.println("exit");
        }
    }

    private void createChartPanel(int width, int height) {
        dataset = new DynamicTimeSeriesCollection(1, 60, new Second());
        dataset.setTimeBase(new Second());
        dataset.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
        chart = ChartFactory.createTimeSeriesChart("OraSimpleBench IOPs Chart", "Time", "IOPs", dataset, true, true,
                false);
        chart.getXYPlot().getDomainAxis().setAutoRange(true);
        chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new java.awt.Dimension((int) (width * .92), (int) (height * .71)));
    }

    private void updateDimensions(int width, int height) {
        jBStart.setBounds((int) (width * 0.046), (int) (height * .8157), (int) (width * 0.13), (int) (height * .0677));
        jBExit.setBounds((int) (width * .848), (int) (height * .823), (int) (width * .113), (int) (height * .0596));
        jPanelGraph.setBounds((int) (width * .046), (int) (height * .0813), (int) (width * .92), (int) (height * .71));
        jPanelGraph.removeAll();
        createChartPanel(width, height);
        jPanelGraph.add(chartPanel);
    }
}
Java:
import javax.swing.JFrame;

public class start {
    public static void main(String[] args) {
        JFrame frame = new JFrame("GRAPH");
        GraphPanel graph = new GraphPanel(566,369);
        frame.add(graph);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setResizable(false);
        frame.setVisible(true);
    }
}
 

ralfb1105

Bekanntes Mitglied
Hallo Blender3D,

Danke für Deine Tipss und Ideen. Wie mrBrown schon richtig bemerkt hat, habe ich Jigloo als GUI Builder verwendet und dort das Layout "absolut" weil es dann am Anfang wesentlich einfacher ist seine Objekte zu platzieren.
Ich gebe Dir Recht, es ist natürlich eleganter wenn man das GUI vergrößern/verkleinern kann und die Objekte passen sich der Größe an. Dazu müsste ich allerdings alles neu schreiben, das kommt dann für die Version 2.0 auf die Agenda, im Moment bin ich bei 0.99 und versuche mich an der technischen Implementierung von meinen Überlegungen zu dem was das GUI können soll.

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo mrBrown,

ich habe versucht meinen oben skizzierten Plan in die Tat, oder besser in Code, umzusetzen aber leider gibt es beim starten der ProcessWorker Klasse eine Java NullPointerException in der process Methode.
Code:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at oracle.OraSimpleBench$ProcessWorkerIOP.process(OraSimpleBench.java:1163)
    at javax.swing.SwingWorker$3.run(Unknown Source)
    at sun.swing.AccumulativeRunnable.run(Unknown Source)
    at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(Unknown Source)
    at sun.swing.AccumulativeRunnable.run(Unknown Source)
    at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(Unknown Source)
    at javax.swing.Timer.fireActionPerformed(Unknown Source)
    at javax.swing.Timer$DoPostEvent.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Hier meine Implementation, aufgeteilt auf die Graph relevanten Teile:
Java:
private JPanel jPanelGraph_IOP;
private DynamicTimeSeriesCollection datasetIOP;

In der initGUI() Methode das erstellen des leeren Graph, was auch ohne Probleme funktioniert:

Java:
{
                jPanelGraph_IOP = new JPanel();
                getContentPane().add(jPanelGraph_IOP);
                jPanelGraph_IOP.setBounds(12, 394, 534, 199);
                jPanelGraph_IOP.setBackground(new java.awt.Color(238,238,238));
            }
            {
                DynamicTimeSeriesCollection datasetIOP = new DynamicTimeSeriesCollection(1, 60, new Second());
                datasetIOP.setTimeBase(new Second());
                datasetIOP.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
                JFreeChart chartIOP = ChartFactory.createTimeSeriesChart("IOP", "Time", "IOP", datasetIOP, true, true, false);
                chartIOP.getXYPlot().getDomainAxis().setAutoRange(true);
                final ChartPanel chartPanelIOP = new ChartPanel(chartIOP);
                chartPanelIOP.setPreferredSize(new java.awt.Dimension(534, 199));
                jPanelGraph_IOP.add(chartPanelIOP);  
            }

Die ProcessWorkerIOP Klasse in der es die Exception gibt:

Java:
public class ProcessWorkerIOP extends SwingWorker<Void, Float>
    {
        private DynamicTimeSeriesCollection datasetIOP;
        Timer timer = null;
        Random iopsRandom = new Random();
       
        public ProcessWorkerIOP(DynamicTimeSeriesCollection dataset)
        {
            this.datasetIOP = dataset;
        }

       
        @Override
        protected Void doInBackground() throws Exception
        {
            //hier l�uft alles in einem eigenen Thread (nebenl�ufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert.
            timer = new Timer(2000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                        float value = iopsRandom.nextFloat();
                        publish(value);
                }
            });
           
            timer.start();
           
            return null;
        }
       
        @Override
        protected void process(List<Float> chunks)
        {
            //hier l�uft alles auf dem EDT (Event Dispatch Thread). Darum k�nnen (und sollten) wir hier die GUI Komponenten manipulieren.
            for(int i = 0; i < chunks.size(); i++)
               {
                   datasetIOP.appendData(new float[] { (float) (chunks.get(i))});
               }
        }
    }

Die instanziierung und der Aufruf erfolgt dann beim drücken eines Buttons:

Java:
  ProcessWorkerIOP iops = new ProcessWorkerIOP(datasetIOP);
        iops.execute();

Wenn ich an Stelle des "publish(value);" ein "System.out.println(value);" schreibe wird alle 2 Sekunden der Random Wert auf der Consoke ausgegeben, auch wenn das natürlich das GUI blockiert. Für mich heißt das aber das der Teil mit dem Timer im doInBackground generell funktioniert.

Wenn ich die Zeile mit dem "datasetIOP.appendData" durch einen "System.out.println(chunks.get(i));" ersetze werden auf der Console zyklisch die Random Werte ausgegeben:
Code:
0.542514
0.54793835
0.81248355
0.06432462
0.0784893
0.9390444
0.68930227

Es muss also am "datasetIOP.appendData(new float[] { (float) (chunks.get(i))});" liegen ... ??

Meine Vermutung liegt darin das ich vermutlich mal wieder das falsche Objekt referenziert habe und ich gar nicht auf das "Chart datasetIOP schreibe" ...

Hast Du eine Idee was ich hier falsch gemacht habe?

Danke nochmals!

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Sorry, jetzt stehe ich auf dem Schlauch :(
Ich habe datasetIOP im initGUI beim erstellen des Graph deklariert. das war also falsch?
Wo muss ich denn das datasetIOP deklarieren? Ich bin davon ausgegangen das ich diese Deklaration schon beim erstellen des leeren Graph benötige, weil ich es ja beim deklarieren von chartIOP mit angeben muss.

Kannst Du mir bezogen auf meinen Code oben sagen wo ich die Deklaration des datasetIOP durchführen muss um es dann bei der Initiierung von ProcessWorker mit übergeben zu können?

Danke.

Gruß

Ralf
 

mrBrown

Super-Moderator
Mitarbeiter
Du deklarierst es einmal in der Klasse als Feld:
Java:
private DynamicTimeSeriesCollection datasetIOP;

Und einmal als lokale Variable:
Java:
DynamicTimeSeriesCollection datasetIOP = new DynamicTimeSeriesCollection(1, 60, new Second());

Mit deklarieren legst du immer eine neue Variable an, und weist nicht die alte zu.
Statt sie lokal neu zu deklarieren, müsstest du einfach das Feld zuweisen:

Java:
this.datasetIOP = new DynamicTimeSeriesCollection(1, 60, new Second());
 

ralfb1105

Bekanntes Mitglied
Mit meinen Worten, ich muss es im initGUI nicht neu deklarieren, sondern über this.datasetIOP das Feld zuweisen. Dieses Feld wird dann über den Aufruf der ProcessWorker Klasse weitergegeben und in dem Konstruktor der Klasse weiter referenziert.

Ist es das so in etwa?

An dieser Stelle noch mal sorry für diese Anfänger Fehler und Fragen, aber das erlernen der Objekt Orientierung ist nicht ganz einfach in meinem Alter wenn man bisher nur procedural programmiert hat. Umso mehr Danke für Deine Geduld und Unterstützung!

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo mrBrown, @All,

nachdem mir mrBrown mit großer Geduld über alle Hürden hinweg geholfen hat, funktioniert es nun so wie ich es mir vorgestellt habe, zumindest mit Random Werten, die Herausforderung mit Daten aus der DB steht ja noch an.

Auch wenn der Code bestimmt nicht optimal ist, wie Blender3D schon angemerkt hat, möchte ich an dieser Stelle aber dennoch den Code der diesen Thread betrifft veröffentlichen, vielleicht hilft es ja in Zukunft anderen Anfängern auch weiter.

1. Deklaration der Felder

Java:
private JPanel jPanelGraph_IOP;
private DynamicTimeSeriesCollection datasetIOP;

2. Erstellen des "leeren" Graph in der initGUI() Methode

Java:
{
                jPanelGraph_IOP = new JPanel();
                getContentPane().add(jPanelGraph_IOP);
                jPanelGraph_IOP.setBounds(12, 394, 534, 199);
                jPanelGraph_IOP.setBackground(new java.awt.Color(238,238,238));
            }
            {
                //zuweisen des Feldes datasetIOP, welches über "private DynamicTimeSeriesCollection datasetIOP;" deklariert worden ist.
                this.datasetIOP = new DynamicTimeSeriesCollection(1, 60, new Second());
                datasetIOP.setTimeBase(new Second());
                datasetIOP.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
                JFreeChart chartIOP = ChartFactory.createTimeSeriesChart("IOP", "Time", "IOP", datasetIOP, true, true, false);
                chartIOP.getXYPlot().getDomainAxis().setAutoRange(true);
                final ChartPanel chartPanelIOP = new ChartPanel(chartIOP);
                chartPanelIOP.setPreferredSize(new java.awt.Dimension(534, 199));
                jPanelGraph_IOP.add(chartPanelIOP);  
            }

3. ProcessWokerIOP Klasse die SwingWorker erweitert. Hier werden die Daten ermittelt und dem Graph dataset zugewiesen.

Java:
public class ProcessWorkerIOP extends SwingWorker<Void, Float>
    {
        //Wichtig ist der Typ des SwingWorker --> hier Float, in den anderen z.B. String. Dies wird beim publish verwendet/genutzt!
       
        private DynamicTimeSeriesCollection datasetIOP;
        Timer timer = null;
        Random iopsRandom = new Random();
       
        public ProcessWorkerIOP(DynamicTimeSeriesCollection dataset)
        {
            this.datasetIOP = dataset;
        }

       
        @Override
        protected Void doInBackground() throws Exception
        {
            //hier laeuft alles in einem eigenen Thread (nebenlaeufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert. Dieser Teil laeuft nicht auf dem EDT!
            timer = new Timer(2000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                        float valueIOP = iopsRandom.nextFloat() * 10;
                        publish(valueIOP);
                }
            });
           
            timer.setRepeats(true);
            timer.start();
           
            return null;
        }
       
        @Override
        protected void process(List<Float> chunks)
        {
            //hier laeuft alles auf dem EDT (Event Dispatch Thread). Darum koennen (und sollten) wir hier die GUI Komponenten manipulieren.
            //Die Werte die verarbeitet werden muessen ueber publish() weitergegeben werden. Der Typ dieser Werte ist der Typ der im SwingWorker angegeben wird.
            //Die Signatur für process(List<type> chunks) muss auch entsprechend angegeben werden, also z.B. Float oder String.
           
            for(int i = 0; i < chunks.size(); i++)
               {
                   datasetIOP.advanceTime();
                   datasetIOP.appendData(new float[] {(chunks.get(i))});
               } 
        }
    }

4. Aufruf des ProcessWorkerIOP - damit werden zyklish Daten in den Graph geladen und angezeigt.

Java:
ProcessWorkerIOP iops = new ProcessWorkerIOP(datasetIOP);
        iops.execute();

Hier noch ein Bild von dem GUI, sprich von dem vorläufigem Ergebnis:
OraceSimpleBenchGUI.png


Danke an die Community!!

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hm, gleich die nächste Herausforderung ...
Dann muss ich anscheinend alle meiner timer umschreiben, denn so wie es aussieht hat java.util.Timer einen anderen Konstruktor, und somit geht z.B.
Java:
timer = new Timer(1000, new ActionListener()
nicht mehr --> The Constructor is undefined.
Also Timer und TimerTask ... verstanden habe ich folgendes:
1. Erstellen eines Timer Objektes
Java:
Timer timer = new Timer();
2. Erstellen einer Klasse die um TimerTask erweitert wird. Diese Klasse enthält dann den Code der vorher in "actionPerformed" ausgeführt wurde, z.B.:
Java:
class Task extends TimerTask
        {
          @Override public void run()
          {
              float valueIOP = iopsRandom.nextFloat() * 10;
              publish(valueIOP);
          }
        }
3. TimerTask-Objekt erzeugen, der sofort den Task und dann alle 2 sek ausführt.
Java:
timer.schedule( new Task(), 0, 2000 );

In anderen Teilen meines Codes beende ich den Timer wenn z.B. ein Counter abgelaufen ist, das würde ich dann über
timer.cancel() machen!?

Wäre das der grobe Fahrplan? Vrmutlich ist der theoretische Plan wieder einafcher als die Umsetzung, aber ich werde es mal im kleinen testen um zu sehne wie weit ich komme :rolleyes:

Ich halte Dich auf dem laufenden.

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo mrBrown,

ich habe die Timer Änderung einmal in mein "kleines" GUI, sprich nur der Graph und die Buttons, eingebaut.
Hier der Code, der so auch zu funktionieren scheint:
Java:
package oracle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Random;
import java.util.TimerTask;
import java.util.Timer;

import javax.swing.JButton;
import javax.swing.JPanel;

import javax.swing.WindowConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
//import javax.swing.Timer;

import org.jfree.chart.*;
import org.jfree.data.time.*;


/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/


@SuppressWarnings("serial")
public class ChartIOPDemo extends javax.swing.JFrame {
    private JButton jBStart;
    private JButton jBExit;
    private JButton jBStop;
    private JPanel jPChartIOP;
    private DynamicTimeSeriesCollection datasetIOP;
    private boolean stopTimer = false;


    {
        //Set Look & Feel
        try {
            javax.swing.UIManager.setLookAndFeel("com.jgoodies.looks.plastic.Plastic3DLookAndFeel");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }


    /**
    * Auto-generated main method to display this JFrame
    */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ChartIOPDemo inst = new ChartIOPDemo();
                inst.setLocationRelativeTo(null);
                inst.setVisible(true);
            }
        });
    }
   
    public ChartIOPDemo() {
        super();
        initGUI();
    }
   
    public class ProcessWorkerIOP extends SwingWorker<Void, Float>
    {
        //Wichtig ist der Typ des SwingWorker --> hier Float, in den anderen z.B. String. Dies wird beim publish verwendet/genutzt!
       
        private DynamicTimeSeriesCollection datasetIOP;
        Timer timer = null;
        Random iopsRandom = new Random();
       
        class Task extends TimerTask
        {
          @Override public void run()
          {
              float valueIOP = iopsRandom.nextFloat() * 10;
              publish(valueIOP);
             
          }
        }
       
        public ProcessWorkerIOP(DynamicTimeSeriesCollection dataset)
        {
            this.datasetIOP = dataset;
        }

       
        @Override
        protected Void doInBackground() throws Exception
        {
            //hier laeuft alles in einem eigenen Thread (nebenlaeufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert. Dieser Teil laeuft nicht auf dem EDT!
            Timer timerIOP = new Timer();
            timerIOP.schedule( new Task(), 0, 1000 );
            return null;
        }
       
        @Override
        protected void process(List<Float> chunks)
        {
            //hier laeuft alles auf dem EDT (Event Dispatch Thread). Darum koennen (und sollten) wir hier die GUI Komponenten manipulieren.
            //Die Werte die verarbeitet werden muessen ueber publish() weitergegeben werden. Der Typ dieser Werte ist der Typ der im SwingWorker angegeben wird.
            //Die Signatur für process(List<type> chunks) muss auch entsprechend angegeben werden, also z.B. Float oder String.
           
            for(int i = 0; i < chunks.size(); i++)
               {
                   datasetIOP.advanceTime();
                   datasetIOP.appendData(new float[] {(chunks.get(i))});
               } 
        }
    }
   
    private void initGUI() {
        try {
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            getContentPane().setLayout(null);
            {
                jBStart = new JButton();
                getContentPane().add(jBStart);
                jBStart.setText("Start");
                jBStart.setBounds(12, 407, 38, 23);
                jBStart.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBStartActionPerformed(evt);
                    }
                });
            }
            {
                jBExit = new JButton();
                getContentPane().add(jBExit);
                jBExit.setText("Exit");
                jBExit.setBounds(469, 407, 33, 23);
                jBExit.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBExitActionPerformed(evt);
                    }
                });
            }
            {
                jPChartIOP = new JPanel();
                getContentPane().add(jPChartIOP);
                jPChartIOP.setBounds(12, 12, 490, 389);
            }
            {
                jBStop = new JButton();
                getContentPane().add(jBStop);
                jBStop.setText("Stop");
                jBStop.setBounds(55, 407, 38, 23);
                jBStop.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBStopActionPerformed(evt);
                    }
                });
            }
            {
                //zuweisen des Feldes datasetIOP, welches über "private DynamicTimeSeriesCollection datasetIOP;" deklariert worden ist.
                this.datasetIOP = new DynamicTimeSeriesCollection(1, 60, new Second());
                datasetIOP.setTimeBase(new Second());
                datasetIOP.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
                JFreeChart chartIOP = ChartFactory.createTimeSeriesChart("IOP", "Time", "IOP", datasetIOP, true, true, false);
                chartIOP.getXYPlot().getDomainAxis().setAutoRange(true);
                final ChartPanel chartPanelIOP = new ChartPanel(chartIOP);
                chartPanelIOP.setPreferredSize(new java.awt.Dimension(490, 389));
                jPChartIOP.add(chartPanelIOP);  
            }
           
           
            pack();
            this.setSize(530, 480);
        } catch (Exception e) {
            //add your error handling code here
            e.printStackTrace();
        }
    }
   
   
   
    private void jBExitActionPerformed(ActionEvent evt) {
        System.exit(0);
    }
   
    private void jBStartActionPerformed(ActionEvent evt) {
        ProcessWorkerIOP iops = new ProcessWorkerIOP(datasetIOP);
        iops.execute();
    }
   
    private void jBStopActionPerformed(ActionEvent evt) {
       
    }

}

Frage:

Wie würde man denn jetzt das stoppen des Timer z.B. in dem Stop Button Event implementieren? Mir ist nicht klar wie ich das Objekt bzw. den Thread addressieren kann um dann "timerIOP.cancel();" aufrufen zu können?

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Oh je, jetzt fehlen mir wieder die Umsetzung der Basics ...
Die Instanz ist doch in meinem Fall "iops" gebildet aus:
Java:
ProcessWorkerIOP iops = new ProcessWorkerIOP(datasetIOP);
Richtig?
Der Timer wird in der Klasse aus der die Instanz gebildet wird definiert:
Java:
protected Void doInBackground() throws Exception
        {
            //hier laeuft alles in einem eigenen Thread (nebenlaeufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert. Dieser Teil laeuft nicht auf dem EDT!
            Timer timerIOP = new Timer();
            timerIOP.schedule( new Task(), 0, 1000 );
            return null;
        }

Wo und wie wird denn jetzt die Instanzvariable erstellt auf die ich dann zugreifen kann? Die Instanz wird beim Start Button erzeugt:
Java:
private void jBStartActionPerformed(ActionEvent evt) {
        ProcessWorkerIOP iops = new ProcessWorkerIOP(datasetIOP);
        iops.execute();
    }
Im Stop Button kann ich auf die "iops" Instanz nicht zugreifen !? ... oder bin ich jetzt vollkommen auf dem Holzweg?

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hi mrBrown,

ich habe das Programm nun folgendermaßen geändert und nun funktioniert es mit satrt und Stop, bin mir aber nicht sicher ob das so aus Java Sicht OK ist:

Java:
package oracle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Random;
import java.util.TimerTask;
import java.util.Timer;

import javax.swing.JButton;
import javax.swing.JPanel;

import javax.swing.WindowConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
//import javax.swing.Timer;

import org.jfree.chart.*;
import org.jfree.data.time.*;


/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/


@SuppressWarnings("serial")
public class ChartIOPDemo extends javax.swing.JFrame {
    private JButton jBStart;
    private JButton jBExit;
    private JButton jBStop;
    private JPanel jPChartIOP;
    private DynamicTimeSeriesCollection datasetIOP;
    private ProcessWorkerIOP iops;


    {
        //Set Look & Feel
        try {
            javax.swing.UIManager.setLookAndFeel("com.jgoodies.looks.plastic.Plastic3DLookAndFeel");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }


    /**
    * Auto-generated main method to display this JFrame
    */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ChartIOPDemo inst = new ChartIOPDemo();
                inst.setLocationRelativeTo(null);
                inst.setVisible(true);
            }
        });
    }
   
    public ChartIOPDemo() {
        super();
        initGUI();
    }
   
    public class ProcessWorkerIOP extends SwingWorker<Void, Float>
    {
        //Wichtig ist der Typ des SwingWorker --> hier Float, in den anderen z.B. String. Dies wird beim publish verwendet/genutzt!
       
        private DynamicTimeSeriesCollection datasetIOP;
        private Timer timerIOP;
        Random iopsRandom = new Random();
       
        public Timer getTimerIOP() {
            return timerIOP;
        }
       
        class Task extends TimerTask
        {
          @Override public void run()
          {
              float valueIOP = iopsRandom.nextFloat() * 10;
              publish(valueIOP);
             
          }
        }
       
        public ProcessWorkerIOP(DynamicTimeSeriesCollection dataset)
        {
            this.datasetIOP = dataset;
        }

       
        @Override
        protected Void doInBackground() throws Exception
        {
            //hier laeuft alles in einem eigenen Thread (nebenlaeufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert. Dieser Teil laeuft nicht auf dem EDT!
            this.timerIOP = new Timer();
            timerIOP.schedule( new Task(), 0, 1000 );
            return null;
        }
       
        @Override
        protected void process(List<Float> chunks)
        {
            //hier laeuft alles auf dem EDT (Event Dispatch Thread). Darum koennen (und sollten) wir hier die GUI Komponenten manipulieren.
            //Die Werte die verarbeitet werden muessen ueber publish() weitergegeben werden. Der Typ dieser Werte ist der Typ der im SwingWorker angegeben wird.
            //Die Signatur für process(List<type> chunks) muss auch entsprechend angegeben werden, also z.B. Float oder String.
           
            for(int i = 0; i < chunks.size(); i++)
               {
                   datasetIOP.advanceTime();
                   datasetIOP.appendData(new float[] {(chunks.get(i))});
               } 
        }
    }
   
    private void initGUI() {
        try {
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            getContentPane().setLayout(null);
            {
                jBStart = new JButton();
                getContentPane().add(jBStart);
                jBStart.setText("Start");
                jBStart.setBounds(12, 407, 38, 23);
                jBStart.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBStartActionPerformed(evt);
                    }
                });
            }
            {
                jBExit = new JButton();
                getContentPane().add(jBExit);
                jBExit.setText("Exit");
                jBExit.setBounds(469, 407, 33, 23);
                jBExit.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBExitActionPerformed(evt);
                    }
                });
            }
            {
                jPChartIOP = new JPanel();
                getContentPane().add(jPChartIOP);
                jPChartIOP.setBounds(12, 12, 490, 389);
            }
            {
                jBStop = new JButton();
                getContentPane().add(jBStop);
                jBStop.setText("Stop");
                jBStop.setBounds(55, 407, 38, 23);
                jBStop.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jBStopActionPerformed(evt);
                    }
                });
            }
            {
                //zuweisen des Feldes datasetIOP, welches über "private DynamicTimeSeriesCollection datasetIOP;" deklariert worden ist.
                this.datasetIOP = new DynamicTimeSeriesCollection(1, 60, new Second());
                datasetIOP.setTimeBase(new Second());
                datasetIOP.addSeries(new float[] { 0.0f }, 0, "No of IOs per Second");
                JFreeChart chartIOP = ChartFactory.createTimeSeriesChart("IOP", "Time", "IOP", datasetIOP, true, true, false);
                chartIOP.getXYPlot().getDomainAxis().setAutoRange(true);
                final ChartPanel chartPanelIOP = new ChartPanel(chartIOP);
                chartPanelIOP.setPreferredSize(new java.awt.Dimension(490, 389));
                jPChartIOP.add(chartPanelIOP);  
            }
           
           
            pack();
            this.setSize(530, 480);
        } catch (Exception e) {
            //add your error handling code here
            e.printStackTrace();
        }
    }
   
   
   
    private void jBExitActionPerformed(ActionEvent evt) {
        System.exit(0);
    }
   
    private void jBStartActionPerformed(ActionEvent evt) {
        //ProcessWorkerIOP iops = new ProcessWorkerIOP(datasetIOP);
        this.iops = new ProcessWorkerIOP(datasetIOP);
        iops.execute();
    }
   
    private void jBStopActionPerformed(ActionEvent evt) {
        iops.getTimerIOP().cancel();
    }

}
 

mrBrown

Super-Moderator
Mitarbeiter
Naja, man kann es besser lösen, aber für den Anfang Okay ;)

Ein paar Dinge wurden ja schon genannt.
So wie es aktuell ist (mit Timer) könnte man auf den SwingWorker verzichten und stattdessen einfach ObserverPattern nutzen (und dann auch gleich auf vernünftiges MVC umstellen)
 

ralfb1105

Bekanntes Mitglied
Naja, man kann es besser lösen, aber für den Anfang Okay
Ich fasse das mal als ein Lob auf :D denn Du hättest ja auch schreiben können "Schlimmer geht nimmer" ;)
Das mit dem ObserverPattern werde ich mir auch mal anschauen, aktuell aber erst einmal versuchen das mit dem java.util.Timer in meinem GUI zu implementieren, was ja bestimmt wieder einige Fragen aufwirft.

Ich halte Dich/Euch auf dem laufenden ... bitte nicht als Drohung verstehen :cool:

Gruß

Ralf
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
L JavaFX PropertyView mit dynamischer EditCell erstellen? AWT, Swing, JavaFX & SWT 8
L Dynamischer Aufbau einer Tabelle über Objekte AWT, Swing, JavaFX & SWT 2
K JavaFX Erzeugen dynamischer Layouts in fxml AWT, Swing, JavaFX & SWT 3
G Swing JScrollPane/Layoutmanger Problem bei dynamischer Größenänderung AWT, Swing, JavaFX & SWT 7
M Swing Dynamischer Frame AWT, Swing, JavaFX & SWT 3
D BorderLayout.Center mit 3 Panel und dynamischer Größe AWT, Swing, JavaFX & SWT 2
D jLayeredPane Ebenen mit dynamischer Größe AWT, Swing, JavaFX & SWT 2
G dynamischer Filter bei JTable AWT, Swing, JavaFX & SWT 2
S Dynamischer Inhalt in einem JPanel AWT, Swing, JavaFX & SWT 4
loadbrain auslesen der Werte dynamischer Textfields AWT, Swing, JavaFX & SWT 21
M JDBC + dynamischer JTable - Spalten problem AWT, Swing, JavaFX & SWT 5
Z Swing Graph zeichnen lassen AWT, Swing, JavaFX & SWT 16
D Canvas oder scene graph? AWT, Swing, JavaFX & SWT 16
K Aus 2 Arrays xy - Graph erstellen AWT, Swing, JavaFX & SWT 9
Soloeco Graph zeichnen AWT, Swing, JavaFX & SWT 1
I Graph mit Swing zeichnen AWT, Swing, JavaFX & SWT 8
D gerichteten Graph erstellen AWT, Swing, JavaFX & SWT 2
H 2D-Grafik Bibliothek um Graph\Baum zu erstellen AWT, Swing, JavaFX & SWT 2
K Graph erstellen AWT, Swing, JavaFX & SWT 3
S Graph zeichnen bei Mausklick AWT, Swing, JavaFX & SWT 4
S Balkendiagramm und XY-Graph in einem Chart? AWT, Swing, JavaFX & SWT 2
XWing Swing Image anzeigen und probleme mit klassen AWT, Swing, JavaFX & SWT 3
S JTable - Feldinhalte anzeigen AWT, Swing, JavaFX & SWT 15
W Kleine Sub-Tabelle in SpreadsheetView-Zelle anzeigen AWT, Swing, JavaFX & SWT 9
J Java GUI Dropdown-Menü anzeigen AWT, Swing, JavaFX & SWT 5
J JavaFx PDF in einem Element in einem Fenster anzeigen. AWT, Swing, JavaFX & SWT 11
M Swing Bilder in Swing anzeigen AWT, Swing, JavaFX & SWT 9
J BufferedImages nacheinander als Video anzeigen AWT, Swing, JavaFX & SWT 14
BananenBrötchen Swing Arraylist in jList anzeigen AWT, Swing, JavaFX & SWT 6
Lukas2904 Swing ID von WLAN Kamera anzeigen lassen. AWT, Swing, JavaFX & SWT 2
M Problem mit dem Anzeigen von Frames im Vordergrund AWT, Swing, JavaFX & SWT 5
G AWT AWT Kreise permanent anzeigen AWT, Swing, JavaFX & SWT 3
MiMa File Dateien im ListView als Name anzeigen? AWT, Swing, JavaFX & SWT 6
C Swing In der Titelleiste den Namen und den vollständigen Pfad bzw URL des aktuellen Dokuments anzeigen AWT, Swing, JavaFX & SWT 25
C Swing Aufruf der Funktion (die ein Dialog anzeigt) über Symbol anzeigen lassen AWT, Swing, JavaFX & SWT 4
O Timer in JOptionPane anzeigen AWT, Swing, JavaFX & SWT 2
H Daten aus einer XML(x83-Datei) in einem JFrame anzeigen lassen AWT, Swing, JavaFX & SWT 9
C JavaFX Veränderungen in Scenebuilder in Eclipse als Quellcode anzeigen lassen AWT, Swing, JavaFX & SWT 11
N Textdatei GUI, Text in Textarea anzeigen mehrere Zeilen AWT, Swing, JavaFX & SWT 1
J Warum kann ich die Spaltennummer in der Konsole anzeigen, diese aber nicht speichern ? AWT, Swing, JavaFX & SWT 6
VPChief Icons in 2 Jlabels Director nebeneinander anzeigen AWT, Swing, JavaFX & SWT 26
E Auf JPanel malen und davor JComponenten anzeigen AWT, Swing, JavaFX & SWT 12
A Swing Datei lässt sich zwar speichern, aber nicht laden (Inhalt im JTextField anzeigen) AWT, Swing, JavaFX & SWT 18
S Text-Info in der Taskbar anzeigen AWT, Swing, JavaFX & SWT 15
R JavaFX Label oder Imageview anzeigen mit Buttonklick AWT, Swing, JavaFX & SWT 4
B ArrayList, Strings anzeigen AWT, Swing, JavaFX & SWT 1
P Abwächselnd ein Punkt und ein x anzeigen AWT, Swing, JavaFX & SWT 2
A Fenster genau unterhalb von JTextField anzeigen AWT, Swing, JavaFX & SWT 1
N Wie kann ich zwei Grafiken in einer Oberfläche anzeigen lassen? AWT, Swing, JavaFX & SWT 8
T Swing Buffered Image anzeigen AWT, Swing, JavaFX & SWT 45
E Aktuelle Uhrzeit auf jeder Stage anzeigen lassen (JavaFX) AWT, Swing, JavaFX & SWT 2
F JavaFX Aktuelle Zeit in einem TextField anzeigen AWT, Swing, JavaFX & SWT 7
CptK Swing DropdownMenu über Panel-Grenzen hinaus anzeigen AWT, Swing, JavaFX & SWT 1
M JavaFX Bild zur ImageView in einem Kreis anzeigen. AWT, Swing, JavaFX & SWT 4
F Countdown in Label anzeigen AWT, Swing, JavaFX & SWT 14
M Loading Screen anzeigen bei Black Screen AWT, Swing, JavaFX & SWT 1
J CheckComboBox : Ausgewählte Items NICHT im Header anzeigen AWT, Swing, JavaFX & SWT 4
D MySQL Daten in JTable anzeigen AWT, Swing, JavaFX & SWT 2
I Bild über FXML (ImageView, Image) anzeigen AWT, Swing, JavaFX & SWT 1
K Event Handling Über JMenuBar die diversen Panels anzeigen AWT, Swing, JavaFX & SWT 10
G JComboBox: Arrow-Button permanent anzeigen AWT, Swing, JavaFX & SWT 4
L JavaFX Animation, erst zeichnen dann anzeigen AWT, Swing, JavaFX & SWT 4
J CheckComboBox selected Items nicht anzeigen AWT, Swing, JavaFX & SWT 6
L Suchergebnisse variabel mit Button anzeigen lassen AWT, Swing, JavaFX & SWT 3
M JavaFX Ein Labeltext eine zeitlang anzeigen dann weiter machen AWT, Swing, JavaFX & SWT 3
R Swing Verändern der Ausrichtung JButton und neu anzeigen AWT, Swing, JavaFX & SWT 2
J Slider Wert anzeigen AWT, Swing, JavaFX & SWT 15
D MySQL-Tabellen in GUI anzeigen AWT, Swing, JavaFX & SWT 8
Meeresgott AWT JFileChooser bestimmte Ordner anzeigen AWT, Swing, JavaFX & SWT 16
A JScrollPane soll JPanel mit JButtons enthalten und eine Scollbar anzeigen AWT, Swing, JavaFX & SWT 1
M PDF einlesen und innerhalb Pane anzeigen AWT, Swing, JavaFX & SWT 5
S Zwei JTree, ein Model, bei Selection im ersten JTree soll der zweite die Inhlate anzeigen AWT, Swing, JavaFX & SWT 2
M JavaFX StackedBarChart y-Axis soll nur Integerwerte anzeigen AWT, Swing, JavaFX & SWT 1
MiMa PDF in Java FX anzeigen AWT, Swing, JavaFX & SWT 21
T JLabel Textinhalt von Oben anzeigen AWT, Swing, JavaFX & SWT 1
Sugan Java FX Verzeichnisüberwachung -> Bilder auf GUI anzeigen AWT, Swing, JavaFX & SWT 4
Cromewell JavaFX Nur bestimmten Teil eines Canvas rendern und anzeigen AWT, Swing, JavaFX & SWT 2
C Benutzername in GUI eingeben und nach Spiel neues Fenster Benutzername wieder anzeigen AWT, Swing, JavaFX & SWT 1
M Gui-Form alle Labels anzeigen AWT, Swing, JavaFX & SWT 4
J Swing Zeichenfläche im JPanel des Haupfenster anzeigen lassen AWT, Swing, JavaFX & SWT 4
Z Swing Variable eines Objekt aus Hashmap in JList anzeigen AWT, Swing, JavaFX & SWT 1
beatles Swing JTextField - Game Status aus Array anzeigen AWT, Swing, JavaFX & SWT 3
M Java FX Immer aktuelle Mausposition anzeigen AWT, Swing, JavaFX & SWT 6
J Eigene Klasse auf Basis Textfield in SceneBuilder anzeigen AWT, Swing, JavaFX & SWT 4
L wie Layout-Grid in JXPanel anzeigen? AWT, Swing, JavaFX & SWT 5
JavaMachtMichFertig JavaFX Gui - Löschbutton in Tabelle anzeigen, die mittels MySQL Abfrage gefüllt wird AWT, Swing, JavaFX & SWT 5
stylegangsta JButton Transparent anzeigen AWT, Swing, JavaFX & SWT 9
F JavaFX JavaFX HTMLEditor-Eingabe in Textarea als HTML anzeigen AWT, Swing, JavaFX & SWT 2
V JFreeChart: Tooltip auf Knopfdruck anzeigen AWT, Swing, JavaFX & SWT 2
K Swing JScrollPane - JScrollBar anzeigen, wenn Frame verkleinert wird AWT, Swing, JavaFX & SWT 3
D Swing Idealgewicht anzeigen per Radiobuttonaktivierung AWT, Swing, JavaFX & SWT 8
J JavaFX Tooltip Verzögerung beim ersten Anzeigen AWT, Swing, JavaFX & SWT 4
D JButton - Nur Icon anzeigen / transparenter Hintergrund AWT, Swing, JavaFX & SWT 2
I JTable: Doppelklick auf Table soll neues Fenster öffnen und Daten aus JTable anzeigen AWT, Swing, JavaFX & SWT 4
B Swing JXMapKit Mausemove in Label anzeigen AWT, Swing, JavaFX & SWT 0
J JavaFX TextArea dynamisch Icon im Background anzeigen AWT, Swing, JavaFX & SWT 2
D Swing Erstes Item einer JCombobox in JTable anzeigen AWT, Swing, JavaFX & SWT 2
V Wie kann ich die Schrift in Java vollkommen anzeigen AWT, Swing, JavaFX & SWT 1
F Menüs in allen Fenstern anzeigen AWT, Swing, JavaFX & SWT 12
J 2D-Grafik Windows Blue-Screen nach anzeigen eines Bildes in Java AWT, Swing, JavaFX & SWT 10

Ähnliche Java Themen

Neue Themen


Oben