# Java Grafik-Programmierung?



## oOJavaNeulingOo (14. Dez 2012)

Guten Morgen!

Ich wollte hier mal nachfragen, wie schwer es ist in Java 2D-Grafik Programme (Spiele, ..) zu erstellen, und ob es dazu bestimmte Engines gibt, usw, usw.. Bis jetzt habe ich immer nur ein paar sehr kleine Konsolen-Programme und Addons zu bestimmten Spielen programmiert. Daher würde ich sagen, ein klitzkleines bisschen kenne ich die "Grundlagen" (<-- Keine Ahnung wie ich es anders formulieren soll..), doch habe ich keine Ahnung wie ich jetzt mit Grafikprogrammierung anfangen sollte. 

MfG


----------



## TKausL (14. Dez 2012)

Hallo,

wenn du die Grundlagen beherrschst ist die Grafikprogrammierung kein Problem für dich. Anfangen solltest du dann erstmal mit kleinen GUI-Programmen, bevor du wirklich selbst anfängst zu zeichnen.


----------



## oOJavaNeulingOo (14. Dez 2012)

Vielen Dank für die schnelle Antwort!

Die Grundlagen "beherrschen" würde ich es jetzt eher nicht nennen, aber eben so ein kleines bisschen 

Naja, aber wie fange ich denn mit solchen GUI-Programmen an? Welche Library? Was für ein Programm?


----------



## Marco13 (14. Dez 2012)

Es gibt so viele Möglichkeiten, dass es außer einer Aufzählung dieser kaum eine sinnvolle Antwortmöglichkeit gibt. Ohne weitere Details kann man aber sagen, dass es kaum schaden kann, sich mal http://www.java-forum.org/spiele-multimedia-programmierung/54795-quaxli-2d-spiele-tutorial.html anzusehen.


----------



## oOJavaNeulingOo (14. Dez 2012)

Vielen Dank!

Gibt es denn für Java auch so ein Engine wie "Pygame" für Python? Das ist nämlich genial..


----------



## TKausL (14. Dez 2012)

Guck dir mal "Slick" an, das ist eine Java 2D Game-Libary.


----------



## oOJavaNeulingOo (14. Dez 2012)

Vielen Dank! Gibt es dazu denn auch ein deutsches Tutorial?


----------



## 3njoyeD (15. Dez 2012)

Ich versuche mich auch gerade in die Grafikprogrammierung von Java hineinzuarbeiten.
Daher möchte ich keinen neuen Thread aufmachen sondern diesen hier mit nutzen.

Man lehrte uns, die Bibliothek awt - "*Graphics*" einzubziehen.. Sie wird für die 2D - Programmierung genutzt.

Damit kann man Linien, Kreise, Rechtecke, Quadrate usw. zeichnen.
Dazu habe ich auch ein Tutorial gefunden. Leider aber auf Englisch:
Java Programming Tutorial - 84 - Drawing Graphics - YouTube

Wir nutzen gerade den Window Builder. Er dient als Java GUI Designer:
Eclipse Tutorial: GUI-Anwendungen mit WindowBuilder: Der Einstieg - YouTube
Er soll als Hilfe dienen um Fenster schneller aufbauen zu können.

Nun bin ich gerade dabei, einfache Rechtecke in einem JPanel zu zeichnen. 
Es funktioniert auch. Aber, ich diese Rechtecke werden auf der Grundfläche im content Pane gezeichnet. 
_Ich möchte diese Rechtecke aber in einem weiteren JPanel zeichnen lassen. 
Also die Bounds davon als Bezugspunkt nutzen. _Wie bekomme ich das hin? ???:L

Hier mein aktueller Quelltext:


```
package Sinus;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;		// für Grafiken in der GUI
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.JTextField;


public class Sinus extends JFrame {

	
	
	JPanel contentPane = new JPanel();
	private JPanel Sinuspanel;
	private JTextField textField;
	private Graphics g2D;
	
	
	/**
	 * Launch the application.
	 */
	

	
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					
					Sinus frame = new Sinus();
					frame.setVisible(true);
					
					
				} catch (Exception e) {
					
					
					e.printStackTrace();
					
					
				}
			}
		});
	}

	
	
	
	
	/**
	 * Create the frame.
	 */
	
	
	public Sinus() {
		
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 800, 400);
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		JPanel Sinuspanel = new JPanel();
		Sinuspanel.setBounds(50, 50, 450, 207);
		contentPane.add(Sinuspanel);
		Sinuspanel.setLayout(null);
		
		textField = new JTextField();
		textField.setBounds(25, 251, 86, 20);
		contentPane.add(textField);
		textField.setColumns(10);
		contentPane.add(Sinuspanel);
		
		// 900 = Start des Fensters vom linken Bildschirmrand bis zum Beginn der linken Seite des Fensters
		// 400 = Start des Fensters vom oberen Bildschirmrand bis zum Beginn der Kopfseite des Fensters
		// 130 = Die Breite des Fensters
		// 300 = Die Höhe des Fensters
	

		
	}		// Wie kann ich diesen Teil in einem JPanel ( in meinem Fall: "Sinuspanel") integrieren?
	public void paint (Graphics g2D){
		
		g2D.setColor(Color.BLUE);
		g2D.fillRect(25,35,100,30);
		
		}
	}
```


----------



## TKausL (15. Dez 2012)

```
public void paintComponent(Graphics g){
        
        g.setColor(Color.BLUE);
        g.fillRect(25,35,100,30);
        
        }
```


----------



## L-ectron-X (15. Dez 2012)

Die erste Zeile in der paintComponent()-Methode sollte unbedingt der Aufruf der paintComponent()-Methode der Basisklasse sein.

[JAVA=2]super.paintComponent(g);[/code]


----------



## 3njoyeD (15. Dez 2012)

@ TKausL

Okok, da sich die Mehtode in der Basisklasse auch "paintComponent" nennt, sollte man nun auch den Namen weiterhin verwenden. In Ordnung habe ich umgetzt.
Hmm.. der Variablenname selbst kann ja auch andere bezeichnungen als "g" haben. 
Deshalb habe ich nun mal g2D für 2D Grafiken gewählt.


In der ersten Zeile meiner Konfiguration der Methode paintComponent soll den Aufruf der Mehtode in der Baisklasse sein. 
Wenn ich das mit in den Quellcode nehme, wird *NICHTS* mehr gezeichnet.
Egal, wo ich die Startpunkte setze :-/ 
Was geschieht bei diesem Methodenaufruf, das meine Funktion außer Kraft gesetzt wird?


----------



## TKausL (15. Dez 2012)

3njoyeD hat gesagt.:


> Hmm.. der Variablenname selbst kann ja auch andere bezeichnungen als "g" haben.
> Deshalb habe ich nun mal g2D für 2D Grafiken gewählt.



Ist aber Verwirrend da du ein Graphics-Object übergeben bekommst, und kein Graphics2D-Object.
In vielen PaintComponents siehst du dann sowas:


```
public void paintComponent(Graphics g){
  Graphics2D g2d = (Graphics2D) g;
  //Draw blabla
}
```

Das was du danach erklärst verstehe ich leider nicht so ganz


----------



## 3njoyeD (15. Dez 2012)

Ich habe das so mitbekommen, das dieses Objekt g aus der Klasse Graphics wohl nur für 2D Grafiken genutzt wird. Seit dem wir in bei der eigentlichen Programmierung von Java sind mit OOA - OOD und OOP haben sich die Ereignisse recht schnell überschlagen und ich hab wohl etwas den Anschluss verpasst. 

Ich bekomme keinen Fehler angezeigt, aber mein blaues Rechteck wird nicht mehr gezeichnet:

Das Objekt g vom Datentyp Graphics habe ich neben den Elementen der GUI mit instanziert.


```
public Sinus() {
	
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(0,0, 800, 400);
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		JPanel Sinuspanel = new JPanel();
		Sinuspanel.setBounds(50, 50, 450, 207);
		contentPane.add(Sinuspanel);
		Sinuspanel.setLayout(null);
		
		txtTest = new JTextField();
		txtTest.setText("Test");
		txtTest.setBounds(50, 268, 86, 20);
		contentPane.add(txtTest);
		txtTest.setColumns(10);
		contentPane.add(Sinuspanel);

	}			
	public void paintComponent (Graphics g2D){
		super.paintComponents(g2D);
		
		g.setColor(Color.BLUE);
		g.fillRect(20,30,35,50);
			
		}
	}
```

Aber nun wird gar nix mehr angezeigt .. Was mache ich denn falsch?


----------



## Marco13 (15. Dez 2012)

Was auch immer das 'g' da unten ist: Es sollte 'g2d' sein.


----------



## 3njoyeD (16. Dez 2012)

Abend, wollt mich nochmal melden. :meld:
Das was ich erreichen wollte habe ich nun auch geschafft.

Aber, ich würde diese geschaffen Funktion gerne auf einem JPanel aufzeichnen, sodass ich nachher im JFrame auch zwischen den Reitern wechseln kann.. ich hoffe, ihr versteht mein ursprüngliches Problem nun so besser.



Das Objekt "achsenWerte" wird in dieser Klasse erzeugt, der Bauplan befindet sich in der Klasse Sinuskonfiguration.


```
package Sinus;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;		// für Grafiken in der GUI
import java.awt.Image;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.JTextField;

public class Sinus extends JFrame {

	private JPanel contentPane = new JPanel();
	private JTextField textField;
	private Graphics g2D;
	private JPanel Sinuspanel = new JPanel();
	private int height=240;
	private int width=440;
	private Sinuskonfiguration achsenWerte = new Sinuskonfiguration ();
	int pixelX[] = new int [361];
	int pixelY[] = new int [361];
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Sinus frame = new Sinus();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
					}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Sinus() {
		
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		setSize(800, 500);
		setLocationRelativeTo(null);
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		Sinuspanel.setBounds(50, 50, 450, 207);
		contentPane.add(Sinuspanel);
		Sinuspanel.setLayout(null);
		
		textField = new JTextField();
		textField.setBounds(50, 268, 86, 20);
		contentPane.add(textField);
		textField.setColumns(10);
		contentPane.add(Sinuspanel);
	
		for (double winkelalpha = 0; winkelalpha <= 360; winkelalpha += 1){
			
			double sinus,udach,augenblickswert;
			sinus=augenblickswert= 0;
			udach=50;
			int alpha = (int) winkelalpha;
			
				//	=SIN(2*PI()*alpha/360)
				sinus = Math.sin(2 * Math.PI * (winkelalpha/360));
				augenblickswert = sinus * udach;
				pixelX[alpha]= Math.round(Math.round((winkelalpha/360)*width));
				pixelY[alpha]= Math.round(Math.round((augenblickswert/udach)*height/2));
				System.out.println("Sinus von: " + sinus + " bei einem Winkel von " + winkelalpha + "° & einem Augenblickswert von: " + augenblickswert + "V" +
						" ---   X-Achse: " + pixelX[alpha] + " Y-Achse: " + pixelY[alpha]);
				
				achsenWerte.setAchsenwerte(pixelX, pixelY, alpha);
		}
	
}	
	
	public void paint (Graphics g2D){
		super.paintComponents(g2D);
		
		g2D.setColor(Color.BLUE);
		g2D.fillRect(8,31,200,80);
		
		// 8 = Anfangspunkt bezogen auf 8 Pixel von der linken Seite des Fensters bis zur linken Seite des Rechtecks
		// 31  = Anfangspunkt bezogen auf 31 Pixel vom oberen Seitenrand des Fensters bis zur Kopfseite des Rechtecks
		// 200 = Endposition des Rechtecks auf der X-Achse  (Beginn von der linken Seite des Fensters)
		// 80 = Endposition des Rechtecks auf der Y-Achse  (Beginn vom oberen Seitenpunkt des Fensters)
		
		g2D.setColor(Color.BLACK);
		g2D.drawLine(250, 50, 250, 300);
		
				// 250 = Anfangspunkt bezogen auf 250 Pixel von der linken Seite des Fensters bis zur linken Seite der Linie
				// 50  = Anfangspunkte bezogen auf 50 Pixel vom oberen Seitenrand des Fensters bis zum oberen Anfangspunkt der Linie
				// 250 = Endposition der Linie auf der X-Achse  (Beginn von der linken Seite des Fensters)
				// 300 = Endposition der Linie auf der Y-Achse  (Beginn vom oberen Seitenpunkt des Fensters)
		
		g2D.drawLine(250, 175, 700, 175);

			// Nur als Beispiel:
			
			g2D.setColor(Color.BLACK);
			g2D.fillRect(450, 175, 1, 1);
			g2D.fillRect(650, 175, 1, 1);
			
//			g2D.drawLine(450, 175, 1, 1);

			// 450 = Anfangspunkt bezogen auf 450 Pixel von der linken Seite des Fensters bis zur linken Seite der Linie
			// 175  = Anfangspunkte bezogen auf 175 Pixel vom oberen Seitenrand des Fensters bis zum oberen Anfangspunkt der Linie
			// 1 = Breite des Quadrats auf der X-Achse  (Beginn vom Anfangspunkt X-Achse)
			// 1 = Höhe des Quadrats auf der Y-Achse  (Beginn vom Anfangspunkt Y-Achse)
	
			for (int alpha = 0; alpha <= 360; alpha += 1){
				int pixelX = achsenWerte.getpixelX(alpha);
				int pixelY = achsenWerte.getpixelY(alpha);
				System.out.println("Winkel: " + alpha + "° --- X-Achse: " + pixelX + " --- Y-Achse: " + pixelY);
				g2D.fillRect(pixelX + 250, 175 - pixelY, 1, 1);
			}
		
		}
	
	}
```

Klasse Sinuskonfiguration im selben Package (Sinus)

```
package Sinus;
public class Sinuskonfiguration {

	private int pixelX [] = new int [361];
	private int pixelY [] = new int [361];
	
	Sinuskonfiguration () {	}

	public void setAchsenwerte (int pixelX[], int pixelY[], int alpha){
		this.pixelX[alpha]=pixelX[alpha];
		this.pixelY[alpha]=pixelY[alpha];
		}
		
	public int getpixelX (int alpha){
		return pixelX[alpha];
	}	
	
	public int getpixelY (int alpha){
		return pixelY[alpha];
	}
	
}
```







Mühsam ernährt sich das Eichhörnchen 
Das Schöne daran ist, das ich nun mit einem Lächeln nächtigen gehe.
Vielen Dank an euch!


----------



## Michael... (16. Dez 2012)

Bei so etwas kann es an verschiedenen Stellen Probleme geben. Wenn man selbst zeichnet, muss man auf mehrer Dinge achten. z.B. nutzt man einen LayoutManager und orientiert sich dieser an der PreferredSize der Kompnonente. Wenn man selbst zeichnet muss man sich auch selbst darum kümmern, dass die korrekte PreferredSize der Komponente richtig gesetzt ist.
Wenn man die Komponente in den CENTER Bereich eines BorderLayouts setzt (s.u.), spielt das alles keine Rolle.

Aber grundsätzlich gilt in 99,9% der Fälle:
- man erbt von JPanel oder JComponent und überschreibt deren paintComponent(Graphic)
- und ruft darin als erstes deren super.paintComponent(Graphic) auf

```
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(0, 0, 500, 200);
frame.setLocationRelativeTo(null);

frame.add(new JPanel() {
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		int yM = this.getHeight()/2;
		g.drawLine(0, yM, this.getWidth(), yM);
		for (int x = 0; x < this.getWidth(); x++) {
			double sin = Math.sin(Math.toRadians(x)) * (yM-20);
			g.drawLine(x, yM -(int)sin, x, yM -(int)sin);
		}
	}
});
```


----------



## Marco13 (16. Dez 2012)

Vielleicht ist http://www.java-forum.org/codeschnipsel-u-projekte/122994-einfacher-funktionsplotter.html auch ganz interessant. Sowas wie
 private int pixelX [] = new int [361];
sieht zumindest sehr fragwürdig (um nicht zu sagen: "falsch") aus... Willst du die Plots als Bilder speichern...?


----------

