JPanel - zeichnen eines Arrays

Status
Nicht offen für weitere Antworten.

redbomber

Bekanntes Mitglied
Hi zusammen,
vielleicht könnt ihr mir ja auf die Sprünge helfen.

Ich möchte einen Array, der mit Werten gefüllt ist (Integer oder Double) zeichnen.
Soll so etwas wie ein Plot werden.

In der paintComponent Methode meines JPanels, mache ich dies, indem ich den array durchlaufe und immer zwischen zwei Zeichen eine g.drawLine Linie ziehe.

Ok, das was ich dann habe entspricht aber der "negativ" Zeichnung.

Jetzt meine Frage.
Muss ich davor den Min/Max Wert des Arrays bestimmen und dann für jeden Punkt komplizierte Berechnungen durchführen, damit ich für jeden Punkt die korrekten Koordinaten heraus bekomme?

Oder gibt es da eine einfacher Möglichkeit?
 

Marco13

Top Contributor
Was meinst du mit "negativ"? Kann es sein, dass du nur überall statt
g.drawLine(x0,y0,x1,y1);
sowas schreiben musst wie
g.drawLine(x0,getHeight()-y0,x1,getHeight()-y1);

!?
 

redbomber

Bekanntes Mitglied
also mit "negativ" meine ich, dass er ja immer die linke obere Ecke als (0,0) Ursprung ansieht.

Also muss ich mir vermutlich erst einmal berechnen, wie groß mein Wertebereich ist.
Ich probiere das gleich mal mit getHeight();
 

redbomber

Bekanntes Mitglied
das hat leider nicht funktioniert.

Aber gibt es in Swing nicht schon irgend etwas vorgefertigtes, welches das zeichnen von Plots vereinfacht?
 

Ebenius

Top Contributor
redbomber hat gesagt.:
Aber gibt es in Swing nicht schon irgend etwas vorgefertigtes, welches das zeichnen von Plots vereinfacht?
Bei Swing ist nix dabei. Gibt aber ne ganze Menge Zeugs was man benutzen könnte: Java+Swing+Plot.

Ansonsten mit AffineTransform den Zeichenbereich transformieren und dann einfach im Wertebereich zeichnen. In etwa so (im Browser getippt und ungetestet):
Code:
protected void paintComponent(Graphics g) {
  final Graphics2D g2d = (Graphics2D) g;
  final AffineTransform orgTf = g2d.getTransform();
  try {
    g2d.scale(myMaxX * 1. / getWidth, myMaxY * -1. / getHeight);
    // do your painting in target coord system here
  } finally {
    g2d.setTransform(orgTf);
  }
}
Ebenius
 

redbomber

Bekanntes Mitglied
hey, ja hatte auch schon gegoogelt.
Aber es werden entweder nur fertige Anwendungen angeboten, oder man findet Code für komplexe scatter Plots.

Aber ein einfaches Beispiel in dem einfach ein paar (x,y) Punkte gezeichnet werden ist leider nicht dabei.
 

redbomber

Bekanntes Mitglied
sorry aber bekomms leider noch immernicht hin...

kann mir vielleicht jemand erklären was das Prinzip des ganzen ist?

Also ich habe meinen Array mit Daten.
Von diesem bestimme ich folgende Werte:

maxX
maxY
minX
minY

also kann ich damit schon einmal eine Fläche aufspannen :)

Ok, dann weiter:
Ich besitze ein JPanel mit bestimmter Größe, also besitze ich auch folgendes:

gethHeight()
getWidth()

So und nun blick ich es nicht mehr.

Wie setzte ich das ganze Fenster auf meinen Wertebereich? Wie zeichne ich die einzelnen Werte aus meinem Array in das JPanel?
 

Marco13

Top Contributor
Du hast Werte (x,y) und die besagten xMin...yMax und width und height. Jetzt kommt das, was man glaubich "Dreisatz" nennt: Man rechnet den Wert (x,y) so um, dass man seine eine "Relative Position" innerhalb des (von xMin...yMax) aufgespannten Recheteckes bekommt. Die Position des Punktes innerhalb dieses Rechteckes wird also mit Koordinaten (rx,ry) beschrieben, die beide zwischen 0 und 1 liegen:

float rx = (x-xMin)/(xMax-xMin);
float ry = (y-yMin)/(yMax-yMin);

Oder an einem Beispiel: Bei xMin = 50 und xMax = 150 liegt ein Punkt, der bei x=100 liegt, genau in der Mitte des Rechtecks - in diesem fall sollte rx=0.5 sein (und das ist auch so :wink: )

Diese relativen Positionen kann man dann wieder auf die Fenstergröße hochrechnen:

int fx = (int)(rx*getWidth());
int fy = (int)(ry*getHeight());

Ein Punkt, der vorher in der Mitte des Rechtecks (also bei x=0.5) lag, liegt dann in der Mitte des Fensters (eben bei getWidth()*0.5)

Diese beiden Schritte kann man auch zu einem Schritt zusammenfassen, aber wenn man sie getrennt läßt, ist es intuituver und kann einige Vorteile bezüglich Flexibilität bringen. (Optimierungen zum Vermeiden überflüssiger Zwischenschritte kann man später machen...)
 

redbomber

Bekanntes Mitglied
also meine paintComponent Methode sieht nun wie folgt aus:

Code:
 public void paintComponent (Graphics g)
    {
    	super.paintComponent(g);
    	  final Graphics2D g2d = (Graphics2D) g;
    	  final AffineTransform orgTf = g2d.getTransform();
    	  try {
    	    g2d.translate(5., 5.);
    	    for (int i = 0; i < data.size() - 1; i++) {
    			double rx1 = ((i) - minx) / (maxx - minx);
    			double ry1 = (data.get(i) - miny) / (maxy - miny);
    			double rx2 = ((i + 1) - minx) / (maxx - minx);
    			double ry2 = (data.get(i + 1) - miny) / (maxy - miny);

    			int fx1 = (int) (rx1 * getWidth());
    			int fy1 = (int) (ry1 * getHeight());
    			int fx2 = (int) (rx2 * getWidth());
    			int fy2 = (int) (ry2 * getHeight());

    			g2d.setColor(Color.GREEN);
    			g2d.drawLine(fx1, fy1, fx2, fy2);

    		}
    	    
    	    if(drawLine){
    			g2d.setColor(Color.CYAN);
    			g2d.drawLine((int)xLinePos, 0, (int)xLinePos, getWidth()); 
    		}
    	    
    	  } finally {
    	    // reset old transform
    	    g2d.setTransform(orgTf);
    	  }

	}

Trotzdem wird aber der Plot immernoch horizontal gespiegelt dargestellt.

Das ganze habe ich auch verwendet um mittels ToolTipText mit die Position in x,y Koordinaten anzeigen zu lassen.
Hier bestätigt sich, dass ich links oben meinen Ursprung habe.
 

Ebenius

Top Contributor
redbomber, Du musst die Beispiele schon lesen. Ich hab oben doch scale geschrieben... Für y negativ!
 

redbomber

Bekanntes Mitglied
ja aber wenn ich
Code:
g2d.scale(1., -1.);

oder auch
Code:
g2d.scale(myMaxX * 1. / getWidth(), myMaxY * -1. / getHeight());
verwende, dann bekomme ich überhaupt keine Koordinaten gezeichnet.

Brauche ich denn die scale Methode überhaupt wenn ich die Koordinaten so umrechne wie Marco13 es beschrieben hat?

Die Koordinaten werden schon horizontal gespiegelt.

Also wenn meine Datenwerte zu Beginn ansteigen, dann fallen sie im Plot entsprechend ab (und umgekehrt)
 

Marco13

Top Contributor
Poste ein kleines, compilierbares(!!!!) sofort ausführbares Beispielprogramm (mit irgendwelchen "Dummy-Werten" in einem Test-Array, und meinetwegen festen min/max Werten und so). Dann füge ich dir das fehlende "getHeight()-" ein :bae:
 

redbomber

Bekanntes Mitglied
sodele :)
Code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;




public class Test {

	protected static ArrayList<Double> data = new ArrayList();
	static double miny=Double.MAX_VALUE, minx=Double.MAX_VALUE, maxy=Double.MIN_VALUE, maxx=Double.MIN_VALUE;
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		JFrame frame = new JFrame();
		frame.setTitle("Plotting Window");
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.setVisible(true);
		// Kann man hiermit in der Mitte positionieren
		frame.setLocation(0,0);
		frame.setResizable(false);
		setData();
		JScrollPane scrollPane = new JScrollPane(new MyPanel());
		scrollPane.setVisible(true);
		scrollPane.setBackground(Color.WHITE);
		
		
		//scrollPane.setViewport(panel);
		frame.add(scrollPane);
    	frame.pack();
    	
		
	}
	
	public static class MyPanel extends JPanel{
		
		public MyPanel(){
			this.setBackground(Color.WHITE);
			this.setPreferredSize(new Dimension(5000, 200));
                        this.setSize(5000, 200);
	    	//buffer = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
			this.setOpaque(true);
			
			this.setVisible(true);
			this.setBorder(BorderFactory.createLineBorder(Color.black, 1));

	    	setMinMaxValues(this);
		}
		
		 public void paintComponent (Graphics g)
		    {

				super.paintComponent(g);
				
				final Graphics2D g2d = (Graphics2D) g;
				final AffineTransform orgTf = g2d.getTransform();
				try {
					g2d.setColor(Color.GREEN);
					for (int i = 0; i < data.size() - 1; i++) {
						// this.setForeground(Color.RED);
						double rx1 = ((i) - minx) / (maxx - minx);
						double ry1 = (data.get(i) - miny) / (maxy - miny);
						double rx2 = ((i + 1) - minx) / (maxx - minx);
						double ry2 = (data.get(i + 1) - miny) / (maxy - miny);

						int fx1 = (int) (rx1 * getWidth());
						int fy1 = (int) (ry1 * getHeight());
						int fx2 = (int) (rx2 * getWidth());
						int fy2 = (int) (ry2 * getHeight());

						g2d.setColor(Color.GREEN);
						g2d.drawLine(fx1, fy1, fx2, fy2);
					}

				} finally {
					// reset old transform
					g2d.setTransform(orgTf);
				}

			}
		 
		 protected void setMinMaxValues(MyPanel panel){	
				minx = 0;
				maxx = data.size();
				
		    	for(int i = 1; i < data.size(); i++){
		    		miny = miny<data.get(i)?miny:data.get(i);
		    		maxy = maxy>data.get(i)?maxy:data.get(i);
		    	}

		    	System.out.println("minx: " + minx);
		    	System.out.println("maxx: " + maxx);
		    	System.out.println("miny: " + miny);
		    	System.out.println("maxy: " + maxy);
		    	System.out.println("width: " + panel.getWidth());
		    	System.out.println("height: " + panel.getHeight());
		    }
	}
	
	
	
	protected static void setData(){
		data.add(10.);
		data.add(14.);
		data.add(15.);
		data.add(20.);
		data.add(14.);
		data.add(12.);
		data.add(9.);
		data.add(7.);
		data.add(4.);
		data.add(2.);
		data.add(-3.);
		data.add(-9.);
		data.add(-12.);
		data.add(-9.);
		data.add(-3.);
		data.add(2.);
		data.add(6.);
		data.add(13.);
		data.add(17.);
		data.add(22.);
	}

}
 

redbomber

Bekanntes Mitglied
dabie habe ich dann die folgenden Werte:

minx: 0.0
maxx: 20.0
miny: -12.0
maxy: 22.0
width: 5000
height: 200
 

Marco13

Top Contributor
Eigentlich würde ich ja rein der vollständigkeit halber wieder was compilierbares posten, aber da man (wie ich schon in der ersten Antwort geschrieben habe) NUR die Zeile 84 ändern muss in
g2d.drawLine(fx1, getHeight()-fy1, fx2, getHeight()-fy2);
lohnt sich das eigentlich nicht...
 

Ebenius

Top Contributor
Da ist ein hübscher Fehler in Deiner Klasse. Double.MIN_VALUE ist nicht der kleinstmögliche Double-Wert, sondern ein Wert der so klein wie möglich größer als 0 ist. Bei Double muss
Code:
-Double.MAX_VALUE
verwendet werden! Bei Float entsprechend.

Ebenius
 

Ebenius

Top Contributor
So geht's ansonsten sehr hübsch.
Code:
public void paintComponent(Graphics g) {
  super.paintComponent(g);

  final Graphics2D g2d = (Graphics2D) g;
  final AffineTransform orgTf = g2d.getTransform();
  final Stroke orgStroke = g2d.getStroke();
  try {
    /* get the component size */
    final Insets ins = getInsets();
    final int width = getWidth() - ins.left - ins.right;
    final int height = getHeight() - ins.top - ins.bottom;

    /* transform view into codomain */
    g2d.translate(ins.left, ins.top);
    g2d.scale((width - 1) / (maxx - 1), -(height - 1) / (maxy - miny));
    g2d.translate(minx, -maxy);

    /* assign a 1px stroke */
    g2d.setStroke(new BasicStroke(1f / width, BasicStroke.CAP_ROUND,
          BasicStroke.JOIN_ROUND));

    final Line2D.Double line = new Line2D.Double();
    g2d.setColor(Color.GREEN);
    for (int i = 0; i < data.size() - 1; i++) {
      line.setLine(i, data.get(i).doubleValue(), i + 1, data.get(i + 1)
            .doubleValue());
      g2d.draw(line);
    }
  } finally {
    // reset old transform
    g2d.setTransform(orgTf);
    g2d.setStroke(orgStroke);
  }
}

[ edit ] Code geändert; Stroke wird im finally-Block zurück gesetzt. Die line-Variable könnte man natürlich noch zum Member machen...

Ebenius
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
S auf einem mit Netbeans (GUI) erstellten JPanel (eines JFrames) zeichnen? AWT, Swing, JavaFX & SWT 7
CptK Funktionsgraphen effizient zeichnen und nur Teile von JPanel erneuern AWT, Swing, JavaFX & SWT 2
W Swing JPanel nur einmal nach mehreren Änderungen neu zeichnen AWT, Swing, JavaFX & SWT 1
F Java Swing Rechteck in JPanel zeichnen AWT, Swing, JavaFX & SWT 7
J Linien auf JPanel zeichnen AWT, Swing, JavaFX & SWT 3
llabusch Linien in JPanel zeichnen AWT, Swing, JavaFX & SWT 6
M Kein Zeichnen der Figuren auf JPanel AWT, Swing, JavaFX & SWT 4
X Swing JPanel mehrere Ebenen zeichnen AWT, Swing, JavaFX & SWT 13
N JPanel neu zeichnen AWT, Swing, JavaFX & SWT 10
S Swing Bild auf jPanel nach Änderung von JComboBox zeichnen AWT, Swing, JavaFX & SWT 4
P JPanel neu zeichnen AWT, Swing, JavaFX & SWT 10
T Oval auf ein JPanel zeichnen AWT, Swing, JavaFX & SWT 3
S Swing Bild in JPanel in ScrollPane neu zeichnen AWT, Swing, JavaFX & SWT 2
H String auf Knopfdruck in JPanel zeichnen. AWT, Swing, JavaFX & SWT 6
L Freies zeichnen auf JPanel AWT, Swing, JavaFX & SWT 3
das-mo AWT In JPanel 2mal zeichnen AWT, Swing, JavaFX & SWT 3
R JPanel auf JFrame neu zeichnen AWT, Swing, JavaFX & SWT 11
P RAM-Auslastung - Problem. Zeichnen von JPEGs auf JPanel AWT, Swing, JavaFX & SWT 2
A Swing Zeichnen auf JPanel AWT, Swing, JavaFX & SWT 4
B Zeichnen von Bildern auf JPanel aus eigenem Objekt AWT, Swing, JavaFX & SWT 19
B Swing JPanel in Abhängigkeit von DefaultListModel Instanz neu zeichnen AWT, Swing, JavaFX & SWT 3
Sammay Swing JPanel nach dem einfügen neu zeichnen AWT, Swing, JavaFX & SWT 6
N JPanel zeichnen AWT, Swing, JavaFX & SWT 4
V Bild auf JPanel zeichnen AWT, Swing, JavaFX & SWT 9
G Swing Kreise auf JPanel zeichnen AWT, Swing, JavaFX & SWT 11
V Zeichnen auf JPanel und in JFrame einfügen AWT, Swing, JavaFX & SWT 16
D In JPanel zeichnen AWT, Swing, JavaFX & SWT 11
E Rechteck in JPanel Zeichnen AWT, Swing, JavaFX & SWT 6
S Koordinaten aus Array verwenden zum zeichnen auf JPanel?! AWT, Swing, JavaFX & SWT 3
0din Jpanel will nich alles zeichnen AWT, Swing, JavaFX & SWT 15
R JPanel - BufferedImage - zeichnen großer Bilder AWT, Swing, JavaFX & SWT 2
J Swing JScrollPane nimmt das JPanel zum Zeichnen nicht an AWT, Swing, JavaFX & SWT 5
R JPanel - zeichnen in skalierten Bereich - Linie (X-Achse) nicht sichtbar AWT, Swing, JavaFX & SWT 11
B Zeichnen in jPanel AWT, Swing, JavaFX & SWT 2
R JPanel - Markierung an der Mausposition zeichnen AWT, Swing, JavaFX & SWT 4
R JPanel in JScrollPane - zeichnen der Mausposition AWT, Swing, JavaFX & SWT 3
R JPanel in JScrollPane neu zeichnen AWT, Swing, JavaFX & SWT 7
G JPanel neu zeichnen mit repaint AWT, Swing, JavaFX & SWT 15
W Zeichnen verschiedener geom. Figuren in einem JPanel AWT, Swing, JavaFX & SWT 5
M In eigene JPanel Klasse zeichnen AWT, Swing, JavaFX & SWT 4
F JPanel übereinander zeichnen AWT, Swing, JavaFX & SWT 4
S Zeichnen in einem JPanel AWT, Swing, JavaFX & SWT 15
N Formen drehen und auf JPanel zeichnen AWT, Swing, JavaFX & SWT 6
B JPanel + Zeichnen AWT, Swing, JavaFX & SWT 3
S Problem mit dem Zeichnen einer Linie auf einem JPanel AWT, Swing, JavaFX & SWT 30
M Auf JPanel zeichnen AWT, Swing, JavaFX & SWT 17
H Punkte auf einem JPanel zeichnen AWT, Swing, JavaFX & SWT 4
G Auf JPanel zeichnen? AWT, Swing, JavaFX & SWT 2
P JPanel Inhalt neu zeichnen AWT, Swing, JavaFX & SWT 5
feuervogel in Jpanel zeichnen AWT, Swing, JavaFX & SWT 3
M JPanel ausserhalb von paintComponent zeichnen AWT, Swing, JavaFX & SWT 6
L Komponente und Grafik gleichzeitig auf JPanel zeichnen AWT, Swing, JavaFX & SWT 11
P Zwei JPanel übereianderlegen AWT, Swing, JavaFX & SWT 14
XWing Basic JPanel mit 2 Buttons beutzen. AWT, Swing, JavaFX & SWT 10
G JPanel per Drag and Drop JButtons und Bilder ablegen AWT, Swing, JavaFX & SWT 1
G JPanel mit JButtons und Bilder AWT, Swing, JavaFX & SWT 5
N AWT JPanel zu Jframe hinzufügen AWT, Swing, JavaFX & SWT 2
M clear JPanel before repainting AWT, Swing, JavaFX & SWT 1
B ImageIcon auf JPanel austauschen AWT, Swing, JavaFX & SWT 3
T Swing Reload JPanel + darin liegende ProgressBar AWT, Swing, JavaFX & SWT 9
P Swing Mehrere JLabels mit ImageIcon in JPanel lesen AWT, Swing, JavaFX & SWT 1
E JScrollPane mit JPanel verbinden AWT, Swing, JavaFX & SWT 1
F JPanel Celleditor AWT, Swing, JavaFX & SWT 8
B JPanel-Inhalte inkl. JTextarea zoomen? AWT, Swing, JavaFX & SWT 3
B Mit ContentPane werden Komponenten angezeigt, mit SplitPane, JPanel nicht? AWT, Swing, JavaFX & SWT 6
P Button simpler random auf einem JPanel verteilen? AWT, Swing, JavaFX & SWT 3
O Swing "Eigenes" JPanel wird dem JScrollPane nicht hinzugefügt AWT, Swing, JavaFX & SWT 5
Ich lerne Java. Swing Von JPanel A auf JPanel B zugreifen. AWT, Swing, JavaFX & SWT 4
A JPanel austauschen und Focus geben AWT, Swing, JavaFX & SWT 3
E Auf JPanel malen und davor JComponenten anzeigen AWT, Swing, JavaFX & SWT 12
L JComponent aus JPanel anhand Mausposition ermitteln AWT, Swing, JavaFX & SWT 10
J JPanel wird nicht angezeigt AWT, Swing, JavaFX & SWT 2
B Verschiebbares JPanel "ruckelt" im Randbereich AWT, Swing, JavaFX & SWT 2
S Swing JPanel nimmt keinen KeyListener an AWT, Swing, JavaFX & SWT 7
K JLabel mit Bilder im nicht initialisierten JPanel hinzufügen AWT, Swing, JavaFX & SWT 5
Hatsi09 Swing JPanel Bild einfügen AWT, Swing, JavaFX & SWT 14
L JPanel zeigt keinen Inhalt AWT, Swing, JavaFX & SWT 1
dereki2000 JPanel mit Rückgbe wie bei JOptionPane AWT, Swing, JavaFX & SWT 3
E Hintergrundfarbe setzen in JPanel funktioneirt nicht AWT, Swing, JavaFX & SWT 4
P JPanel KeyListener hinzufügen AWT, Swing, JavaFX & SWT 8
S Nach scrollen verschwindet das zuvor im JPanel gezeichnete AWT, Swing, JavaFX & SWT 2
P Bewegung eines Balkens in eineum JPanel welches als Spielfeld fungiert AWT, Swing, JavaFX & SWT 2
L Swing JPanel Größe anpassen AWT, Swing, JavaFX & SWT 6
D Platzierung von JTextfield in JPanel AWT, Swing, JavaFX & SWT 3
D Swing Anwendung ohne JPanel erstellen AWT, Swing, JavaFX & SWT 1
M Swing JPanel in JScrollPane AWT, Swing, JavaFX & SWT 3
M Zwei JPanel übereinander nur vorderes "repainten" AWT, Swing, JavaFX & SWT 3
J 2D-Grafik Background einer Jpanel Klasse ändern AWT, Swing, JavaFX & SWT 1
J Ziehen eines Buttons im JPanel AWT, Swing, JavaFX & SWT 2
J Button lässt sich nicht auf dem JPanel verschieben AWT, Swing, JavaFX & SWT 5
D zwei JLabel stapeln in einem JPanel AWT, Swing, JavaFX & SWT 5
DaCrazyJavaExpert Swing JPanel "ContentPane" wird nicht gesetzt/angezeigt AWT, Swing, JavaFX & SWT 16
DaCrazyJavaExpert Swing Größe des JPanel ändern/wird nicht geändert. AWT, Swing, JavaFX & SWT 3
DaCrazyJavaExpert Swing JPanel wird in JScollPane nicht angezeigt AWT, Swing, JavaFX & SWT 2
it_is_all JPanel verschwindet nach Button-Klick AWT, Swing, JavaFX & SWT 2
B Bar Plot in Swing JPanel AWT, Swing, JavaFX & SWT 0
F Screenshot eines JPanel AWT, Swing, JavaFX & SWT 3
S JPanel rotieren, Bild ist abgeschnitten, Clipping? AWT, Swing, JavaFX & SWT 0
M Swing JPanel flüssig verschieben AWT, Swing, JavaFX & SWT 5
G Nur ein JPanel wird angezeigt AWT, Swing, JavaFX & SWT 9

Ähnliche Java Themen

Neue Themen


Oben