2D-Grafik JFreeChart DateAxis

Kevyzar

Mitglied
Guten Tag Lady's and Gentleman. :bae:

Ich habe mein Programm eigentlich soweit ich es brauche fertig, jetzt geht es für mich selbst nurnoch um.. Naja, kleinigkeiten die mich aber dennoch soweit stören, dass ich sie gerne verändert hätte..

Ich habe eine Datenbank, die jede Minute einen aktuellen Datensatz bekommt, da mein Programm aber wahrscheinlich längerfristig genutzt werden soll bräuchte ich ein paar Denkanstöße(Oder einfach damit ich JFreeChart endlich los bin, am besten einen Lösungsvorschlag)

Es geht eigentlich nur um die Formatierung..

Ich hätte mein Chart am liebsten:
2 Hauptmarker
1. Anfangsmarker(Zeit selber bestimmen)
2. Endmarker(aktuelle Zeit)
__________
Mein Code sieht derzeit so aus:

Java:
	public DateAxis DatumsAchse(DateTickUnitType dtu, int wert){
		SimpleDateFormat df = new SimpleDateFormat("dd.MM '-' HH:mm");
		DateAxis xAxis = new DateAxis("Datum in Tag/Monat - Stunde/Minute");
		xAxis.setDateFormatOverride(df);

		
		xAxis.setTickUnit(new DateTickUnit(dtu, wert));
		
		xAxis.setTickMarkPosition(DateTickMarkPosition.START);
		xAxis.setVerticalTickLabels(true);
		return xAxis;
	}


wobei ich allgemein erstmal einen DateTickUnitType.HOUR benutze und den wert dazu mit 6 Stunden.
Das DIagramm geht über 24 Einträge, die jede volle Stunde einen aktuellen Wert ablesen.

Ich habe wirklich schon viel rumgerätselt, und auch schon einige Methoden gegooglet, aber ich werde leider nicht fündig..

Mein Problem ist folgendes:
Entweder ist der Abstand der Zeiten zu gering, man kann an den Labels absolut NICHTSMEHR erkennen.
ODER
Die Abstände sind zu groß, und der Wert lässt sich nurnoch abschätzen.

Außerdem habe ich bei vielen eigenen Versuchen auch das Problem, dass die DateAxis nur noch einen einzigen Wert anzeigt, obwohl mehr erwartet wird.

Hatte eigentlich damit schon abgeschlossen, und wollte es so fertig stellen, aber wenn man doch nochmal das I-Tüpfelchen drauf setzen möchte, dann muss sowas halt "perfektioniert" werden..

Ich hoffe ihr könnt mir helfen..

Liebe grüße!
 
okey, meine glaskugel sagt... "überschreib paint und mach whoosh magic" ... und ich gebe ihr recht.

ne mal im ernst, ich habe verstanden das du irgendwas grafisch in einem chart darstellen möchtest, aber ich habe keinen schimmer was. dazu kommt, das du hier mehrere probleme vermischt.

zum thema chart: https://www.google.de/search?hl=de&site=imghp&tbm=isch&source=hp&q=chart&oq=chart
es gibt 1001 möglichkeiten charts zu machen, welche form möchtest denn haben? darf es eine torte sein, oder balken, oder doch candlestick?

zum thema datenerhebung: benutz im ersten schritt dummy-daten für dein vorhaben, wenns mit denen geht kannst du deine richtige datenquelle anbinden (z.B. eine DB o.ä.)

und im übrigen: nen screenshot wäre auch ganz hilfreich 😉
 
Zuletzt bearbeitet:
Wieso verwendest du überhaupt eine fixe tick unit? JFreeChart bzw. die Klassen, die sich von ValueAxix ableiten, verfügen über einen Mechanismus, mit dem so viele tick labels auf der Achse angezegt werden wie PLatz haben ohne sich zu überlappen. Lass mal den Aufruf
Code:
xAxis.setTickUnit(new DateTickUnit(dtu, wert));
weg und schau was passiert.
Falls dir nicht passt, was JFreeChart für dich auswählt, kannst du der DateAxis eine eigene Liste mit TickUnits verpassen, eine sogenante TickUnitSource. Um eine solche zu erstellen, kannst du dir anschauen, wie JFreeChart die default tick unit source erstellt (statische methode DateAxis.createStandardDateTickUnits).
 
Hi.
Mist, ich hab echt versucht alle wichtigen Daten anzugeben..^^

Ich möchte ein XY Diagramm machen, für die x-Achse habe ich eine DateAxis verwendet..

Die Datenquelle steht schon, ich kann Daten wann wie wo wie oft ich will auslesen, das dürfte nicht das Problem sein.
Im Anhang ist ein Bild, wie ich es derzeit habe.

Das Problem ist die Skalierung.
Wenn ich es z.b. auf eine Woche setze, dann kann ich dies nicht ordentlich skalieren.
Die x-Achse ist dann entweder mit bezeichnungen vollgeknallt, so dass sie schon überlappen, oder man erkennt nichts.

Sagen wir ich möchte die x achse ungefähr so haben
|
| . . .
| . . . .
| .
| .
|x1___________________x2



x1 ist der anfang, (setRange..) x1 = vor 7 tagen
Und das DefaultXYDataset soll 84 Werte haben(7*12 - alle 2 stunden ein Wertepaar bis vor genau 7 tagen)

Dies gut zu skalieren ist für mich ein Rätsel, das Frame wird wahrscheinlich auch nie 800*600 überschreiten.

Ich hoffe jetzt sind es genug Infos

Liebe grüße!


€dit:

Das Problem hatte ich vorher..^^

Jetzt sind es für meinen Geschmack eindeutig zuviele Labels, gibt es eine Möglichkeit dieses Grid(Im Hintergrund) so zu lassen? Habe zwei neue Anhänge hinzugefügt. Das erste wie es jetzt ist, das zweite wie es sein sollte.
 

Anhänge

  • xd123^11.JPG
    xd123^11.JPG
    40,6 KB · Aufrufe: 40
  • Anhang1.JPG
    Anhang1.JPG
    52,1 KB · Aufrufe: 41
  • Anhang2.JPG
    Anhang2.JPG
    53,3 KB · Aufrufe: 42
Zuletzt bearbeitet:
Okay, ich habe mich dazu entschieden doch JFreeChart die Einteilung übernehmen zu lassen.

Ich wäre allerdings froh zu Testzwecken ein Beispiel zu bekommen.. 🙂

Falls dir nicht passt, was JFreeChart für dich auswählt, kannst du der DateAxis eine eigene Liste mit TickUnits verpassen, eine sogenante TickUnitSource. Um eine solche zu erstellen, kannst du dir anschauen, wie JFreeChart die default tick unit source erstellt (statische methode DateAxis.createStandardDateTickUnits).

Außerdem habe ich noch ein letztes Problem:

Das Diagramm zeigt so klobige viereckige Punkte, ich habe schon viel gegooglet, aber ich weiß nicht woran es liegt, dass ich als einen Datenpunkt ein viereck bekomme, fände es einiges besser, wenn ich einen kleinen kreis hätte, oder einfach eine durchgehende Linie.

Java:
public DefaultXYDataset data(double[][] datenset, String Bezeichnung) {
		double[][] ij = new double[2][12];
		ij = datenset;
		XYDataset dataset = new DefaultXYDataset();
		((DefaultXYDataset)dataset).addSeries(Bezeichnung, ij);
		return (DefaultXYDataset)dataset;
	}
	
	public DateAxis datumsAchse(){
		SimpleDateFormat df = new SimpleDateFormat("dd.MM '-' HH:mm");
		DateAxis xAxis = new DateAxis("Datum in Tag/Monat - Stunde/Minute");
		xAxis.setDateFormatOverride(df);
		xAxis.setTickMarkPosition(DateTickMarkPosition.START);
		xAxis.setVerticalTickLabels(true);
		return xAxis;
	}
	
	public ValueAxis wertAchse(String Kategorie){
		ValueAxis yAxis = new NumberAxis(Kategorie);
		return yAxis;
	}
	
	public XYItemRenderer itemRender(){
		XYItemRenderer renderer = new XYLineAndShapeRenderer();
		return renderer;
	}
	
	public ChartPanel createChartPanel(String name, int comboboxItem){
		DatenbankAbfragen t2 = new DatenbankAbfragen();
		DiagrammErsteller DDD = new DiagrammErsteller();
		String row="";
		String xAxisbeschreibung="";
		if (name.equals("Helligkeit")){
			row = "Helligkeit";
			xAxisbeschreibung = "Helligkeit in Lux";
		} else if (name.equals("Temperatur")){
			row = "Temperatur";
			xAxisbeschreibung = "Temperatur in °C";
		} else if (name.equals("Luftfeuchtigkeit")) {
			row = "Luftfeuchtigkeit";
			xAxisbeschreibung = "Luftfeuchtigkeit in %";
		} else if (name.equals("Luftdruck")){
			row = "Luftdruck";
			xAxisbeschreibung = "Luftdruck in milliBar";
		}
		DateAxis dt = DDD.datumsAchse();
		
		XYPlot x = new XYPlot();
		try
		{
			x = new XYPlot(DDD.data(t2.wert(row,comboboxItem),xAxisbeschreibung), dt, DDD.wertAchse(row), DDD.itemRender());
			
		}
		catch(SQLException e)
		{
			// TODO Auto-generated code
			e.printStackTrace();
		}
		JFreeChart c = new JFreeChart(row, new Font("Tahoma",2,22), x, true);
		ChartPanel cp = new ChartPanel(c);
		return cp;
	}


Ich hoffe ihr könnt mir helfen..
Und danke für die bisherige Hilfe! Große Klasse dieses Forum! 🙂

Liebe grüße!
 

Anhänge

  • klobige Punkte.JPG
    klobige Punkte.JPG
    14,4 KB · Aufrufe: 33
Zuletzt bearbeitet:
Hallo Kevyzar,
hier ein bisschen Demo-Code
Java:
public class SimpleXYPlot {

    public static void main(String[] args) {
        int count = 500;
        int series = 5;
        DefaultXYDataset dataset = new DefaultXYDataset();
        long start = System.currentTimeMillis();
        long increment = 1000*60*20; //20 min
        for(int s = 0; s < series; s++){
            double[][] data = new double[2][count];
            for(int i = 0; i < count; i++){
                data[0][i] = start + increment * i;
                data[1][i] = (s + 1)*i;
            }
            dataset.addSeries("Series " + s, data);
        }
        DateAxis xAxis = new DateAxis("x axis");
        xAxis.setStandardTickUnits(createStandardDateTickUnits());
        NumberAxis yAxis = new NumberAxis("y axis");
        XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(false, true);
        renderer.setUseOutlinePaint(true);
        Shape shape = new Ellipse2D.Double(-4, -4, 8, 8);
        for(int i = 0; i < series; i++){
            renderer.setSeriesShape(i, shape);
            renderer.setSeriesOutlinePaint(i, Color.black);
        }
        XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer);
        BasicStroke lineStroke = new BasicStroke(1.0f);
        plot.setDomainMinorGridlinesVisible(true);
        plot.setDomainMinorGridlineStroke(lineStroke);
        plot.setDomainGridlineStroke(lineStroke);
        plot.setDomainMinorGridlinePaint(Color.gray);
        plot.setDomainGridlinePaint(Color.BLACK);
        JFreeChart chart = new JFreeChart(plot);
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new ChartPanel(chart));
        frame.pack();
        frame.setVisible(true);
    }
    public static TickUnitSource createStandardDateTickUnits() {

        TickUnits units = new TickUnits();

        // date formatters
        DateFormat f1 = new SimpleDateFormat("dd HH:mm:ss.SSS");
        DateFormat f2 = new SimpleDateFormat("dd HH:mm:ss");
        DateFormat f3 = new SimpleDateFormat("dd HH:mm");
        DateFormat f4 = new SimpleDateFormat("dd.MM. HH:mm");
        DateFormat f5 = new SimpleDateFormat("dd.MM.");
        DateFormat f6 = new SimpleDateFormat("MM/yyyy");
        DateFormat f7 = new SimpleDateFormat("yyyy");

        // milliseconds
        units.add(new DateTickUnit(DateTickUnitType.MILLISECOND, 1, f1, 2));
        units.add(new DateTickUnit(DateTickUnitType.MILLISECOND, 5,
                DateTickUnitType.MILLISECOND, 1, f1, 5));
        units.add(new DateTickUnit(DateTickUnitType.MILLISECOND, 10,
                DateTickUnitType.MILLISECOND, 1, f1, 4));
        units.add(new DateTickUnit(DateTickUnitType.MILLISECOND, 25,
                DateTickUnitType.MILLISECOND, 5, f1, 5));
        units.add(new DateTickUnit(DateTickUnitType.MILLISECOND, 50,
                DateTickUnitType.MILLISECOND, 10, f1, 5));
        units.add(new DateTickUnit(DateTickUnitType.MILLISECOND, 100,
                DateTickUnitType.MILLISECOND, 10, f1, 4));
        units.add(new DateTickUnit(DateTickUnitType.MILLISECOND, 250,
                DateTickUnitType.MILLISECOND, 10, f1, 5));
        units.add(new DateTickUnit(DateTickUnitType.MILLISECOND, 500,
                DateTickUnitType.MILLISECOND, 50, f1, 5));

        // seconds
        units.add(new DateTickUnit(DateTickUnitType.SECOND, 1,
                DateTickUnitType.MILLISECOND, 50, f2, 2));
        units.add(new DateTickUnit(DateTickUnitType.SECOND, 5,
                DateTickUnitType.SECOND, 1, f2, 5));
        units.add(new DateTickUnit(DateTickUnitType.SECOND, 10,
                DateTickUnitType.SECOND, 1, f2, 4));
        units.add(new DateTickUnit(DateTickUnitType.SECOND, 30,
                DateTickUnitType.SECOND, 5, f2, 3));

        // hours
        units.add(new DateTickUnit(DateTickUnitType.HOUR, 1,
                DateTickUnitType.MINUTE, 5, f3, 2));
        units.add(new DateTickUnit(DateTickUnitType.HOUR, 2,
                DateTickUnitType.MINUTE, 10, f3, 4));
        units.add(new DateTickUnit(DateTickUnitType.HOUR, 4,
                DateTickUnitType.MINUTE, 30, f3, 4));
        units.add(new DateTickUnit(DateTickUnitType.HOUR, 6,
                DateTickUnitType.HOUR, 1, f3, 3));
        units.add(new DateTickUnit(DateTickUnitType.HOUR, 12,
                DateTickUnitType.HOUR, 1, f4, 4));

        // days
        units.add(new DateTickUnit(DateTickUnitType.DAY, 1,
                DateTickUnitType.HOUR, 1, f5, 4));
        units.add(new DateTickUnit(DateTickUnitType.DAY, 2,
                DateTickUnitType.HOUR, 1, f5, 4));
        units.add(new DateTickUnit(DateTickUnitType.DAY, 7,
                DateTickUnitType.DAY, 1, f5, 7));
        units.add(new DateTickUnit(DateTickUnitType.DAY, 15,
                DateTickUnitType.DAY, 1, f5, 5));
        return units;

    }
}
und hier die Erläuterungen:
1. Der Code zur Erstellung der TickUnitSource wurde aus dem Code für die DateAxis herauskopiert und etwas verändert. a) Alle DateTickUnits (auch die für den Millisekunden-Bereich) enthalten jetzt den Tag des Monats. b) Die TickUnits für den Minutenbereich werden nicht angelegt. Letzteres siehtst du daran, daß, wenn du in einen Bereich < 1 h reinzoomst, keine tick labels erscheinen, weil die DateAxis in dem Zoombereich keine passenden mehr findet, die ohne Überlappung dargestellt werden könnten. Erst wenn du weiter reinzoomst, erscheinen die tick labels wieder.
2. Die sog. minor grid lines wurden eingeblendet. Das ist im Prinzip ein Gitter ohne labels.
3. Durch einen anderen Konstruktor wuirde der XYLineAndShapeRenderer angewiesen, keine Linien mehr zu zeichnen, sondern nur noch Symbole.
4. Als Symbole werden einheitlich Kreise verwendet, es tut aber jede beliebige Shape. Du musst nur darauf achten, daß die Shape um den Ursprung zentriert ist.
5. Die Kreise bekommen eine konstrastfarbige Umrandung.
HTH
 
Hmpf, leider kann ichs nicht mehr editieren.
Worauf ich gesondert hinweisen möchte: Du kannst dir im prinzip auch den Aufruf von
Code:
dateAxis.setDateFormatOverride(DateFormat df)
sparen, wenn du dir in der TickUnitSource geeignete DateFormats definierst.
 
Guten Tag, Problem hat sich nun endgültig gelöst.
Habe den renderer.setSeriesShape nur falsch bedient, folgendes hat gewünschten Effekt erbracht:

Java:
public XYLineAndShapeRenderer itemRender(int i){
		XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
		Shape shape = new Ellipse2D.Float(-2,-2,4,4);
                /* .. */
                renderer.setSeriesShape(0,shape);
		return renderer;
	}
€dit:

Ich habe eben deinen Beitrag erst gesehen, da war ich etwas voreilig, und vielen Dank, dass du dir die Mühe gemacht hast, mir zu antworten! 🙂

Ich habe aber leider folgendes Problem beim einfügen des testcodes.

"The constructor DateTickUnit(DateTickUnitType, int, DateTickUnitType, int, DateFormat, int) is undefined"
"The constructor DateTickUnit(DateTickUnitType, int, DateFormat, int) is undefined"
etc.
Java:
units.add(new DateTickUnit(DateTickUnitType.MILLISECOND, 10,
                DateTickUnitType.MILLISECOND, 1, f1, 4));

Ich werde mich im laufe des Abends tiefgehender damit beschäftigen.
Liebe Grüße
 
Zuletzt bearbeitet:
Hallo,
ich verwende noch Version 1.0.13. Mein Codeschnipsel stammt auch aus dieser Version. Offenbar wurde in einer aktuelleren Version der Konstruktor von DateTickUnit geändert, so daß die Anzahl der "minor ticks" (Achsenstriche ohne Label) nicht mehr gesetzt wird.
Lass einfach das letzte int Argument weg und schau was passiert.
 
So heute hatte ich endlich genug Zeit, um mir deinen Beitrag mal genauer anzusehen.

Also weitestgehend hab ich es verstanden! :toll:
(Hoffe ich zumindest)

Bleibt eigentlich keine Frage mehr offen, obwohl ich zum Verständnis noch eine hätte, aber das sprengt hier langsam den Rahmen..

Also großen Dank an dich Harry, dass du dir die Zeit genommen hast mir zu Antworten.:applaus:
 
Zuletzt bearbeitet:

Zurück
Oben