Version 1.0.0 (2024-12-29): Material ZPG (2019)

This commit is contained in:
Thomas Schaller 2024-12-29 14:06:34 +01:00
parent 7835d8e99a
commit 67d0889188
825 changed files with 391265 additions and 3 deletions

View file

@ -0,0 +1,14 @@
//Überlege dir, was die Anweisungen in der Methode "waszeichneich" auslösen könnten
// Verändere die Werte, die den Methoden übergeben werden. Was passiert?
void waszeichneich() {
line(100, 50, 200, 100);
ellipse(100, 200, 50, 100);
rect(300, 100, 250, 20);
}
void setup() {
size(600, 400);
waszeichneich(); // Aufruf der Methode
}

View file

@ -0,0 +1,28 @@
void zeichneBildC() {
// Zeichne dir zunächst eine Skizze auf ein Blatt Papier und überlege dir, welche
// Werte du den Methoden rect(x,y,b,h) und ellipse(x,y,b,h) übergeben musst,
// dass Bild C gezeichnet wird
// ***** hier kommen deine Anweisungen hin ************
// ***** Ende der eigenen Anweisungen **********
}
//***** Zusatzaufgabe bzw. Hausaufgabe *************
void zeichneBildA() {
// ***** hier kommen deine Anweisungen hin ************
// ***** Ende der eigenen Anweisungen **********
}
void setup() {
size(500, 350); // Festlegen der Fenstergröße
zeichneBildC(); // Aufruf deiner Methode
// zeichneBildA();
}

View file

@ -0,0 +1,15 @@
void zeichneBildC() {
// ***** hier kommen deine Anweisungen hin ************
// ***** Ende der eigenen Anweisungen **********
}
void setup() {
size(500, 350); // Festlegen der Fenstergröße
zeichneBildC(); // Aufruf deiner Methode
}

View file

@ -0,0 +1,48 @@
// Programm zur Darstellung eines Arrays als Balkendiagramm
// Autor: Thomas Schaller
// Version: 1.0 vom 12.02.2019
// Liste mit allen Werten //<>//
int[] zahlen={45, 23, 123, 87, 98, 2, 1, 23, 23, 34};
// Schriften
PFont kleineSchrift;
PFont grosseSchrift;
public void setup() {
size(1000, 700);
background(0);
kleineSchrift = loadFont("KleineSchrift.vlw");
grosseSchrift = loadFont("GrosseSchrift.vlw");
zeichneBalken();
}
public void zeichneBalken() {
clear();
// Überschrift
fill(255,255,255);
textFont(grosseSchrift);
text("Balkendiagramm", 2, 20);
textFont(kleineSchrift);
// ----------------------------------------------------------------------
// To Do
// ----------------------------------------------------------------------
// Version 1:
// Implementiere die ersten vier Balken durch Angabe der Koordinaten aus der Tabelle.
// Ergänze dazu die Methode zeicheBalken an der "ToDo"-Stelle.
// Version 2:
// Ersetze die y-Koordinate und die Breite durch die oben ermittelte Formel.
// Deklariere vorher eine Integer-Variable i. Setze i vor der ersten Rechteck
// auf 0, vor dem zweite auf 1 usw. Überprüfe, ob deine Rechtecke immer noch
// korrekt gezeichnet werden.
// Version 3:
// Verwende eine for-Schleife, um alle Balken zeichnen zu lassen. Diese muss das i
// in jedem Durchgang um 1 erhöhen. Die Anzahl der Elemente im Array bekommst du
// durch zahlen.length.
// Tipp: Vergleiche mit deiner Implementation von der Kaffeehaus-Täuschung.
}

View file

@ -0,0 +1,64 @@
/**
* Balkendiagramm für int-Array, Zahlen werden zufällig erzeugt.
*
* @author Schaller
* @version 29.11.18
*/
// Liste mit allen Werten //<>//
int[] zahlen;
// Schriften
PFont kleineSchrift;
PFont grosseSchrift;
public void setup() {
// Zeichenfläche erzeugen
size(1000, 700);
background(0);
// Schriften laden
kleineSchrift = loadFont("KleineSchrift.vlw");
grosseSchrift = loadFont("GrosseSchrift.vlw");
// Zufallszahlen erzeugen und anzeigen
erzeugeZufallsarray(20);
zeichneBalken();
}
public int getZufallszahl(int min, int max) {
java.util.Random r = new java.util.Random();
return r.nextInt(max-min+1)+min;
}
public void erzeugeZufallsarray(int laenge) {
// ToDo: Neues Array der richtigen Länge erzeugen
// ToDo: Jedes Element mit einer Zufallszahl belegen
}
public void zeichneBalken() {
clear();
// Überschrift
fill(255,255,255);
textFont(grosseSchrift);
text("Balkendiagramm", 2, 20);
textFont(kleineSchrift);
// Alle Einträge darstellen
for (int i = 0; i< zahlen.length; i++) {
fill(20,30,170);
// Balkendiagramm zeichnen
rect(120, 25+i*15, zahlen[i]+1, 13);
// Beschriftung
fill(255,255,255);
text("i="+i, 2, 35+i*15);
text("zahlen["+i+"]="+zahlen[i], 30, 35+i*15);
}
}

View file

@ -0,0 +1,75 @@
/**
* Balkendiagramm für int-Array, Zahlen werden aus CSV-Datei gelesen.
*
* @author Schaller
* @version 29.11.18
*/
// Liste mit allen Werten
// Deklariere ein Array zahlen für die Punkte und ein Array namen für die Spielernamen
//------------
// TODO
//------------
// Schriften
PFont kleineSchrift;
PFont grosseSchrift;
public void setup() {
// Zeichenfläche erzeugen
size(1000, 700);
background(0);
// Schriften laden
kleineSchrift = loadFont("KleineSchrift.vlw");
grosseSchrift = loadFont("GrosseSchrift.vlw");
// CSV-Datei laden und anzeigen
ladeTabelle("punkte.csv");
zeichneBalken();
}
public void ladeTabelle(String name) {
// Tabelle aus CSV-Datei laden
Table csv = loadTable(name,"header,csv");
// Initialisiere Arrays, in die alle Zeilen der Tabelle passen
// Die Anzahl der gespeicherten Zeilen bekommt man mit csv.getRowCount()
//------------
// TODO
//------------
// Fülle die Arrays mit Werten aus der Tabelle
// Mit csv.getInt(zeilennummer, "Name der Spalte") oder csv.getInt(zeilennummer, spaltennummer)
// bekommt man die Werte der Tabelleneinträge als Integer-Wert
// Informiere dich unter https://processing.org/reference/Table.html, welche Methode geeignet ist,
// um die Namen der Spieler als String zu bekommen. getInt hilft hier nicht weiter.
//------------
// TODO
//------------
}
public void zeichneBalken() {
clear();
// Überschrift
fill(255,255,255);
textFont(grosseSchrift);
text("Punkte", 2, 20);
textFont(kleineSchrift);
// Alle Einträge darstellen
// lasse alle Ergebnisse der Spieler in der Form
// SpielerXY 234 XXXXXXXXXXXXXXXX
// SpielerZY 12 XX
// usw.
// darstellen. Wandle dazu dein Programm, um die Werte eines Arrays darzustelle ab.
//------------
// TODO
//------------
}

View file

@ -0,0 +1,6 @@
"Name","Punkte"
Niko,216
Klaus,591
Anna,857
Lena,180
Winfried,168
1 Name Punkte
2 Niko 216
3 Klaus 591
4 Anna 857
5 Lena 180
6 Winfried 168

View file

@ -0,0 +1,156 @@
/**
* Balkendiagramm für int-Array, Zahlen werden aus CSV-Datei gelesen, Maximum der Werte wird bestimmt.
* Hinweis zur Benutzung:
* Klicke in das Zeichenfenster
* Animierte Suche mit Taste "a"
* Automatisches Testen mit Taste "t"*
* @author Schaller
* @version 29.11.18
*/
// Liste mit allen Werten //<>//
int[] zahlen;
String[] namen;
// Hilfsvariablen für die Suche
// -------------------------------------------------------------------
// ToDo: Hilfsvariablen erzeugen für aktuell größtes und aktuell
// untersuchtes Element
// -------------------------------------------------------------------
// aktuell groesstes Element
// aktuell untersuchtes Element
int verzoegerung=1000; // Geschwindigkeit der Ausführung
// Schriften
PFont kleineSchrift;
PFont grosseSchrift;
public void setup() {
// Zeichenfläche erzeugen
size(1000, 700);
background(0);
// Schriften laden
kleineSchrift = loadFont("KleineSchrift.vlw");
grosseSchrift = loadFont("GrosseSchrift.vlw");
// CSV-Datei laden und anzeigen
ladeTabelle("punkte.csv");
zeichneBalken();
}
public void draw() {
zeichneBalken();
}
public void keyPressed() {
// Animierte Suche mit Taste "a"
if (key=='a') {
thread("maximumsuche");
}
// Automatisches Testen mit Taste "t"
if(key == 't') {
// Testfall 1
verzoegerung = 0;
ladeTabelle("testfall1.csv");
int m1 = maximumsuche();
if (m1 == 12) {
System.out.println("Maximum korrekt gefunden. In Datei testfall1.csv ist der größte Wert "+ zahlen[m1]+" von "+namen[m1]+" an Position "+m1);
} else {
System.out.println("Maximum in testfall.csv nicht gefunden. Du ermittelst "+m1+" richtig wäre 12");
}
// Testfall 2: negative Zahlen
ladeTabelle("testfall2.csv");
int m2 = maximumsuche();
if (m2 == 3) {
System.out.println("Maximum korrekt gefunden. In Datei testfall2.csv ist der größte Wert "+ zahlen[m2]+" von "+namen[m2]+" an Position "+m2);
} else {
System.out.println("Maximum in testfall2.csv nicht gefunden. Du ermittelst "+m2+" richtig wäre 3");
}
// Testfall 3: Nur 1 Element
ladeTabelle("testfall3.csv");
int m3 = maximumsuche();
if (m3 == 0) {
System.out.println("Maximum korrekt gefunden. In Datei testfall3.csv ist der größte Wert "+ zahlen[m3]+" von "+namen[m3]+" an Position "+m3);
} else {
System.out.println("Maximum in testfall3.csv nicht gefunden. Du ermittelst "+m3+" richtig wäre 0");
}
// Testfall 4: Leere Liste
ladeTabelle("testfall4.csv");
int m4 = maximumsuche();
if (m4 == -1) {
System.out.println("Maximum korrekt gefunden. Da die Datei keine Spieler enthält wird -1 zurückgegeben.");
} else {
System.out.println("Maximum in testfall4.csv nicht gefunden. Du ermittelst "+m4+" richtig wäre -1, da die Datei leer ist.");
}
}
}
public void ladeTabelle(String name) {
// Tabelle aus CSV-Datei laden
Table csv = loadTable(name, "header,csv");
if (csv != null && csv.getColumnCount()==2) {
// Initialisiere Arrays, in die alle Zeilen der Tabelle passen
zahlen = new int[csv.getRowCount()];
namen = new String[csv.getRowCount()];
// Fülle die Arrays mit Werten aus der Tabelle
for (int i = 0; i < zahlen.length; i++) {
// Lies Wert aus der i. Zeile und der Spalte "Punkte" bzw. "Name"
zahlen[i] = csv.getInt(i, "Punkte");
namen[i] = csv.getString(i, "Name");
}
}
}
public void zeichneBalken() {
clear();
// Überschrift
fill(255,255,255);
textFont(grosseSchrift);
text("Punkte", 2, 20);
textFont(kleineSchrift);
// Alle Einträge darstellen
if (zahlen != null) {
for (int i = 0; i< zahlen.length; i++) {
fill(20,25,165);
// aktuelle Elemente farblich hervorheben
// ----------------------------------------------------------------------
// ToDo: Falls i dem aktuell untersuchtem oder der aktuellen Maximal-
// position entspricht, muss eine andere Farbe gewählt werden
// ----------------------------------------------------------------------
// Balkendiagramm zeichnen
if (zahlen[i]>=0) rect(120, 25+i*15, zahlen[i]+1, 13);
// Beschriftung
fill(255,255,255);
text(namen[i], 2, 35+i*15);
text(""+zahlen[i], 70, 35+i*15);
}
}
}
public int maximumsuche() {
// ------------------------------------------------------------------------------
// ToDO: Implementiere die Maximumsuche, füge nach jeder Veränderung der
// Position des aktuellen Elements oder der Position des momentanen Maximums
// die Befehle: redraw(); und delay(verzoegerung); ein.
// Als Ergebnis soll die Methode die Position des Maximums zurückgeben
// Kommentiere die Maximumsuche
// ------------------------------------------------------------------------------
//<>//
return -1;
}

View file

@ -0,0 +1,6 @@
"Name","Punkte"
Niko,216
Klaus,591
Anna,857
Lena,180
Winfried,168
1 Name Punkte
2 Niko 216
3 Klaus 591
4 Anna 857
5 Lena 180
6 Winfried 168

View file

@ -0,0 +1,20 @@
"Name","Punkte"
Spieler1,0
Spieler1,6
Spieler2,19
Spieler6,1
Spieler4,45
Spieler3,23
Spieler3,12
Spieler2,44
Spieler1,72
Spieler5,12
Spieler6,4
Spieler7,2
Spieler4,98
Spieler3,21
Spieler3,12
Spieler2,32
Spieler1,12
Spieler5,44
Spieler3,12
1 Name Punkte
2 Spieler1 0
3 Spieler1 6
4 Spieler2 19
5 Spieler6 1
6 Spieler4 45
7 Spieler3 23
8 Spieler3 12
9 Spieler2 44
10 Spieler1 72
11 Spieler5 12
12 Spieler6 4
13 Spieler7 2
14 Spieler4 98
15 Spieler3 21
16 Spieler3 12
17 Spieler2 32
18 Spieler1 12
19 Spieler5 44
20 Spieler3 12

View file

@ -0,0 +1,20 @@
"Name","Punkte"
Spieler1,-5
Spieler1,-6
Spieler2,-19
Spieler6,-1
Spieler4,-45
Spieler3,-23
Spieler3,-12
Spieler2,-44
Spieler1,-72
Spieler5,-12
Spieler6,-4
Spieler7,-2
Spieler4,-98
Spieler3,-21
Spieler3,-12
Spieler2,-32
Spieler1,-12
Spieler5,-44
Spieler3,-12
1 Name Punkte
2 Spieler1 -5
3 Spieler1 -6
4 Spieler2 -19
5 Spieler6 -1
6 Spieler4 -45
7 Spieler3 -23
8 Spieler3 -12
9 Spieler2 -44
10 Spieler1 -72
11 Spieler5 -12
12 Spieler6 -4
13 Spieler7 -2
14 Spieler4 -98
15 Spieler3 -21
16 Spieler3 -12
17 Spieler2 -32
18 Spieler1 -12
19 Spieler5 -44
20 Spieler3 -12

View file

@ -0,0 +1,2 @@
"Name","Punkte"
Spieler1,45
1 Name Punkte
2 Spieler1 45

View file

@ -0,0 +1 @@
"Name","Punkte"
1 Name Punkte

View file

@ -0,0 +1,97 @@
/**
* Automatische Zeitungsmeldung mit Maximum und Durchschnitt, Zahlen werden aus CSV-Datei gelesen.
*
* @author Schaller
* @version 29.11.18
*/
// Liste mit allen Werten
int[] punkte;
String[] namen;
// Schriften
PFont kleineSchrift;
PFont grosseSchrift;
public void setup() {
// Zeichenfläche erzeugen
size(1000, 700);
background(0);
// Schriften laden
kleineSchrift = loadFont("KleineSchrift.vlw");
grosseSchrift = loadFont("GrosseSchrift.vlw");
// CSV-Datei laden und anzeigen
ladeTabelle("punkte.csv");
int summe = berechneSumme(punkte);
System.out.println("Summe: "+summe);
schreibeZeitungsmeldung();
}
public void ladeTabelle(String name) { //<>//
// Tabelle aus CSV-Datei laden //<>//
Table csv = loadTable(name, "header,csv");
if (csv != null && csv.getColumnCount()==2) {
// Initialisiere Arrays, in die alle Zeilen der Tabelle passen
punkte = new int[csv.getRowCount()];
namen = new String[csv.getRowCount()];
// Fülle die Arrays mit Werten aus der Tabelle
for (int i = 0; i < punkte.length; i++) {
// Lies Wert aus der i. Zeile und der Spalte "Punkte" bzw. "Name"
punkte[i] = csv.getInt(i, "Punkte");
namen[i] = csv.getString(i, "Name");
}
}
}
public void schreibeZeitungsmeldung() {
clear();
// Überschrift
fill(225,225,255);
stroke(155,155,255);
textFont(grosseSchrift);
text("BREAKING NEWS",5,32);
strokeWeight(3);
line(2,4,400,4);
line(2,45,400,45);
strokeWeight(2);
line(2,7,400,7);
line(2,42,400,42);
strokeWeight(1);
textFont(kleineSchrift);
fill(240);
int anzahlSpieler = 0;
int anzahlSpiele = 0;
int summe = berechneSumme(punkte);
double durchschnitt = 0;
text("Großartiges Ergebnis - Klasse XY nimmt an Binärwettbewerb teil.", 2, 60);
text("Die Klasse XY hat beim diesjährigen Binärwettbewerb teilgenommen", 2, 82);
text("und ein großartiges Ergebnis erzielt. Die XX Schülerinnen und", 2, 94);
text("Schüler der Klasse erreichten in "+anzahlSpiele+" Spielen eine Gesamtpunktzahl",2,106);
text("von "+summe+". Das ist ein Durchschnitt von XX.X pro Spiel.",2,118);
}
public int berechneSumme(int[] zahlen) {
int summe;
int i;
// Startwerte setzen //<>//
summe = 0;
// Alle Arrayelemente untersuchen
for (i=0; i< zahlen.length; i++) {
summe = summe + i;
}
// Gib die Summe zurück
return i;
}

View file

@ -0,0 +1,6 @@
"Name","Punkte"
Niko,216
Klaus,591
Anna,857
Lena,180
Winfried,168
1 Name Punkte
2 Niko 216
3 Klaus 591
4 Anna 857
5 Lena 180
6 Winfried 168

View file

@ -0,0 +1,20 @@
"Name","Punkte"
Spieler1,0
Spieler1,6
Spieler2,19
Spieler6,1
Spieler4,45
Spieler3,23
Spieler3,12
Spieler2,44
Spieler1,72
Spieler5,12
Spieler6,4
Spieler7,2
Spieler4,98
Spieler3,21
Spieler3,12
Spieler2,32
Spieler1,12
Spieler5,44
Spieler3,12
1 Name Punkte
2 Spieler1 0
3 Spieler1 6
4 Spieler2 19
5 Spieler6 1
6 Spieler4 45
7 Spieler3 23
8 Spieler3 12
9 Spieler2 44
10 Spieler1 72
11 Spieler5 12
12 Spieler6 4
13 Spieler7 2
14 Spieler4 98
15 Spieler3 21
16 Spieler3 12
17 Spieler2 32
18 Spieler1 12
19 Spieler5 44
20 Spieler3 12

View file

@ -0,0 +1,20 @@
"Name","Punkte"
Spieler1,-5
Spieler1,-6
Spieler2,-19
Spieler6,-1
Spieler4,-45
Spieler3,-23
Spieler3,-12
Spieler2,-44
Spieler1,-72
Spieler5,-12
Spieler6,-4
Spieler7,-2
Spieler4,-98
Spieler3,-21
Spieler3,-12
Spieler2,-32
Spieler1,-12
Spieler5,-44
Spieler3,-12
1 Name Punkte
2 Spieler1 -5
3 Spieler1 -6
4 Spieler2 -19
5 Spieler6 -1
6 Spieler4 -45
7 Spieler3 -23
8 Spieler3 -12
9 Spieler2 -44
10 Spieler1 -72
11 Spieler5 -12
12 Spieler6 -4
13 Spieler7 -2
14 Spieler4 -98
15 Spieler3 -21
16 Spieler3 -12
17 Spieler2 -32
18 Spieler1 -12
19 Spieler5 -44
20 Spieler3 -12

View file

@ -0,0 +1,2 @@
"Name","Punkte"
Spieler1,45
1 Name Punkte
2 Spieler1 45

View file

@ -0,0 +1 @@
"Name","Punkte"
1 Name Punkte

View file

@ -0,0 +1,132 @@
/**
* Balkendiagramm für int-Array, Zahlen werden aus CSV-Datei gelesen, Umwandlung in sortierte Tabelle.
* Hinweis zur Benutzung:
* Klicke in das Zeichenfenster
* Start des Algorithmus "wastutes" mit Taste "a"
* @author Schaller
* @version 29.11.18
*/
// Liste mit allen Werten //<>//
int[] zahlen;
String[] namen;
// Hilfsvariablen für die Suche
int akt_maximum=-1; // aktuell groesstes Element
int akt=-2; // aktuell untersuchtes Element
int verzoegerung=1000; // Geschwindigkeit der Ausführung
// Schriften
PFont kleineSchrift;
PFont grosseSchrift;
public void setup() {
// Zeichenfläche erzeugen
size(1000, 700);
background(0);
// Schriften laden
kleineSchrift = loadFont("KleineSchrift.vlw");
grosseSchrift = loadFont("GrosseSchrift.vlw");
// CSV-Datei laden und anzeigen
ladeTabelle("punkte.csv");
zeichneBalken();
}
public void draw() {
zeichneBalken();
}
public void keyPressed() {
// Animierte Suche mit Taste "a"
if (key=='a') {
thread("wastutes");
}
}
public void ladeTabelle(String name) {
// Tabelle aus CSV-Datei laden
Table csv = loadTable(name, "header,csv");
if (csv != null && csv.getColumnCount()==2) {
// Initialisiere Arrays, in die alle Zeilen der Tabelle passen
zahlen = new int[csv.getRowCount()];
namen = new String[csv.getRowCount()];
// Fülle die Arrays mit Werten aus der Tabelle
for (int i = 0; i < zahlen.length; i++) {
// Lies Wert aus der i. Zeile und der Spalte "Punkte" bzw. "Name"
zahlen[i] = csv.getInt(i, "Punkte");
namen[i] = csv.getString(i, "Name");
}
}
}
public void zeichneBalken() {
clear();
// Überschrift
fill(255, 255, 255);
textFont(grosseSchrift);
text("Punkte", 2, 20);
textFont(kleineSchrift);
// Alle Einträge darstellen
if (zahlen != null) {
for (int i = 0; i< zahlen.length; i++) {
fill(20, 25, 165);
// aktuelle Elemente farblich hervorheben
if (i == akt || i == akt+1 ) {
fill(140, 230, 20);
}
// Balkendiagramm zeichnen
if (zahlen[i]>=0) rect(120, 25+i*15, zahlen[i]+1, 13);
// Beschriftung
fill(255, 255, 255);
text(namen[i], 2, 35+i*15);
text(zahlen[i], 70, 35+i*15);
}
}
}
public void wastutes() {
// Sind überhaupt Daten da?
if (zahlen.length==0 ) {
return;
}
//
for (akt=0; akt+1 < zahlen.length; akt++) {
//
redraw();
delay(verzoegerung);
//
if (zahlen[akt+1]> zahlen[akt]) {
//
int dummy = zahlen[akt];
zahlen[akt] = zahlen[akt+1];
zahlen[akt+1] = dummy;
//
redraw();
delay(verzoegerung);
}
}
//
akt = -2;
redraw();
delay(verzoegerung);
}

View file

@ -0,0 +1,6 @@
"Name","Punkte"
Niko,216
Klaus,591
Anna,857
Lena,180
Winfried,168
1 Name Punkte
2 Niko 216
3 Klaus 591
4 Anna 857
5 Lena 180
6 Winfried 168

View file

@ -0,0 +1,20 @@
"Name","Punkte"
Spieler1,0
Spieler1,6
Spieler2,19
Spieler6,1
Spieler4,45
Spieler3,23
Spieler3,12
Spieler2,44
Spieler1,72
Spieler5,12
Spieler6,4
Spieler7,2
Spieler4,98
Spieler3,21
Spieler3,12
Spieler2,32
Spieler1,12
Spieler5,44
Spieler3,12
1 Name Punkte
2 Spieler1 0
3 Spieler1 6
4 Spieler2 19
5 Spieler6 1
6 Spieler4 45
7 Spieler3 23
8 Spieler3 12
9 Spieler2 44
10 Spieler1 72
11 Spieler5 12
12 Spieler6 4
13 Spieler7 2
14 Spieler4 98
15 Spieler3 21
16 Spieler3 12
17 Spieler2 32
18 Spieler1 12
19 Spieler5 44
20 Spieler3 12

View file

@ -0,0 +1,20 @@
"Name","Punkte"
Spieler1,-5
Spieler1,-6
Spieler2,-19
Spieler6,-1
Spieler4,-45
Spieler3,-23
Spieler3,-12
Spieler2,-44
Spieler1,-72
Spieler5,-12
Spieler6,-4
Spieler7,-2
Spieler4,-98
Spieler3,-21
Spieler3,-12
Spieler2,-32
Spieler1,-12
Spieler5,-44
Spieler3,-12
1 Name Punkte
2 Spieler1 -5
3 Spieler1 -6
4 Spieler2 -19
5 Spieler6 -1
6 Spieler4 -45
7 Spieler3 -23
8 Spieler3 -12
9 Spieler2 -44
10 Spieler1 -72
11 Spieler5 -12
12 Spieler6 -4
13 Spieler7 -2
14 Spieler4 -98
15 Spieler3 -21
16 Spieler3 -12
17 Spieler2 -32
18 Spieler1 -12
19 Spieler5 -44
20 Spieler3 -12

View file

@ -0,0 +1,2 @@
"Name","Punkte"
Spieler1,45
1 Name Punkte
2 Spieler1 45

View file

@ -0,0 +1 @@
"Name","Punkte"
1 Name Punkte

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,114 @@
/**
* XY-Diagramm für Schalldruckpegel, Zahlen werden aus CSV-Datei gelesen.
*
* @author Schaller
* @version 29.11.18
*/
// Liste mit allen Werten
int[] punkte;
String[] namen;
// Hilfsvariablen für die Suche
int akt_maximum=-1; // aktuell groesstes Element
int akt=-1; // aktuell untersuchtes Element
int verzoegerung=0; // Geschwindigkeit der Ausführung
// Schriften
PFont kleineSchrift;
PFont grosseSchrift;
public void setup() {
// Zeichenfläche erzeugen
size(1000, 700);
background(0);
// Schriften laden
kleineSchrift = loadFont("KleineSchrift.vlw");
grosseSchrift = loadFont("GrosseSchrift.vlw");
// CSV-Datei laden und anzeigen
ladeTabelle("punkte.csv");
stroke(250,250,200);
zeichneBalken();
}
//<>//
public void ladeTabelle(String name) {
// Tabelle aus CSV-Datei laden //<>//
Table csv = loadTable(name, "header,csv");
if (csv != null && csv.getColumnCount()==2) {
// Initialisiere Arrays, in die alle Zeilen der Tabelle passen
punkte = new int[csv.getRowCount()];
namen = new String[csv.getRowCount()];
// Fülle die Arrays mit Werten aus der Tabelle
for (int i = 0; i < punkte.length; i++) {
// Lies Wert aus der i. Zeile und der Spalte "Punkte" bzw. "Name"
punkte[i] = csv.getInt(i, "Punkte");
namen[i] = csv.getString(i, "Name");
}
}
}
public void zeichneBalken() {
// Überschrift
fill(255,255,255);
textFont(grosseSchrift);
text("Punkte", 2, 20);
textFont(kleineSchrift);
// Alle Einträge darstellen
if (punkte != null) {
for (int i = 0; i< punkte.length; i++) {
fill(20,25,165);
// aktuelle Elemente farblich hervorheben
if (i == akt) {
fill(140,230,20);
}
if (i == akt_maximum) {
fill(230,60,140);
}
// Balkendiagramm zeichnen
if (punkte[i]>=0) rect(120, 25+i*15, punkte[i]+1, 13);
// Beschriftung
fill(255,255,255);
text(namen[i], 2, 35+i*15);
text(punkte[i], 70, 35+i*15);
}
}
}
public int sucheMaximum(int[] zahlen) {
// Sind überhaupt Daten da?
if (zahlen.length==0 ) {
return -1;
}
// Startwerte setzen
akt_maximum = 0;
akt = 1;
// Alle Arrayelemente untersuchen
while (akt < zahlen.length) {
// Neues größtes Element??
if (zahlen[akt]> zahlen[akt_maximum]) {
// Dann merke dir das neue
akt_maximum = akt;
}
akt = akt + 1;
}
// Gib Position des größten Elements zurück
return akt_maximum;
} //<>//

View file

@ -0,0 +1,6 @@
"Name","Punkte"
Niko,216
Klaus,591
Anna,857
Lena,180
Winfried,168
1 Name Punkte
2 Niko 216
3 Klaus 591
4 Anna 857
5 Lena 180
6 Winfried 168

View file

@ -0,0 +1,36 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
/**
* Ergänzen Sie hier eine Beschreibung für die Klasse MyWorld.
*
* @author (Ihr Name)
* @version (eine Versionsnummer oder ein Datum)
*/
public class MyWorld extends World
{
/**
* Konstruktor für Objekte der Klasse MyWorld
*
*/
public MyWorld()
{
// Erstellt eine neue Welt mit 1200x900 Pixeln
super(1000, 700, 1);
prepare();
}
/**
* Bereite die Welt für den Programmstart vor.
* Das heißt: Erzeuge die Anfangs-Objekte und füge sie der Welt hinzu.
*/
private void prepare()
{
Zeichnung zeichnung = new Zeichnung();
addObject(zeichnung,500,350);
}
}

View file

@ -0,0 +1,677 @@
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.util.Vector;
import javax.imageio.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
import java.awt.geom.AffineTransform;
/**
*
* Bildklasse für die Simulation von Processing-Befehlen
*
* Diese Klasse stellt ein BufferedImage bereit, in das mit Processing-Befehlen gezeichnet
* werden kann.
* Zusätzlich kann ein Bildanzeiger über jede Änderung des Bildes informiert werden,
* um "Zurück"-Befehle zu ermöglichen. Der Bildanzeiger ist entweder eine normale Java
* ScrollPane oder ein Actor aus Greenfoot.
* Die Dokumentation der einzelnen Zeichenmethoden ist der Processing-Reference
* (https://processing.org/reference/ steht unter CC-Lizenz: https://creativecommons.org/)
* entnommen und mit Deepl.com ins Deutsche übersetzt.
*
* @version 1.0 from 23.01.2019
* @author Thomas Schaller (ZPG Informatik Klasse 9)
*/
public class Picture{
// Einstellungmöglichkeiten für das Zeichnen von Rechtecken und Ellipsen
// RADIUS = Mittelpunkt+Radius wird gegeben, CENTER = Mittelpunkt und Breite/Höhe wird gegeben,
// CORNER = Linke obere Ecke + Breite/Höhe, CORNERS = Linke obere und rechte untere Ecke
public static final int RADIUS = 1;
public static final int CENTER = 2;
public static final int CORNER = 3;
public static final int CORNERS = 4;
// gespeichertes Bild,
private BufferedImage image;
// aktuelle Farbeinstellungen
private Color background;
private Color pencolor;
private Color fillcolor;
// aktuelle Stiftdicke
private double stroke;
// akkteller Koordinatenmodus von Rechtecken und Ellipsen
private int ellipseMode = CENTER;
private int rectMode = CORNER;
// aktueller Font
private Font textfont = null;
// muss ein Bildanzeiger benachrichtigt werden
private PictureViewer observer = null;
/**
* Erzeugt ein Bild mit Standardgröße 500x400
*/
public Picture() {
this(500,400);
}
/**
* Erzeugt ein Bild der angegeben Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public Picture(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein Bild aus einer Datei
* @param filename Dateiname des Bildes
*/
public Picture(String filename) {
load(filename);
}
/**
* Erzeugt ein Bild der angegebenen Größe mit festgelegtem Hintergrund
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds
*/
public Picture(int width, int height, String background) {
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
this.background = decode(background);
this.pencolor = new Color(0,0,0);
this.stroke = 1;
this.fillcolor = null;
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(this.background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Legt fest, wer das Bild anzeigt.
* Diese ermöglicht die Benachrichtung des Observers, wenn sich das Bild ändert.
* @param observer Anzeiger des Bildes
*/
public void setObserver(PictureViewer observer) {
this.observer= observer;
}
/**
* Direktes Setzen des Bildes (für interne Zwecke)
* @param b Bild, das gespeichert werden soll.
*/
public void setImage(BufferedImage b) {
image = b;
}
/**
* Direktes Abfragen des Bildes (für interne Zwecke)
* @return Bild, das gerade gespeichert ist.
*/
public BufferedImage getImage() {
return image;
}
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
pushImage();
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getWidth() {
return image.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getHeight() {
return image.getHeight();
}
/**
* Erzeugt eine Kopie des Bildes und übergibt sie an den Observer (falls existent), damit dieser die Versionen speichern kann
*/
private void pushImage() {
if(observer != null) {
observer.pushImage();
}
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
private void repaint() {
if(observer != null) {
observer.repaint();
}
}
// ----------------------------------------- Zeichenfunktionen -----------------------------------------------
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
pushImage();
image = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,image.getWidth()-1, image.getHeight()-1);
repaint();
}
/**
* Konvertiert die in einem bestimmten Modus gegebenen Koordinaten in die Java-übliche Links_Oben_Breite_Höhe Version
* Die Änderungen werden direkt im Array vorgenommen
* @param coord Array mit vier Koordinateneinträgen im gegebenen Modus
* @param mode Modus der Koordinaten (CORNER, CORNERS, RADIUS oder CENTER)
*/
private void convert(int[] coord, int mode) {
switch(mode) {
case CORNER: break;
case CORNERS: coord[2] -= coord[0]; coord[3] -= coord[1]; break;
case RADIUS: coord[2] *= 2; coord[3] *=2;
case CENTER: coord[0] -= coord[2]/2; coord[1] -= coord[3]/2;
}
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
rectMode = mode;
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
ellipseMode = mode;
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if (stroke > 0) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawLine(x1, y1, x2, y2);
}
repaint();
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, rectMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillRect(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawRect(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, ellipseMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillOval(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawOval(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
int px[] = {x1, x2, x3};
int py[] = {y1, y2, y3};
polygon(px, py);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
int px[] = {x1, x2, x3, x4};
int py[] = {y1, y2, y3, y4};
polygon(px, py);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillPolygon(x,y, y.length);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawPolygon(x, y, x.length);
}
repaint();
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
ellipse(x,y,1, 1);
}
// ----------------------------------------- Schriftdarstellung -----------------------------------------------
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param s Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String s, int x, int y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(pencolor != null) {
g.setColor(fillcolor);
g.setStroke(new BasicStroke((float) stroke));
g.setFont(textfont);
g.drawString(s, x, y);
}
repaint();
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
this.textfont = font;
}
// ----------------------------------------- Farbfestlegungen -----------------------------------------------
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(String color) {
try{
return new Color(
Integer.valueOf( color.substring( 0, 2 ), 16 ),
Integer.valueOf( color.substring( 2, 4 ), 16 ),
Integer.valueOf( color.substring( 4, 6 ), 16 ) );
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(int color) {
try{
if(color >=0 && color < 256) {
return new Color(color,color,color);
} else {
int r = color / 0x010000 % 0xFF;
int g = color / 0x000100 % 0xFF;
int b = color % 0xFF;
System.out.println(""+r+","+g+","+b);
return new Color(r, g, b );
}
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
this.pencolor = decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
this.pencolor=decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
this.pencolor = new Color(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
this.pencolor = null;
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
this.stroke = width;
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
this.fillcolor = decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
this.fillcolor=decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
this.fillcolor = new Color(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
this.fillcolor = null;
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
if(c < 256) {
this.background=new Color(c,c,c);
} else {
int r = c / 0x010000;
int g = c / 0x000100 % 0xFF;
int b = c % 0xFF;
this.background= new Color(r, g, b );
}
this.clear();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
this.background=new Color(r,g,b);
this.clear();
}
// ----------------------------------------- Dateioperationen -----------------------------------------------
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
try{
this.image = ImageIO.read(new File(filename));
this.background = decode("D0D0D0");
this.pencolor = new Color(0,0,0);
this.fillcolor = null;
this.stroke = 1;
this.repaint();
} catch(Exception e) {
System.out.println("Fehler beim Einlesen der Bilddatei");
}
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
try{
String[] fn = filename.split("\\.");
if (fn.length== 1) {
ImageIO.write(image, "PNG", new File(filename+".png"));
} else {
if (fn.length == 2 && (fn[1].toUpperCase().equals("PNG") ||
fn[1].toUpperCase().equals("GIF"))){
ImageIO.write(image, fn[1], new File(filename));
}else {
System.out.println("Unbekanntes Bildformat");
}
}
} catch(Exception e) {
System.out.println("Fehler beim Speichern");
}
}
// ----------------------------------------- Sonstiges -----------------------------------------------
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
Color[][] pixel = new Color[image.getWidth()][image.getHeight()];
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
pixel[x][y] = new java.awt.Color(image.getRGB(x,y));
}
}
return pixel;
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
size(pixel.length,pixel[0].length);
Graphics2D g = (Graphics2D) image.getGraphics();
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
g.setColor(pixel[x][y]);
g.fillRect(x, y, 1, 1);
}
}
repaint();
}
/**
* Hilfsfunktion zum Verzögern der Ausgabe
* @param millis Wartezeit in Millisekunden
*/
public void delay(int millis) {
try{
Thread.sleep(millis);
} catch(Exception e) {
}
}
}

View file

@ -0,0 +1,507 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.awt.Font;
import java.util.Vector;
import java.awt.Color;
import javax.imageio.*;
import java.io.*;
/**
* Der PictureViewer ist ein Actor, der in der Lage ist ein
* Objekt der Klasse Picture anzuzeigen. Zusätzlich können
* mehrere Verarbeitungsschritte gespeichert werden, um ein
* "zurück"-Funktion zu ermöglichen.
*
* @author Thomas Schaller
* @version V1.0 vom 10.02.2019
*/
public class PictureViewer extends Actor
{
public static final int FIT = -1;
public static final int NORMAL = 1;
private static final int ANZ_BACK = 0;
private double zoom;
private boolean autoRefresh = true;
protected Picture picture = null;
private Vector<BufferedImage> history;
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der Größe 500x400
*/
public PictureViewer() {
this(500,400);
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public PictureViewer(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds als HEX-String (z.B. "FF3A45")
*/
public PictureViewer(int width, int height, String background) {
picture = new Picture(width,height, background);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild aus einer Bilddatei
* @param filename Name des Bildes
*/
public PictureViewer(String filename) {
picture = new Picture(filename);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Speichert das übergebene Bild in der History.
* @param b zu speicherndes Bild
*/
public void pushImage() {
if( this.ANZ_BACK > 0) {
if(history.size() == this.ANZ_BACK) {
history.removeElementAt(0);
}
BufferedImage b = new BufferedImage(picture.getWidth(), picture.getHeight(), picture.getImage().getType());
Graphics g = b.getGraphics();
g.drawImage(picture.getImage(), 0, 0, null);
g.dispose();
history.add(b);
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
private void popImage() {
int anz = history.size();
if(anz>0) {
BufferedImage i = history.get(anz-1);
history.removeElementAt(anz-1);
picture.setImage(i);
repaint();
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
public void back() {
popImage();
}
/**
* Setzt den Zoom-Faktor für das Bild.
* Als Zoomfaktor sind auch die Konstanten Bildanzeiger.FIT (auf Bildschirmgröße zoomen) und Bildanzeiger.NORMAL (100%) möglich.
* @param factor Zoomfaktor (1.0 = 100%).
*/
public void setZoom(double zoom) {
this.zoom = zoom;
repaint();
}
/**
* Setzt die automatische Neuanzeige des Bildes.
* Mit dieser Methode kann man einstellen, ob nach jedem Zeichenbefehl
* die Anzeige auf dem Bildschirm aktualisiert werden soll. Bei sehr
* vielen Zeichenbefehlen wird die Ausgabe dadurch sehr langsam. Es reicht
* eine Anzeige am Ende der Zeichenbefehle. Rufen Sie dann für das Neuzeichnen
* die Methode refresh() auf.
* @param autoRefresh true, wenn nach jedem Zeichenbefehl die Anzeige aktualisiert werden soll.
*/
public void setAutoRefresh(boolean autoRefresh) {
this.autoRefresh = autoRefresh;
}
/**
* Sorgt für die Aktualisierung der Bildschrimanzeige. Das aktuelle Bild
* wird dadurch angezeigt. Durch Einstellung von autoRefresh kann die
* Anzeige automatisiert werden.
*/
public void refresh() {
double faktor = zoom;
if (zoom == FIT) {
double faktorw = (double) this.getWorld().getWidth() / picture.getWidth();
double faktorh = (double) this.getWorld().getHeight() / picture.getHeight();
faktor = Math.min(faktorw, faktorh);
}
int gfi_width = (int) (picture.getWidth()*faktor);
int gfi_height = (int) (picture.getHeight()*faktor);
setImage(new GreenfootImage(gfi_width, gfi_height));
Graphics2D g = (Graphics2D) this.getImage().getAwtImage().getGraphics();
g.drawImage(picture.getImage(),0,0,gfi_width, gfi_height, 0, 0, picture.getWidth(), picture.getHeight(), null);
g.setColor(new java.awt.Color(0,0,0));
g.setStroke(new BasicStroke((float) 1));
g.drawRect(0,0,gfi_width-1, gfi_height-1);
}
/**
* Setzt das angezeigt Bild neu und beachtet dabei den Zoomfaktor.
*/
public void repaint() {
if(autoRefresh) {
refresh();
}
}
// Wrappermethoden
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
picture.size(width, height);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getImageWidth() {
return picture.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getImageHeight() {
return picture.getHeight();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
picture.background(c);
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
picture.background(r,g,b);
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
picture.line(x1,y1,x2,y2);
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
picture.rect(a,b,c,d);
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
picture.ellipse(a,b,c,d);
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
picture.triangle(x1,y1,x2,y2,x3,y3);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
picture.quad(x1,y1,x2,y2,x3,y3,x4,y4);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
picture.polygon(x,y);
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
picture.point(x,y);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
picture.rectMode(mode);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
picture.ellipseMode(mode);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
picture.stroke(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
picture.noStroke();
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
picture.strokeWeight(width);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
picture.fill(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
picture.noFill();
}
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
picture.clear();
}
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
picture.load(filename);
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
picture.save(filename);
}
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param t Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String t, int x, int y) {
picture.text(t,x,y);
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
picture.textFont(font);
}
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
return picture.getPixelArray();
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
picture.setPixelArray(pixel);
}
}

View file

@ -0,0 +1,14 @@
------------------------------------------------------------------------
Dies ist die README-Datei des Projekts. Hier sollten Sie Ihr Projekt
beschreiben.
Erzählen Sie dem Leser (jemand, der nichts über dieses Projekt weiss),
alles, was er/sie wissen muss. Üblicherweise sollte der Kommentar
zumindest die folgenden Angaben umfassen:
------------------------------------------------------------------------
PROJEKTBEZEICHNUNG:
PROJEKTZWECK:
VERSION oder DATUM:
WIE IST DAS PROJEKT ZU STARTEN:
AUTOR(EN):
BENUTZERHINWEISE:

View file

@ -0,0 +1,24 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.Font;
/**
* Entdecken von Zeichenmethoden
*
* @author Eisenmann, Vorlage: Schaller
* @version 13.03.19
*/
public class Zeichnung extends PictureViewer
{
public Zeichnung() {
size(700, 400);
waszeichneich(); // Aufruf der Methode
}
void waszeichneich() {
line(100, 50, 200, 100);
ellipse(100, 200, 50, 100);
rect(300, 100, 250, 20);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -0,0 +1,66 @@
#Greenfoot project file
class.PictureViewer.image=bilderrahmen.png
class.Zeichnung.image=balken.png
dependency1.from=MyWorld
dependency1.to=Zeichnung
dependency1.type=UsesDependency
dependency2.from=PictureViewer
dependency2.to=Picture
dependency2.type=UsesDependency
dependency3.from=Picture
dependency3.to=PictureViewer
dependency3.type=UsesDependency
editor.fx.0.height=0
editor.fx.0.width=0
editor.fx.0.x=0
editor.fx.0.y=0
height=885
package.numDependencies=3
package.numTargets=4
project.charset=UTF-8
publish.hasSource=false
publish.locked=true
publish.longDesc=
publish.shortDesc=
publish.tags=
publish.title=
publish.url=
readme.height=58
readme.name=@README
readme.width=47
readme.x=10
readme.y=10
simulation.speed=97
target1.height=50
target1.name=PictureViewer
target1.showInterface=false
target1.type=ClassTarget
target1.width=100
target1.x=0
target1.y=0
target2.height=50
target2.name=Zeichnung
target2.showInterface=false
target2.type=ClassTarget
target2.width=120
target2.x=0
target2.y=0
target3.height=50
target3.name=Picture
target3.showInterface=false
target3.type=ClassTarget
target3.width=80
target3.x=0
target3.y=0
target4.height=50
target4.name=MyWorld
target4.showInterface=false
target4.type=ClassTarget
target4.width=80
target4.x=0
target4.y=0
version=3.0.0
width=1350
world.lastInstantiated=MyWorld
xPosition=271
yPosition=94

View file

@ -0,0 +1,36 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
/**
* Ergänzen Sie hier eine Beschreibung für die Klasse MyWorld.
*
* @author (Ihr Name)
* @version (eine Versionsnummer oder ein Datum)
*/
public class MyWorld extends World
{
/**
* Konstruktor für Objekte der Klasse MyWorld
*
*/
public MyWorld()
{
// Erstellt eine neue Welt mit 1200x900 Pixeln
super(1000, 700, 1);
prepare();
}
/**
* Bereite die Welt für den Programmstart vor.
* Das heißt: Erzeuge die Anfangs-Objekte und füge sie der Welt hinzu.
*/
private void prepare()
{
Zeichnung zeichnung = new Zeichnung();
addObject(zeichnung,500,350);
}
}

View file

@ -0,0 +1,677 @@
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.util.Vector;
import javax.imageio.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
import java.awt.geom.AffineTransform;
/**
*
* Bildklasse für die Simulation von Processing-Befehlen
*
* Diese Klasse stellt ein BufferedImage bereit, in das mit Processing-Befehlen gezeichnet
* werden kann.
* Zusätzlich kann ein Bildanzeiger über jede Änderung des Bildes informiert werden,
* um "Zurück"-Befehle zu ermöglichen. Der Bildanzeiger ist entweder eine normale Java
* ScrollPane oder ein Actor aus Greenfoot.
* Die Dokumentation der einzelnen Zeichenmethoden ist der Processing-Reference
* (https://processing.org/reference/ steht unter CC-Lizenz: https://creativecommons.org/)
* entnommen und mit Deepl.com ins Deutsche übersetzt.
*
* @version 1.0 from 23.01.2019
* @author Thomas Schaller (ZPG Informatik Klasse 9)
*/
public class Picture{
// Einstellungmöglichkeiten für das Zeichnen von Rechtecken und Ellipsen
// RADIUS = Mittelpunkt+Radius wird gegeben, CENTER = Mittelpunkt und Breite/Höhe wird gegeben,
// CORNER = Linke obere Ecke + Breite/Höhe, CORNERS = Linke obere und rechte untere Ecke
public static final int RADIUS = 1;
public static final int CENTER = 2;
public static final int CORNER = 3;
public static final int CORNERS = 4;
// gespeichertes Bild,
private BufferedImage image;
// aktuelle Farbeinstellungen
private Color background;
private Color pencolor;
private Color fillcolor;
// aktuelle Stiftdicke
private double stroke;
// akkteller Koordinatenmodus von Rechtecken und Ellipsen
private int ellipseMode = CENTER;
private int rectMode = CORNER;
// aktueller Font
private Font textfont = null;
// muss ein Bildanzeiger benachrichtigt werden
private PictureViewer observer = null;
/**
* Erzeugt ein Bild mit Standardgröße 500x400
*/
public Picture() {
this(500,400);
}
/**
* Erzeugt ein Bild der angegeben Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public Picture(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein Bild aus einer Datei
* @param filename Dateiname des Bildes
*/
public Picture(String filename) {
load(filename);
}
/**
* Erzeugt ein Bild der angegebenen Größe mit festgelegtem Hintergrund
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds
*/
public Picture(int width, int height, String background) {
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
this.background = decode(background);
this.pencolor = new Color(0,0,0);
this.stroke = 1;
this.fillcolor = null;
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(this.background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Legt fest, wer das Bild anzeigt.
* Diese ermöglicht die Benachrichtung des Observers, wenn sich das Bild ändert.
* @param observer Anzeiger des Bildes
*/
public void setObserver(PictureViewer observer) {
this.observer= observer;
}
/**
* Direktes Setzen des Bildes (für interne Zwecke)
* @param b Bild, das gespeichert werden soll.
*/
public void setImage(BufferedImage b) {
image = b;
}
/**
* Direktes Abfragen des Bildes (für interne Zwecke)
* @return Bild, das gerade gespeichert ist.
*/
public BufferedImage getImage() {
return image;
}
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
pushImage();
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getWidth() {
return image.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getHeight() {
return image.getHeight();
}
/**
* Erzeugt eine Kopie des Bildes und übergibt sie an den Observer (falls existent), damit dieser die Versionen speichern kann
*/
private void pushImage() {
if(observer != null) {
observer.pushImage();
}
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
private void repaint() {
if(observer != null) {
observer.repaint();
}
}
// ----------------------------------------- Zeichenfunktionen -----------------------------------------------
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
pushImage();
image = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,image.getWidth()-1, image.getHeight()-1);
repaint();
}
/**
* Konvertiert die in einem bestimmten Modus gegebenen Koordinaten in die Java-übliche Links_Oben_Breite_Höhe Version
* Die Änderungen werden direkt im Array vorgenommen
* @param coord Array mit vier Koordinateneinträgen im gegebenen Modus
* @param mode Modus der Koordinaten (CORNER, CORNERS, RADIUS oder CENTER)
*/
private void convert(int[] coord, int mode) {
switch(mode) {
case CORNER: break;
case CORNERS: coord[2] -= coord[0]; coord[3] -= coord[1]; break;
case RADIUS: coord[2] *= 2; coord[3] *=2;
case CENTER: coord[0] -= coord[2]/2; coord[1] -= coord[3]/2;
}
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
rectMode = mode;
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
ellipseMode = mode;
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if (stroke > 0) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawLine(x1, y1, x2, y2);
}
repaint();
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, rectMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillRect(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawRect(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, ellipseMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillOval(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawOval(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
int px[] = {x1, x2, x3};
int py[] = {y1, y2, y3};
polygon(px, py);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
int px[] = {x1, x2, x3, x4};
int py[] = {y1, y2, y3, y4};
polygon(px, py);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillPolygon(x,y, y.length);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawPolygon(x, y, x.length);
}
repaint();
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
ellipse(x,y,1, 1);
}
// ----------------------------------------- Schriftdarstellung -----------------------------------------------
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param s Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String s, int x, int y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(pencolor != null) {
g.setColor(fillcolor);
g.setStroke(new BasicStroke((float) stroke));
g.setFont(textfont);
g.drawString(s, x, y);
}
repaint();
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
this.textfont = font;
}
// ----------------------------------------- Farbfestlegungen -----------------------------------------------
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(String color) {
try{
return new Color(
Integer.valueOf( color.substring( 0, 2 ), 16 ),
Integer.valueOf( color.substring( 2, 4 ), 16 ),
Integer.valueOf( color.substring( 4, 6 ), 16 ) );
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(int color) {
try{
if(color >=0 && color < 256) {
return new Color(color,color,color);
} else {
int r = color / 0x010000 % 0xFF;
int g = color / 0x000100 % 0xFF;
int b = color % 0xFF;
System.out.println(""+r+","+g+","+b);
return new Color(r, g, b );
}
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
this.pencolor = decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
this.pencolor=decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
this.pencolor = new Color(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
this.pencolor = null;
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
this.stroke = width;
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
this.fillcolor = decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
this.fillcolor=decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
this.fillcolor = new Color(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
this.fillcolor = null;
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
if(c < 256) {
this.background=new Color(c,c,c);
} else {
int r = c / 0x010000;
int g = c / 0x000100 % 0xFF;
int b = c % 0xFF;
this.background= new Color(r, g, b );
}
this.clear();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
this.background=new Color(r,g,b);
this.clear();
}
// ----------------------------------------- Dateioperationen -----------------------------------------------
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
try{
this.image = ImageIO.read(new File(filename));
this.background = decode("D0D0D0");
this.pencolor = new Color(0,0,0);
this.fillcolor = null;
this.stroke = 1;
this.repaint();
} catch(Exception e) {
System.out.println("Fehler beim Einlesen der Bilddatei");
}
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
try{
String[] fn = filename.split("\\.");
if (fn.length== 1) {
ImageIO.write(image, "PNG", new File(filename+".png"));
} else {
if (fn.length == 2 && (fn[1].toUpperCase().equals("PNG") ||
fn[1].toUpperCase().equals("GIF"))){
ImageIO.write(image, fn[1], new File(filename));
}else {
System.out.println("Unbekanntes Bildformat");
}
}
} catch(Exception e) {
System.out.println("Fehler beim Speichern");
}
}
// ----------------------------------------- Sonstiges -----------------------------------------------
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
Color[][] pixel = new Color[image.getWidth()][image.getHeight()];
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
pixel[x][y] = new java.awt.Color(image.getRGB(x,y));
}
}
return pixel;
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
size(pixel.length,pixel[0].length);
Graphics2D g = (Graphics2D) image.getGraphics();
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
g.setColor(pixel[x][y]);
g.fillRect(x, y, 1, 1);
}
}
repaint();
}
/**
* Hilfsfunktion zum Verzögern der Ausgabe
* @param millis Wartezeit in Millisekunden
*/
public void delay(int millis) {
try{
Thread.sleep(millis);
} catch(Exception e) {
}
}
}

View file

@ -0,0 +1,507 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.awt.Font;
import java.util.Vector;
import java.awt.Color;
import javax.imageio.*;
import java.io.*;
/**
* Der PictureViewer ist ein Actor, der in der Lage ist ein
* Objekt der Klasse Picture anzuzeigen. Zusätzlich können
* mehrere Verarbeitungsschritte gespeichert werden, um ein
* "zurück"-Funktion zu ermöglichen.
*
* @author Thomas Schaller
* @version V1.0 vom 10.02.2019
*/
public class PictureViewer extends Actor
{
public static final int FIT = -1;
public static final int NORMAL = 1;
private static final int ANZ_BACK = 0;
private double zoom;
private boolean autoRefresh = true;
protected Picture picture = null;
private Vector<BufferedImage> history;
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der Größe 500x400
*/
public PictureViewer() {
this(500,400);
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public PictureViewer(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds als HEX-String (z.B. "FF3A45")
*/
public PictureViewer(int width, int height, String background) {
picture = new Picture(width,height, background);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild aus einer Bilddatei
* @param filename Name des Bildes
*/
public PictureViewer(String filename) {
picture = new Picture(filename);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Speichert das übergebene Bild in der History.
* @param b zu speicherndes Bild
*/
public void pushImage() {
if( this.ANZ_BACK > 0) {
if(history.size() == this.ANZ_BACK) {
history.removeElementAt(0);
}
BufferedImage b = new BufferedImage(picture.getWidth(), picture.getHeight(), picture.getImage().getType());
Graphics g = b.getGraphics();
g.drawImage(picture.getImage(), 0, 0, null);
g.dispose();
history.add(b);
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
private void popImage() {
int anz = history.size();
if(anz>0) {
BufferedImage i = history.get(anz-1);
history.removeElementAt(anz-1);
picture.setImage(i);
repaint();
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
public void back() {
popImage();
}
/**
* Setzt den Zoom-Faktor für das Bild.
* Als Zoomfaktor sind auch die Konstanten Bildanzeiger.FIT (auf Bildschirmgröße zoomen) und Bildanzeiger.NORMAL (100%) möglich.
* @param factor Zoomfaktor (1.0 = 100%).
*/
public void setZoom(double zoom) {
this.zoom = zoom;
repaint();
}
/**
* Setzt die automatische Neuanzeige des Bildes.
* Mit dieser Methode kann man einstellen, ob nach jedem Zeichenbefehl
* die Anzeige auf dem Bildschirm aktualisiert werden soll. Bei sehr
* vielen Zeichenbefehlen wird die Ausgabe dadurch sehr langsam. Es reicht
* eine Anzeige am Ende der Zeichenbefehle. Rufen Sie dann für das Neuzeichnen
* die Methode refresh() auf.
* @param autoRefresh true, wenn nach jedem Zeichenbefehl die Anzeige aktualisiert werden soll.
*/
public void setAutoRefresh(boolean autoRefresh) {
this.autoRefresh = autoRefresh;
}
/**
* Sorgt für die Aktualisierung der Bildschrimanzeige. Das aktuelle Bild
* wird dadurch angezeigt. Durch Einstellung von autoRefresh kann die
* Anzeige automatisiert werden.
*/
public void refresh() {
double faktor = zoom;
if (zoom == FIT) {
double faktorw = (double) this.getWorld().getWidth() / picture.getWidth();
double faktorh = (double) this.getWorld().getHeight() / picture.getHeight();
faktor = Math.min(faktorw, faktorh);
}
int gfi_width = (int) (picture.getWidth()*faktor);
int gfi_height = (int) (picture.getHeight()*faktor);
setImage(new GreenfootImage(gfi_width, gfi_height));
Graphics2D g = (Graphics2D) this.getImage().getAwtImage().getGraphics();
g.drawImage(picture.getImage(),0,0,gfi_width, gfi_height, 0, 0, picture.getWidth(), picture.getHeight(), null);
g.setColor(new java.awt.Color(0,0,0));
g.setStroke(new BasicStroke((float) 1));
g.drawRect(0,0,gfi_width-1, gfi_height-1);
}
/**
* Setzt das angezeigt Bild neu und beachtet dabei den Zoomfaktor.
*/
public void repaint() {
if(autoRefresh) {
refresh();
}
}
// Wrappermethoden
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
picture.size(width, height);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getImageWidth() {
return picture.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getImageHeight() {
return picture.getHeight();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
picture.background(c);
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
picture.background(r,g,b);
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
picture.line(x1,y1,x2,y2);
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
picture.rect(a,b,c,d);
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
picture.ellipse(a,b,c,d);
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
picture.triangle(x1,y1,x2,y2,x3,y3);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
picture.quad(x1,y1,x2,y2,x3,y3,x4,y4);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
picture.polygon(x,y);
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
picture.point(x,y);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
picture.rectMode(mode);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
picture.ellipseMode(mode);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
picture.stroke(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
picture.noStroke();
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
picture.strokeWeight(width);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
picture.fill(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
picture.noFill();
}
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
picture.clear();
}
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
picture.load(filename);
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
picture.save(filename);
}
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param t Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String t, int x, int y) {
picture.text(t,x,y);
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
picture.textFont(font);
}
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
return picture.getPixelArray();
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
picture.setPixelArray(pixel);
}
}

View file

@ -0,0 +1,14 @@
------------------------------------------------------------------------
Dies ist die README-Datei des Projekts. Hier sollten Sie Ihr Projekt
beschreiben.
Erzählen Sie dem Leser (jemand, der nichts über dieses Projekt weiss),
alles, was er/sie wissen muss. Üblicherweise sollte der Kommentar
zumindest die folgenden Angaben umfassen:
------------------------------------------------------------------------
PROJEKTBEZEICHNUNG:
PROJEKTZWECK:
VERSION oder DATUM:
WIE IST DAS PROJEKT ZU STARTEN:
AUTOR(EN):
BENUTZERHINWEISE:

View file

@ -0,0 +1,38 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.Font;
/**
* Entdecken von Zeichenmethoden
*
* @author Eisenmann, Vorlage: Schaller
* @version 13.03.19
*/
public class Zeichnung extends PictureViewer
{
public Zeichnung() {
size(500, 350);
zeichneBildC(); // Aufruf deiner Methode
// zeichneBildA();
}
void zeichneBildC() {
// Zeichne dir zunächst eine Skizze auf ein Blatt Papier und überlege dir, welche
// Werte du den Methoden rect(x,y,b,h) und ellipse(x,y,b,h) übergeben musst,
// dass Bild C gezeichnet wird
// ***** hier kommen deine Anweisungen hin ************
// ***** Ende der eigenen Anweisungen **********
}
// Zusatzaufgabe bzw. Hausaufgabe:
void zeichneBildA(){
// ******** hier kommen deine Anweisungen hin ***********
// ******** Ende der eigenen Anweisungen ***************
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -0,0 +1,78 @@
#Greenfoot project file
class.MyWorld.superclass=greenfoot.World
class.Picture.superclass=
class.PictureViewer.image=bilderrahmen.png
class.PictureViewer.superclass=greenfoot.Actor
class.Zeichnung.image=balken.png
class.Zeichnung.superclass=PictureViewer
dependency1.from=PictureViewer
dependency1.to=Picture
dependency1.type=UsesDependency
dependency2.from=Picture
dependency2.to=PictureViewer
dependency2.type=UsesDependency
dependency3.from=MyWorld
dependency3.to=Zeichnung
dependency3.type=UsesDependency
editor.fx.0.height=739
editor.fx.0.width=816
editor.fx.0.x=1042
editor.fx.0.y=22
height=885
mainWindow.height=881
mainWindow.width=1281
mainWindow.x=40
mainWindow.y=40
package.numDependencies=3
package.numTargets=4
project.charset=UTF-8
publish.hasSource=false
publish.locked=true
publish.longDesc=
publish.shortDesc=
publish.tags=
publish.title=
publish.url=
readme.height=58
readme.name=@README
readme.width=47
readme.x=10
readme.y=10
simulation.speed=97
target1.height=50
target1.name=PictureViewer
target1.showInterface=false
target1.type=ClassTarget
target1.typeParameters=
target1.width=100
target1.x=0
target1.y=0
target2.height=50
target2.name=Zeichnung
target2.showInterface=false
target2.type=ClassTarget
target2.typeParameters=
target2.width=120
target2.x=0
target2.y=0
target3.height=50
target3.name=Picture
target3.showInterface=false
target3.type=ClassTarget
target3.typeParameters=
target3.width=80
target3.x=0
target3.y=0
target4.height=50
target4.name=MyWorld
target4.showInterface=false
target4.type=ClassTarget
target4.typeParameters=
target4.width=80
target4.x=0
target4.y=0
version=3.0.0
width=1350
world.lastInstantiated=MyWorld
xPosition=271
yPosition=94

View file

@ -0,0 +1,36 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
/**
* Ergänzen Sie hier eine Beschreibung für die Klasse MyWorld.
*
* @author (Ihr Name)
* @version (eine Versionsnummer oder ein Datum)
*/
public class MyWorld extends World
{
/**
* Konstruktor für Objekte der Klasse MyWorld
*
*/
public MyWorld()
{
// Erstellt eine neue Welt mit 1200x900 Pixeln
super(1000, 700, 1);
prepare();
}
/**
* Bereite die Welt für den Programmstart vor.
* Das heißt: Erzeuge die Anfangs-Objekte und füge sie der Welt hinzu.
*/
private void prepare()
{
Zeichnung zeichnung = new Zeichnung();
addObject(zeichnung,500,350);
}
}

View file

@ -0,0 +1,677 @@
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.util.Vector;
import javax.imageio.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
import java.awt.geom.AffineTransform;
/**
*
* Bildklasse für die Simulation von Processing-Befehlen
*
* Diese Klasse stellt ein BufferedImage bereit, in das mit Processing-Befehlen gezeichnet
* werden kann.
* Zusätzlich kann ein Bildanzeiger über jede Änderung des Bildes informiert werden,
* um "Zurück"-Befehle zu ermöglichen. Der Bildanzeiger ist entweder eine normale Java
* ScrollPane oder ein Actor aus Greenfoot.
* Die Dokumentation der einzelnen Zeichenmethoden ist der Processing-Reference
* (https://processing.org/reference/ steht unter CC-Lizenz: https://creativecommons.org/)
* entnommen und mit Deepl.com ins Deutsche übersetzt.
*
* @version 1.0 from 23.01.2019
* @author Thomas Schaller (ZPG Informatik Klasse 9)
*/
public class Picture{
// Einstellungmöglichkeiten für das Zeichnen von Rechtecken und Ellipsen
// RADIUS = Mittelpunkt+Radius wird gegeben, CENTER = Mittelpunkt und Breite/Höhe wird gegeben,
// CORNER = Linke obere Ecke + Breite/Höhe, CORNERS = Linke obere und rechte untere Ecke
public static final int RADIUS = 1;
public static final int CENTER = 2;
public static final int CORNER = 3;
public static final int CORNERS = 4;
// gespeichertes Bild,
private BufferedImage image;
// aktuelle Farbeinstellungen
private Color background;
private Color pencolor;
private Color fillcolor;
// aktuelle Stiftdicke
private double stroke;
// akkteller Koordinatenmodus von Rechtecken und Ellipsen
private int ellipseMode = CENTER;
private int rectMode = CORNER;
// aktueller Font
private Font textfont = null;
// muss ein Bildanzeiger benachrichtigt werden
private PictureViewer observer = null;
/**
* Erzeugt ein Bild mit Standardgröße 500x400
*/
public Picture() {
this(500,400);
}
/**
* Erzeugt ein Bild der angegeben Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public Picture(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein Bild aus einer Datei
* @param filename Dateiname des Bildes
*/
public Picture(String filename) {
load(filename);
}
/**
* Erzeugt ein Bild der angegebenen Größe mit festgelegtem Hintergrund
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds
*/
public Picture(int width, int height, String background) {
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
this.background = decode(background);
this.pencolor = new Color(0,0,0);
this.stroke = 1;
this.fillcolor = null;
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(this.background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Legt fest, wer das Bild anzeigt.
* Diese ermöglicht die Benachrichtung des Observers, wenn sich das Bild ändert.
* @param observer Anzeiger des Bildes
*/
public void setObserver(PictureViewer observer) {
this.observer= observer;
}
/**
* Direktes Setzen des Bildes (für interne Zwecke)
* @param b Bild, das gespeichert werden soll.
*/
public void setImage(BufferedImage b) {
image = b;
}
/**
* Direktes Abfragen des Bildes (für interne Zwecke)
* @return Bild, das gerade gespeichert ist.
*/
public BufferedImage getImage() {
return image;
}
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
pushImage();
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getWidth() {
return image.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getHeight() {
return image.getHeight();
}
/**
* Erzeugt eine Kopie des Bildes und übergibt sie an den Observer (falls existent), damit dieser die Versionen speichern kann
*/
private void pushImage() {
if(observer != null) {
observer.pushImage();
}
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
private void repaint() {
if(observer != null) {
observer.repaint();
}
}
// ----------------------------------------- Zeichenfunktionen -----------------------------------------------
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
pushImage();
image = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,image.getWidth()-1, image.getHeight()-1);
repaint();
}
/**
* Konvertiert die in einem bestimmten Modus gegebenen Koordinaten in die Java-übliche Links_Oben_Breite_Höhe Version
* Die Änderungen werden direkt im Array vorgenommen
* @param coord Array mit vier Koordinateneinträgen im gegebenen Modus
* @param mode Modus der Koordinaten (CORNER, CORNERS, RADIUS oder CENTER)
*/
private void convert(int[] coord, int mode) {
switch(mode) {
case CORNER: break;
case CORNERS: coord[2] -= coord[0]; coord[3] -= coord[1]; break;
case RADIUS: coord[2] *= 2; coord[3] *=2;
case CENTER: coord[0] -= coord[2]/2; coord[1] -= coord[3]/2;
}
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
rectMode = mode;
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
ellipseMode = mode;
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if (stroke > 0) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawLine(x1, y1, x2, y2);
}
repaint();
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, rectMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillRect(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawRect(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, ellipseMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillOval(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawOval(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
int px[] = {x1, x2, x3};
int py[] = {y1, y2, y3};
polygon(px, py);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
int px[] = {x1, x2, x3, x4};
int py[] = {y1, y2, y3, y4};
polygon(px, py);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillPolygon(x,y, y.length);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawPolygon(x, y, x.length);
}
repaint();
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
ellipse(x,y,1, 1);
}
// ----------------------------------------- Schriftdarstellung -----------------------------------------------
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param s Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String s, int x, int y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(pencolor != null) {
g.setColor(fillcolor);
g.setStroke(new BasicStroke((float) stroke));
g.setFont(textfont);
g.drawString(s, x, y);
}
repaint();
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
this.textfont = font;
}
// ----------------------------------------- Farbfestlegungen -----------------------------------------------
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(String color) {
try{
return new Color(
Integer.valueOf( color.substring( 0, 2 ), 16 ),
Integer.valueOf( color.substring( 2, 4 ), 16 ),
Integer.valueOf( color.substring( 4, 6 ), 16 ) );
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(int color) {
try{
if(color >=0 && color < 256) {
return new Color(color,color,color);
} else {
int r = color / 0x010000 % 0xFF;
int g = color / 0x000100 % 0xFF;
int b = color % 0xFF;
System.out.println(""+r+","+g+","+b);
return new Color(r, g, b );
}
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
this.pencolor = decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
this.pencolor=decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
this.pencolor = new Color(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
this.pencolor = null;
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
this.stroke = width;
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
this.fillcolor = decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
this.fillcolor=decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
this.fillcolor = new Color(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
this.fillcolor = null;
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
if(c < 256) {
this.background=new Color(c,c,c);
} else {
int r = c / 0x010000;
int g = c / 0x000100 % 0xFF;
int b = c % 0xFF;
this.background= new Color(r, g, b );
}
this.clear();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
this.background=new Color(r,g,b);
this.clear();
}
// ----------------------------------------- Dateioperationen -----------------------------------------------
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
try{
this.image = ImageIO.read(new File(filename));
this.background = decode("D0D0D0");
this.pencolor = new Color(0,0,0);
this.fillcolor = null;
this.stroke = 1;
this.repaint();
} catch(Exception e) {
System.out.println("Fehler beim Einlesen der Bilddatei");
}
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
try{
String[] fn = filename.split("\\.");
if (fn.length== 1) {
ImageIO.write(image, "PNG", new File(filename+".png"));
} else {
if (fn.length == 2 && (fn[1].toUpperCase().equals("PNG") ||
fn[1].toUpperCase().equals("GIF"))){
ImageIO.write(image, fn[1], new File(filename));
}else {
System.out.println("Unbekanntes Bildformat");
}
}
} catch(Exception e) {
System.out.println("Fehler beim Speichern");
}
}
// ----------------------------------------- Sonstiges -----------------------------------------------
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
Color[][] pixel = new Color[image.getWidth()][image.getHeight()];
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
pixel[x][y] = new java.awt.Color(image.getRGB(x,y));
}
}
return pixel;
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
size(pixel.length,pixel[0].length);
Graphics2D g = (Graphics2D) image.getGraphics();
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
g.setColor(pixel[x][y]);
g.fillRect(x, y, 1, 1);
}
}
repaint();
}
/**
* Hilfsfunktion zum Verzögern der Ausgabe
* @param millis Wartezeit in Millisekunden
*/
public void delay(int millis) {
try{
Thread.sleep(millis);
} catch(Exception e) {
}
}
}

View file

@ -0,0 +1,507 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.awt.Font;
import java.util.Vector;
import java.awt.Color;
import javax.imageio.*;
import java.io.*;
/**
* Der PictureViewer ist ein Actor, der in der Lage ist ein
* Objekt der Klasse Picture anzuzeigen. Zusätzlich können
* mehrere Verarbeitungsschritte gespeichert werden, um ein
* "zurück"-Funktion zu ermöglichen.
*
* @author Thomas Schaller
* @version V1.0 vom 10.02.2019
*/
public class PictureViewer extends Actor
{
public static final int FIT = -1;
public static final int NORMAL = 1;
private static final int ANZ_BACK = 0;
private double zoom;
private boolean autoRefresh = true;
protected Picture picture = null;
private Vector<BufferedImage> history;
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der Größe 500x400
*/
public PictureViewer() {
this(500,400);
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public PictureViewer(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds als HEX-String (z.B. "FF3A45")
*/
public PictureViewer(int width, int height, String background) {
picture = new Picture(width,height, background);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild aus einer Bilddatei
* @param filename Name des Bildes
*/
public PictureViewer(String filename) {
picture = new Picture(filename);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Speichert das übergebene Bild in der History.
* @param b zu speicherndes Bild
*/
public void pushImage() {
if( this.ANZ_BACK > 0) {
if(history.size() == this.ANZ_BACK) {
history.removeElementAt(0);
}
BufferedImage b = new BufferedImage(picture.getWidth(), picture.getHeight(), picture.getImage().getType());
Graphics g = b.getGraphics();
g.drawImage(picture.getImage(), 0, 0, null);
g.dispose();
history.add(b);
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
private void popImage() {
int anz = history.size();
if(anz>0) {
BufferedImage i = history.get(anz-1);
history.removeElementAt(anz-1);
picture.setImage(i);
repaint();
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
public void back() {
popImage();
}
/**
* Setzt den Zoom-Faktor für das Bild.
* Als Zoomfaktor sind auch die Konstanten Bildanzeiger.FIT (auf Bildschirmgröße zoomen) und Bildanzeiger.NORMAL (100%) möglich.
* @param factor Zoomfaktor (1.0 = 100%).
*/
public void setZoom(double zoom) {
this.zoom = zoom;
repaint();
}
/**
* Setzt die automatische Neuanzeige des Bildes.
* Mit dieser Methode kann man einstellen, ob nach jedem Zeichenbefehl
* die Anzeige auf dem Bildschirm aktualisiert werden soll. Bei sehr
* vielen Zeichenbefehlen wird die Ausgabe dadurch sehr langsam. Es reicht
* eine Anzeige am Ende der Zeichenbefehle. Rufen Sie dann für das Neuzeichnen
* die Methode refresh() auf.
* @param autoRefresh true, wenn nach jedem Zeichenbefehl die Anzeige aktualisiert werden soll.
*/
public void setAutoRefresh(boolean autoRefresh) {
this.autoRefresh = autoRefresh;
}
/**
* Sorgt für die Aktualisierung der Bildschrimanzeige. Das aktuelle Bild
* wird dadurch angezeigt. Durch Einstellung von autoRefresh kann die
* Anzeige automatisiert werden.
*/
public void refresh() {
double faktor = zoom;
if (zoom == FIT) {
double faktorw = (double) this.getWorld().getWidth() / picture.getWidth();
double faktorh = (double) this.getWorld().getHeight() / picture.getHeight();
faktor = Math.min(faktorw, faktorh);
}
int gfi_width = (int) (picture.getWidth()*faktor);
int gfi_height = (int) (picture.getHeight()*faktor);
setImage(new GreenfootImage(gfi_width, gfi_height));
Graphics2D g = (Graphics2D) this.getImage().getAwtImage().getGraphics();
g.drawImage(picture.getImage(),0,0,gfi_width, gfi_height, 0, 0, picture.getWidth(), picture.getHeight(), null);
g.setColor(new java.awt.Color(0,0,0));
g.setStroke(new BasicStroke((float) 1));
g.drawRect(0,0,gfi_width-1, gfi_height-1);
}
/**
* Setzt das angezeigt Bild neu und beachtet dabei den Zoomfaktor.
*/
public void repaint() {
if(autoRefresh) {
refresh();
}
}
// Wrappermethoden
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
picture.size(width, height);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getImageWidth() {
return picture.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getImageHeight() {
return picture.getHeight();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
picture.background(c);
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
picture.background(r,g,b);
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
picture.line(x1,y1,x2,y2);
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
picture.rect(a,b,c,d);
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
picture.ellipse(a,b,c,d);
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
picture.triangle(x1,y1,x2,y2,x3,y3);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
picture.quad(x1,y1,x2,y2,x3,y3,x4,y4);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
picture.polygon(x,y);
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
picture.point(x,y);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
picture.rectMode(mode);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
picture.ellipseMode(mode);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
picture.stroke(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
picture.noStroke();
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
picture.strokeWeight(width);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
picture.fill(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
picture.noFill();
}
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
picture.clear();
}
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
picture.load(filename);
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
picture.save(filename);
}
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param t Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String t, int x, int y) {
picture.text(t,x,y);
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
picture.textFont(font);
}
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
return picture.getPixelArray();
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
picture.setPixelArray(pixel);
}
}

View file

@ -0,0 +1,14 @@
------------------------------------------------------------------------
Dies ist die README-Datei des Projekts. Hier sollten Sie Ihr Projekt
beschreiben.
Erzählen Sie dem Leser (jemand, der nichts über dieses Projekt weiss),
alles, was er/sie wissen muss. Üblicherweise sollte der Kommentar
zumindest die folgenden Angaben umfassen:
------------------------------------------------------------------------
PROJEKTBEZEICHNUNG:
PROJEKTZWECK:
VERSION oder DATUM:
WIE IST DAS PROJEKT ZU STARTEN:
AUTOR(EN):
BENUTZERHINWEISE:

View file

@ -0,0 +1,25 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.Font;
/**
* Entdecken von Zeichenmethoden
*
* @author Eisenmann, Vorlage: Schaller
* @version 13.03.19
*/
public class Zeichnung extends PictureViewer
{
public Zeichnung() {
size(500, 350);
zeichneBildC(); // Aufruf deiner Methode
}
void zeichneBildC() {
// ***** hier kommen deine Anweisungen hin ************
// ***** Ende der eigenen Anweisungen **********
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -0,0 +1,78 @@
#Greenfoot project file
class.MyWorld.superclass=greenfoot.World
class.Picture.superclass=
class.PictureViewer.image=bilderrahmen.png
class.PictureViewer.superclass=greenfoot.Actor
class.Zeichnung.image=balken.png
class.Zeichnung.superclass=PictureViewer
dependency1.from=PictureViewer
dependency1.to=Picture
dependency1.type=UsesDependency
dependency2.from=Picture
dependency2.to=PictureViewer
dependency2.type=UsesDependency
dependency3.from=MyWorld
dependency3.to=Zeichnung
dependency3.type=UsesDependency
editor.fx.0.height=739
editor.fx.0.width=816
editor.fx.0.x=787
editor.fx.0.y=123
height=885
mainWindow.height=881
mainWindow.width=1281
mainWindow.x=40
mainWindow.y=40
package.numDependencies=3
package.numTargets=4
project.charset=UTF-8
publish.hasSource=false
publish.locked=true
publish.longDesc=
publish.shortDesc=
publish.tags=
publish.title=
publish.url=
readme.height=58
readme.name=@README
readme.width=47
readme.x=10
readme.y=10
simulation.speed=97
target1.height=50
target1.name=PictureViewer
target1.showInterface=false
target1.type=ClassTarget
target1.typeParameters=
target1.width=100
target1.x=0
target1.y=0
target2.height=50
target2.name=Zeichnung
target2.showInterface=false
target2.type=ClassTarget
target2.typeParameters=
target2.width=120
target2.x=0
target2.y=0
target3.height=50
target3.name=Picture
target3.showInterface=false
target3.type=ClassTarget
target3.typeParameters=
target3.width=80
target3.x=0
target3.y=0
target4.height=50
target4.name=MyWorld
target4.showInterface=false
target4.type=ClassTarget
target4.typeParameters=
target4.width=80
target4.x=0
target4.y=0
version=3.0.0
width=1350
world.lastInstantiated=MyWorld
xPosition=271
yPosition=94

View file

@ -0,0 +1,55 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.Font;
/**
* Balkendiagramm für int-Array.
*
* @author Schaller
* @version 29.11.18
*/
public class Balkendiagramm extends PictureViewer
{
// Liste mit allen Werten
int[] zahlen={45, 23, 123, 87, 98, 2, 1, 23, 23, 34};;
// Schriften
Font kleineSchrift;
Font grosseSchrift;
public Balkendiagramm() {
size(1000, 700);
background(0);
kleineSchrift = new Font( Font.SANS_SERIF, Font.PLAIN, 12 );
grosseSchrift = new Font( Font.SANS_SERIF, Font.PLAIN, 20 );
zeichneBalken();
}
public void zeichneBalken() {
clear();
// Überschrift
fill(255,255,255);
textFont(grosseSchrift);
text("Balkendiagramm", 2, 20);
textFont(kleineSchrift);
// ----------------------------------------------------------------------
// To Do
// ----------------------------------------------------------------------
// Version 1:
// Implementiere die ersten vier Balken durch Angabe der Koordinaten aus der Tabelle.
// Ergänze dazu die Methode zeicheBalken an der "ToDo"-Stelle.
// Version 2:
// Ersetze die y-Koordinate und die Breite durch die oben ermittelte Formel.
// Deklariere vorher eine Integer-Variable i. Setze i vor der ersten Rechteck
// auf 0, vor dem zweite auf 1 usw. Überprüfe, ob deine Rechtecke immer noch
// korrekt gezeichnet werden.
// Version 3:
// Verwende eine for-Schleife, um alle Balken zeichnen zu lassen. Diese muss das i
// in jedem Durchgang um 1 erhöhen. Die Anzahl der Elemente im Array bekommst du
// durch zahlen.length.
// Tipp: Vergleiche mit deiner Implementation von der Kaffeehaus-Täuschung.
}
}

View file

@ -0,0 +1,36 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
/**
* Ergänzen Sie hier eine Beschreibung für die Klasse MyWorld.
*
* @author (Ihr Name)
* @version (eine Versionsnummer oder ein Datum)
*/
public class MyWorld extends World
{
/**
* Konstruktor für Objekte der Klasse MyWorld
*
*/
public MyWorld()
{
// Erstellt eine neue Welt mit 1200x900 Pixeln
super(1000, 700, 1);
prepare();
}
/**
* Bereite die Welt für den Programmstart vor.
* Das heißt: Erzeuge die Anfangs-Objekte und füge sie der Welt hinzu.
*/
private void prepare()
{
Balkendiagramm balkendiagramm = new Balkendiagramm();
addObject(balkendiagramm,500,350);
}
}

View file

@ -0,0 +1,699 @@
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.util.Vector;
import javax.imageio.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
import java.awt.geom.AffineTransform;
/**
*
* Bildklasse für die Simulation von Processing-Befehlen
*
* Diese Klasse stellt ein BufferedImage bereit, in das mit Processing-Befehlen gezeichnet
* werden kann.
* Zusätzlich kann ein Bildanzeiger über jede Änderung des Bildes informiert werden,
* um "Zurück"-Befehle zu ermöglichen. Der Bildanzeiger ist entweder eine normale Java
* ScrollPane oder ein Actor aus Greenfoot.
* Die Dokumentation der einzelnen Zeichenmethoden ist der Processing-Reference
* (https://processing.org/reference/ steht unter CC-Lizenz: https://creativecommons.org/)
* entnommen und mit Deepl.com ins Deutsche übersetzt.
*
* @version 1.0 from 23.01.2019
* @author Thomas Schaller (ZPG Informatik Klasse 9)
*/
public class Picture{
// Einstellungmöglichkeiten für das Zeichnen von Rechtecken und Ellipsen
// RADIUS = Mittelpunkt+Radius wird gegeben, CENTER = Mittelpunkt und Breite/Höhe wird gegeben,
// CORNER = Linke obere Ecke + Breite/Höhe, CORNERS = Linke obere und rechte untere Ecke
public static final int RADIUS = 1;
public static final int CENTER = 2;
public static final int CORNER = 3;
public static final int CORNERS = 4;
// gespeichertes Bild,
private BufferedImage image;
// aktuelle Farbeinstellungen
private Color background;
private Color pencolor;
private Color fillcolor;
// aktuelle Stiftdicke
private double stroke;
// akkteller Koordinatenmodus von Rechtecken und Ellipsen
private int ellipseMode = CENTER;
private int rectMode = CORNER;
// aktueller Font
private Font textfont = null;
// muss ein Bildanzeiger benachrichtigt werden
private PictureViewer observer = null;
private boolean autorefresh = true;
/**
* Erzeugt ein Bild mit Standardgröße 500x400
*/
public Picture() {
this(500,400);
}
/**
* Erzeugt ein Bild der angegeben Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public Picture(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein Bild aus einer Datei
* @param filename Dateiname des Bildes
*/
public Picture(String filename) {
load(filename);
}
/**
* Erzeugt ein Bild der angegebenen Größe mit festgelegtem Hintergrund
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds
*/
public Picture(int width, int height, String background) {
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
this.background = decode(background);
this.pencolor = new Color(0,0,0);
this.stroke = 1;
this.fillcolor = null;
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(this.background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Legt fest, wer das Bild anzeigt.
* Diese ermöglicht die Benachrichtung des Observers, wenn sich das Bild ändert.
* @param observer Anzeiger des Bildes
*/
public void setObserver(PictureViewer observer) {
this.observer= observer;
}
/**
* Direktes Setzen des Bildes (für interne Zwecke)
* @param b Bild, das gespeichert werden soll.
*/
public void setImage(BufferedImage b) {
image = b;
}
/**
* Direktes Abfragen des Bildes (für interne Zwecke)
* @return Bild, das gerade gespeichert ist.
*/
public BufferedImage getImage() {
return image;
}
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
pushImage();
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getWidth() {
return image.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getHeight() {
return image.getHeight();
}
/**
* Erzeugt eine Kopie des Bildes und übergibt sie an den Observer (falls existent), damit dieser die Versionen speichern kann
*/
private void pushImage() {
if(observer != null) {
observer.pushImage();
}
}
/**
* Legt fest, ob nach jedem Zeichenbefehl automatisch das Bild auch in
* der Oberfläche aktualisiert wird. Die Einstellung "false" beschleunigt
* das Zeichnen aufwändiger Bilder und verhindert "Flackern".
* Das Neuzeichnen kann durch die Methode "refresh" gezielt ausgelöst werden.
* @param autorefresh true = nach jedem Zeichenbefehl die Anzeige aktualisieren, false= nur durch die Methode refresh neu zeichnen
*/
public void setAutoRefresh(boolean autoRefresh) {
this.autorefresh = autoRefresh;
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
private void repaint() {
if(observer != null && autorefresh) {
observer.repaint();
}
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
public void refresh() {
if(observer != null) {
observer.repaint();
}
}
// ----------------------------------------- Zeichenfunktionen -----------------------------------------------
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
pushImage();
image = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,image.getWidth()-1, image.getHeight()-1);
repaint();
}
/**
* Konvertiert die in einem bestimmten Modus gegebenen Koordinaten in die Java-übliche Links_Oben_Breite_Höhe Version
* Die Änderungen werden direkt im Array vorgenommen
* @param coord Array mit vier Koordinateneinträgen im gegebenen Modus
* @param mode Modus der Koordinaten (CORNER, CORNERS, RADIUS oder CENTER)
*/
private void convert(int[] coord, int mode) {
switch(mode) {
case CORNER: break;
case CORNERS: coord[2] -= coord[0]; coord[3] -= coord[1]; break;
case RADIUS: coord[2] *= 2; coord[3] *=2;
case CENTER: coord[0] -= coord[2]/2; coord[1] -= coord[3]/2;
}
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
rectMode = mode;
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
ellipseMode = mode;
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if (stroke > 0) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawLine(x1, y1, x2, y2);
}
repaint();
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, rectMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillRect(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawRect(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, ellipseMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillOval(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawOval(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
int px[] = {x1, x2, x3};
int py[] = {y1, y2, y3};
polygon(px, py);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
int px[] = {x1, x2, x3, x4};
int py[] = {y1, y2, y3, y4};
polygon(px, py);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillPolygon(x,y, y.length);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawPolygon(x, y, x.length);
}
repaint();
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
ellipse(x,y,1, 1);
}
// ----------------------------------------- Schriftdarstellung -----------------------------------------------
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param s Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String s, int x, int y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(pencolor != null) {
g.setColor(fillcolor);
g.setStroke(new BasicStroke((float) stroke));
g.setFont(textfont);
g.drawString(s, x, y);
}
repaint();
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
this.textfont = font;
}
// ----------------------------------------- Farbfestlegungen -----------------------------------------------
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(String color) {
try{
return new Color(
Integer.valueOf( color.substring( 0, 2 ), 16 ),
Integer.valueOf( color.substring( 2, 4 ), 16 ),
Integer.valueOf( color.substring( 4, 6 ), 16 ) );
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(int color) {
try{
if(color >=0 && color < 256) {
return new Color(color,color,color);
} else {
int r = color / 0x010000 % 0xFF;
int g = color / 0x000100 % 0xFF;
int b = color % 0xFF;
System.out.println(""+r+","+g+","+b);
return new Color(r, g, b );
}
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
this.pencolor = decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
this.pencolor=decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
this.pencolor = new Color(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
this.pencolor = null;
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
this.stroke = width;
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
this.fillcolor = decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
this.fillcolor=decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
this.fillcolor = new Color(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
this.fillcolor = null;
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
if(c < 256) {
this.background=new Color(c,c,c);
} else {
int r = c / 0x010000;
int g = c / 0x000100 % 0xFF;
int b = c % 0xFF;
this.background= new Color(r, g, b );
}
this.clear();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
this.background=new Color(r,g,b);
this.clear();
}
// ----------------------------------------- Dateioperationen -----------------------------------------------
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
try{
this.image = ImageIO.read(new File(filename));
this.background = decode("D0D0D0");
this.pencolor = new Color(0,0,0);
this.fillcolor = null;
this.stroke = 1;
this.repaint();
} catch(Exception e) {
System.out.println("Fehler beim Einlesen der Bilddatei");
}
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
try{
String[] fn = filename.split("\\.");
if (fn.length== 1) {
ImageIO.write(image, "PNG", new File(filename+".png"));
} else {
if (fn.length == 2 && (fn[1].toUpperCase().equals("PNG") ||
fn[1].toUpperCase().equals("GIF"))){
ImageIO.write(image, fn[1], new File(filename));
}else {
System.out.println("Unbekanntes Bildformat");
}
}
} catch(Exception e) {
System.out.println("Fehler beim Speichern");
}
}
// ----------------------------------------- Sonstiges -----------------------------------------------
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
Color[][] pixel = new Color[image.getWidth()][image.getHeight()];
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
pixel[x][y] = new java.awt.Color(image.getRGB(x,y));
}
}
return pixel;
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
size(pixel.length,pixel[0].length);
Graphics2D g = (Graphics2D) image.getGraphics();
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
g.setColor(pixel[x][y]);
g.fillRect(x, y, 1, 1);
}
}
repaint();
}
/**
* Hilfsfunktion zum Verzögern der Ausgabe
* @param millis Wartezeit in Millisekunden
*/
public void delay(int millis) {
try{
Thread.sleep(millis);
} catch(Exception e) {
}
}
}

View file

@ -0,0 +1,499 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.awt.Font;
import java.util.Vector;
import java.awt.Color;
import javax.imageio.*;
import java.io.*;
/**
* Der PictureViewer ist ein Actor, der in der Lage ist ein
* Objekt der Klasse Picture anzuzeigen. Zusätzlich können
* mehrere Verarbeitungsschritte gespeichert werden, um ein
* "zurück"-Funktion zu ermöglichen.
*
* @author Thomas Schaller
* @version V1.0 vom 10.02.2019
*/
public class PictureViewer extends Actor
{
public static final int FIT = -1;
public static final int NORMAL = 1;
private static final int ANZ_BACK = 0;
private double zoom;
protected Picture picture = null;
private Vector<BufferedImage> history;
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der Größe 500x400
*/
public PictureViewer() {
this(500,400);
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public PictureViewer(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds als HEX-String (z.B. "FF3A45")
*/
public PictureViewer(int width, int height, String background) {
picture = new Picture(width,height, background);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild aus einer Bilddatei
* @param filename Name des Bildes
*/
public PictureViewer(String filename) {
picture = new Picture(filename);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Speichert das übergebene Bild in der History.
* @param b zu speicherndes Bild
*/
public void pushImage() {
if( this.ANZ_BACK > 0) {
if(history.size() == this.ANZ_BACK) {
history.removeElementAt(0);
}
BufferedImage b = new BufferedImage(picture.getWidth(), picture.getHeight(), picture.getImage().getType());
Graphics g = b.getGraphics();
g.drawImage(picture.getImage(), 0, 0, null);
g.dispose();
history.add(b);
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
private void popImage() {
int anz = history.size();
if(anz>0) {
BufferedImage i = history.get(anz-1);
history.removeElementAt(anz-1);
picture.setImage(i);
repaint();
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
public void back() {
popImage();
}
/**
* Setzt den Zoom-Faktor für das Bild.
* Als Zoomfaktor sind auch die Konstanten Bildanzeiger.FIT (auf Bildschirmgröße zoomen) und Bildanzeiger.NORMAL (100%) möglich.
* @param factor Zoomfaktor (1.0 = 100%).
*/
public void setZoom(double zoom) {
this.zoom = zoom;
repaint();
}
/**
* Setzt die automatische Neuanzeige des Bildes.
* Mit dieser Methode kann man einstellen, ob nach jedem Zeichenbefehl
* die Anzeige auf dem Bildschirm aktualisiert werden soll. Bei sehr
* vielen Zeichenbefehlen wird die Ausgabe dadurch sehr langsam. Es reicht
* eine Anzeige am Ende der Zeichenbefehle. Rufen Sie dann für das Neuzeichnen
* die Methode refresh() auf.
* @param autoRefresh true, wenn nach jedem Zeichenbefehl die Anzeige aktualisiert werden soll.
*/
public void setAutoRefresh(boolean autoRefresh) {
picture.setAutoRefresh(autoRefresh);
}
/**
* Sorgt für die Aktualisierung der Bildschrimanzeige. Das aktuelle Bild
* wird dadurch angezeigt. Durch Einstellung von autoRefresh kann die
* Anzeige automatisiert werden.
*/
public void refresh() {
repaint();
}
/**
* Setzt das angezeigt Bild neu und beachtet dabei den Zoomfaktor.
*/
public void repaint() {
double faktor = zoom;
if (zoom == FIT) {
double faktorw = (double) this.getWorld().getWidth() / picture.getWidth();
double faktorh = (double) this.getWorld().getHeight() / picture.getHeight();
faktor = Math.min(faktorw, faktorh);
}
int gfi_width = (int) (picture.getWidth()*faktor);
int gfi_height = (int) (picture.getHeight()*faktor);
setImage(new GreenfootImage(gfi_width, gfi_height));
Graphics2D g = (Graphics2D) this.getImage().getAwtImage().getGraphics();
g.drawImage(picture.getImage(),0,0,gfi_width, gfi_height, 0, 0, picture.getWidth(), picture.getHeight(), null);
g.setColor(new java.awt.Color(0,0,0));
g.setStroke(new BasicStroke((float) 1));
g.drawRect(0,0,gfi_width-1, gfi_height-1);
}
// Wrappermethoden
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
picture.size(width, height);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getImageWidth() {
return picture.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getImageHeight() {
return picture.getHeight();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
picture.background(c);
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
picture.background(r,g,b);
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
picture.line(x1,y1,x2,y2);
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
picture.rect(a,b,c,d);
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
picture.ellipse(a,b,c,d);
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
picture.triangle(x1,y1,x2,y2,x3,y3);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
picture.quad(x1,y1,x2,y2,x3,y3,x4,y4);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
picture.polygon(x,y);
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
picture.point(x,y);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
picture.rectMode(mode);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
picture.ellipseMode(mode);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
picture.stroke(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
picture.noStroke();
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
picture.strokeWeight(width);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
picture.fill(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
picture.noFill();
}
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
picture.clear();
}
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
picture.load(filename);
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
picture.save(filename);
}
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param t Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String t, int x, int y) {
picture.text(t,x,y);
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
picture.textFont(font);
}
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
return picture.getPixelArray();
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
picture.setPixelArray(pixel);
}
}

View file

@ -0,0 +1,14 @@
------------------------------------------------------------------------
Dies ist die README-Datei des Projekts. Hier sollten Sie Ihr Projekt
beschreiben.
Erzählen Sie dem Leser (jemand, der nichts über dieses Projekt weiss),
alles, was er/sie wissen muss. Üblicherweise sollte der Kommentar
zumindest die folgenden Angaben umfassen:
------------------------------------------------------------------------
PROJEKTBEZEICHNUNG:
PROJEKTZWECK:
VERSION oder DATUM:
WIE IST DAS PROJEKT ZU STARTEN:
AUTOR(EN):
BENUTZERHINWEISE:

View file

@ -0,0 +1,894 @@
/**
* Die Klasse Table vereinfacht den Zugriff auf CSV-Dateien.
* Die Klassen Table und TableRow ermöglichen einen einfachen Zugriff auf tabellenbasierte
* Dokumente.
*
* @author Thomas Schaller
* @version 1.0 vom 01.02.2019
*/
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.util.Scanner;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
public class Table
{
// Standardtrennzeichen für Spalten
private static final char DEFAULT_SEPARATOR = ';';
// Standardmarkierung für Texte
private static final char DEFAULT_QUOTE = '"';
// Standardtrennzeichen für Dezimalzahlen
private static final char DEFAULT_COMMA = ',';
// mögliche Spaltentypen
private static final String UNKNOWN ="UNKOWN";
private static final String INT = "INTEGER";
private static final String DOUBLE = "DOUBLE";
private static final String FLOAT = "FLOAT";
// interne Verwaltung des Dokuments als JDOM-Document-Objekt
private Document doc;
// Verweis auf Element für Kopfzeile
private Element header;
// Ende Attribute
/**
* Erzeugt leeres Tabellen-Dokument.
*/
public Table() {
this.doc = new Document();
doc.setRootElement(new Element("CSV-Data"));
this.header = new Element("Header");
doc.getRootElement().addContent(header);
}
/**
* Erzeugt Tabellen-Dokument aus einer CSV-Datei.
* Liest den Inhalt einer Datei und erstellt ein Tabellenobjekt mit seinen Werten.
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
* @param separator Trennzeichen für Spalten (meist ';' oder ',' oder '\t' für Tab)
* @param quote Kennung für Texte (meist '"').
*/
public Table(String filename, String options, char separator, char quote) {
loadCSV(filename, options, separator, quote);
}
/**
* Erzeugt Tabellen-Dokument aus einer CSV-Datei.
* Liest den Inhalt einer Datei und erstellt ein Tabellenobjekt mit seinen Werten (Separator = ';', Kennung für Text = '"').
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
*/
public Table(String filename, String options) {
loadCSV(filename, options);
}
/**
* Erzeugt Tabellen-Dokument aus einer CSV-Datei.
* Liest den Inhalt einer Datei ohne Kopfzeile und erstellt ein Tabellenobjekt mit seinen Werten (Separator = ';', Kennung für Text = '"').
* @param filename Dateiname der CSV-Datei.
*/
public Table(String filename) {
loadCSV(filename);
}
// Anfang Methoden
/**
* Liest den Inhalt einer CSV-Datei ohne Kopfzeile (Separator = ';', Kennung für Text = '"').
* @param filename Dateiname der CSV-Datei.
*/
public void loadCSV(String filename) {
loadCSV(filename, "");
}
/**
* Liest den Inhalt einer CSV-Datei (Separator = ';', Kennung für Text = '"').
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
*/
public void loadCSV(String filename, String options) {
loadCSV(filename, options, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
}
/**
* Liest den Inhalt einer CSV-Datei.
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
* @param separator Trennzeichen für Spalten (meist ';' oder ',' oder '\t' für Tab)
* @param quote Kennung für Texte (meist '"').
*/
public void loadCSV(String filename, String options, char separator, char quote) {
doc = new Document();
doc.setRootElement(new Element("CSV-Data"));
header = new Element("Header");
doc.getRootElement().addContent(header);
try {
File f = new File(filename);
Scanner scanner = new Scanner(new File(filename));
if(options.toLowerCase().contains("header") && scanner.hasNext()) {
List<String> entries = parseLine(scanner.nextLine(), separator, quote);
int i= 0;
for(String s : entries) {
Element entry = new Element("Column");
header.addContent(entry);
entry.setText(s);
entry.setAttribute("type", "unknown");
i++;
}
}
List<Element> cols = header.getChildren();
while (scanner.hasNext()) {
Element line = new Element("Row");
doc.getRootElement().addContent(line);
List<String> entries = parseLine(scanner.nextLine(), separator, quote);
int i= 0;
for(String s : entries) {
if(i==cols.size()) {
Element entry = new Element("Column");
entry.setAttribute("type", "unknown");
header.addContent(entry);
cols = header.getChildren();
}
Element entry = new Element("Entry");
entry.setText(s);
line.addContent(entry);
i++;
}
}
scanner.close();
} catch (Exception e) {
System.out.println("Fehler beim Lesen der CSV-Datei");
}
}
/**
* Speichert das aktuelle Dokument als CSV-Datei ohne Kopfzeile (Separator = ';', Kennung für Text = '"').
* @param filename Dateiname der CSV-Datei.
*/
public void saveCSV(String filename) {
saveCSV(filename, "");
}
/**
* Speichert das aktuelle Dokument als CSV-Datei (Separator = ';', Kennung für Text = '"').
* Wenn die Datei eine Kopfzeile enthalten, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile haben soll,
* dann lassen Sie einfach die Option "header" weg.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile haben soll.
* @param filename Dateiname der CSV-Datei.
*/
public void saveCSV(String filename, String options) {
saveCSV(filename, options, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
}
/**
* Speichert das aktuelle Dokument als CSV-Datei.
* Wenn die Datei eine Kopfzeile enthalten, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile haben soll,
* dann lassen Sie einfach die Option "header" weg.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile haben soll.
* @param filename Dateiname der CSV-Datei.
* @param separator Trennzeichen für Spalten (meist ';' oder ',' oder '\t' für Tab)
* @param quote Kennung für Texte (meist '"').
*/
public void saveCSV(String filename, String options, char separator, char quote){
try{
File f = new File(filename);
PrintStream outputFile = new PrintStream (f);
System.out.println("Speicher in : "+f.getAbsolutePath());
List<Element> columns = header.getChildren();
String sq = ""+quote;
String ss = ""+separator;
if(quote =='"') sq = "\"";
if(separator =='"') ss = "\"";
if(options.toLowerCase().contains("header")) {
String h = "";
for(Element c : columns) {
h += ss + sq + c.getText()+sq;
}
outputFile.println(h.substring(1));
}
for(int i = 0; i<getRowCount(); i++) {
String l = "";
for(String s: getStringRow(i)) {
if(s.contains(""+separator)) {
if(quote == '"' && s.contains("\"")) {
s = s.replace("\"","\"\"");
}
l += ss + sq + s+sq;
} else {
l += ss+s;
}
}
outputFile.println(l.substring(1));
}
outputFile.close();
}
catch(Exception e) {
System.out.println("Fehler beim Schreiben der Datei");
}
}
/** Speichert die Tabelle als XML-Dokument.
* @param filename Dateiname des XML-Files
*/
public void saveXML(String filename) {
try {
// new XMLOutputter().output(doc, System.out);
XMLOutputter xmlOutput = new XMLOutputter();
// display nice nice
xmlOutput.setFormat(Format.getPrettyFormat());
File f = new File(filename);
FileOutputStream outputFile = new FileOutputStream(f);
System.out.println("Speicher in : "+f.getAbsolutePath() );
xmlOutput.output(doc, outputFile);
outputFile.close();
System.out.println("File Saved!");
} catch (IOException io) {
System.out.println(io.getMessage());
}
}
//----------------------------------------------- Zeigerbewegungen --------------------------------------------------
/** HIlfsfunktion für die Analyse einer Dateizeile
* @param cvsLine Zeile aus der Datei
* @return Liste von String für die einzelnen Spalten
*/
private List<String> parseLine(String cvsLine) {
return parseLine(cvsLine, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
}
/** HIlfsfunktion für die Analyse einer Dateizeile
* @param cvsLine Zeile aus der Datei
* @param sparator Trennzeichen für die Spalten
* @return Liste von String für die einzelnen Spalten
*/
private List<String> parseLine(String cvsLine, char separator) {
return parseLine(cvsLine, separator, DEFAULT_QUOTE);
}
/** HIlfsfunktion für die Analyse einer Dateizeile
* @param cvsLine Zeile aus der Datei
* @param sparator Trennzeichen für die Spalten
* @param customQuote Kennung für Strings
* @return Liste von String für die einzelnen Spalten
*/
private List<String> parseLine(String cvsLine, char separator, char customQuote) {
List<String> result = new ArrayList<>();
//if empty, return!
if (cvsLine == null && cvsLine.isEmpty()) {
return result;
}
//ggf. Default-Value laden
if (customQuote == ' ') {
customQuote = DEFAULT_QUOTE;
}
if (separator == ' ') {
separator = DEFAULT_SEPARATOR;
}
StringBuffer curVal = new StringBuffer();
boolean inQuotes = false;
boolean startCollectChar = false;
boolean doubleQuotesInColumn = false;
char[] chars = cvsLine.toCharArray();
for (char ch : chars) {
if (inQuotes) { // aktueller Text ist in Quotes eingeschlossen
startCollectChar = true;
if (ch == customQuote) { // Quotes werden beendet, aber Achtung bei "" => Metazeichen
inQuotes = false;
if (ch == '\"') {
doubleQuotesInColumn = true;
}
} else {
if (ch == '\"' && !doubleQuotesInColumn) {
doubleQuotesInColumn = true;
} else {
curVal.append(ch);
doubleQuotesInColumn = false;
}
}
} else {
if (ch == customQuote) {
inQuotes = true;
//Fixed : allow "" in empty quote enclosed
if (ch == '\"'){
if(doubleQuotesInColumn) {
curVal.append('"');
doubleQuotesInColumn = false;
} else doubleQuotesInColumn = true;
}
}
else {
doubleQuotesInColumn = false;
if (ch == separator) {
result.add(curVal.toString());
curVal = new StringBuffer();
startCollectChar = false;
} else if (ch == '\r') {
//ignore LF characters
continue;
} else if (ch == '\n') {
//the end, break!
break;
} else {
curVal.append(ch);
}
}
}
}
result.add(curVal.toString());
return result;
}
/**
* Sucht die Nummer einer durch Namen gegebenen Spalte.
* @param name Name der Spalte
* @return Nummer der Spalte
*/
private int findColumnNumber(String name) {
List<Element> columns = header.getChildren();
int i = 0;
for(Element c : columns) {
if (c.getText().toLowerCase().equals(name.toLowerCase())) {
return i;
}
i++;
}
return -1;
}
/**
* Fügt eine neue Spalte am Ende der Tabelle an.
*/
public void addColumn() {
Element entry = new Element("Column");
entry.setAttribute("type", Table.UNKNOWN);
header.addContent(entry);
}
/**
* Fügt eine neue Spalte am Ende der Tabelle an und benennt sie.
* @param title Bezeichnung der Spalte
*/
public void addColumn(String title) {
addColumn();
Element nc = ((List<Element>)(header.getChildren())).get(header.getChildren().size()-1);
nc.setText(title);
}
/**
* Fügt eine neue Spalte am Ende der Tabelle an und benennt und typisiert sie.
* @param title Bezeichnung der Spalte
* @param type Typ der Spalte (UNKNOWN, DOUBLE, INTEGER, FLOAT)
*/
public void addColumn(String title, String type) {
addColumn(title);
Element nc = ((List<Element>)(header.getChildren())).get(header.getChildren().size()-1);
nc.setAttribute("type", type);
}
/**
* Löscht eine Spalte.
* @param i Nummer der Spalte.
*/
public void removeColumn(int i) {
List<Element> lines = doc.getRootElement().getChildren();
for(Element l : lines) {
if(l.getChildren().size()>i) l.removeContent(i);
}
}
/**
* Löscht eine Spalte
* @param name Name der Spalte
*/
public void removeColumn(String name) {
try{
removeColumn(findColumnNumber(name));
} catch(Exception e) { System.out.println("Unbekannter Spaltenname");}
}
/**
* Liefert die Anzahl der Spalten in der Tabelle
* @return Anzahl der Spalten
*/
public int getColumnCount() {
return header.getChildren().size();
}
/**
* Liefert die Anzahl der Zeilen in der Tabelle
* @return Anzahl der Zeilen
*/
public int getRowCount() {
return doc.getRootElement().getChildren().size()-1;
}
/**
* Löscht alle Zeilen der Tabelle.
* Die Spaltenüberschriften und Typen bleiben erhalten.
*/
public void clearRows() {
doc.getRootElement().removeChildren("Row");
}
/**
* Fügt eine neue Zeile an das Ende der Tabelle an.
* @return ein TableRow-Objekt für diese neue Zeile
*/
public TableRow addRow() {
Element row = new Element("Row");
doc.getRootElement().addContent(row);
return new TableRow(doc, row);
}
/**
* Löscht eine Zeile
* @param i Nummer der Zeile
*/
public void removeRow(int i) {
if(i<getRowCount()) {
doc.getRootElement().removeContent(i);
}
}
/**
* Liefert eine Zeile der Tabelle
* @param i Nummer der Zeile
* @return TableRow-Objekt für diese Zeile
*/
public TableRow getRow(int i) {
if(i<getRowCount()) {
List<Element> rows = doc.getRootElement().getChildren();
return new TableRow(doc, rows.get(i+1));
}
return null;
}
/**
* Liefert die ganze Tabelle als Array von TableRow-Objekten
* @return Array von TableRow-Objekten
*/
public TableRow[] rows() {
TableRow[] rows = new TableRow[getRowCount()];
for(int i = 0; i < getRowCount(); i++) {
rows[i] = getRow(i);
}
return rows;
}
/**
* Liefert den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public int getInt(int row, int column) {
return getRow(row).getInt(column);
}
/**
* Liefert den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public int getInt(int row, String name) {
return getRow(row).getInt(name);
}
/**
* Setzt den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @param value neuer Wert der Zelle
*/
public void setInt(int row, int column,int value) {
getRow(row).setInt(column, value);
}
/**
* Setzt den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setInt(int row, String name, int value) {
getRow(row).setInt(name, value);
}
/**
* Liefert alle Werte einer Zeile als Integer-Array.
* @param row Nummer der Zeile
* @return int-Array, dass alle Werte der Zeile enthält
*/
public int[] getIntRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
int[] r = new int[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getInt(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Integer-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public int[] getIntColumn(int column) {
try{
int anz = getRowCount();
int[] r = new int[anz];
for(int i=0; i<anz; i++) {
r[i] = getInt(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Integer-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public int[] getIntColumn(String name) {
return getIntColumn(findColumnNumber(name));
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public float getFloat(int row, int column) {
return getRow(row).getFloat(column);
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public float getFloat(int row, String name) {
return getRow(row).getFloat(name);
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @param value neuer Wert der Zelle
*/
public void setFloat(int row, int column,float value) {
getRow(row).setFloat(column, value);
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setFloat(int row, String name, float value) {
getRow(row).setFloat(name, value);
}
/**
* Liefert alle Werte einer Zeile als Float-Array.
* @param row Nummer der Zeile
* @return int-Array, dass alle Werte der Zeile enthält
*/
public float[] getFloatRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
float[] r = new float[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getFloat(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Float-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public float[] getFloatColumn(int column) {
try{
int anz = getRowCount();
float[] r = new float[anz];
for(int i=0; i<anz; i++) {
r[i] = getFloat(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Float-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public float[] getFloatColumn(String name) {
return getFloatColumn(findColumnNumber(name));
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public double getDouble(int row, int column) {
return getRow(row).getDouble(column);
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public double getDouble(int row, String name) {
return getRow(row).getDouble(name);
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @param value neuer Wert der Zelle
*/
public void setDouble(int row, int column,double value) {
getRow(row).setDouble(column, value);
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setDouble(int row, String name, double value) {
getRow(row).setDouble(name, value);
}
/**
* Liefert alle Werte einer Spalte als Double-Array.
* @param row Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public double[] getDoubleRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
double[] r = new double[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getDouble(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Double-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public double[] getDoubleColumn(int column) {
try{
int anz = getRowCount();
double[] r = new double[anz];
for(int i=0; i<anz; i++) {
r[i] = getDouble(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Double-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public double[] getDoubleColumn(String name) {
return getDoubleColumn(findColumnNumber(name));
}
/**
* Liefert den Wert einer Zelle als String
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public String getString(int row, int column) {
return getRow(row).getString(column);
}
/**
* Liefert den Wert einer Zelle als String
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public String getString(int row, String name) {
return getRow(row).getString(name);
}
/**
* Setzt den Wert einer Zelle als String
* @param row Zeilennummer
* @param column Spaltennummer
* @param text neuer Wert der Zelle
*/
public void setString(int row, int column,String text) {
getRow(row).setString(column, text);
}
/**
* Setzt den Wert einer Zelle als String
* @param row Zeilennummer
* @param name Name der Spalte
* @param text neuer Wert der Zelle
*/
public void setString(int row, String name, String text) {
getRow(row).setString(name, text);
}
/**
* Liefert alle Werte einer Spalte als String-Array.
* @param row Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public String[] getStringRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
String[] r = new String[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getString(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als String-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public String[] getStringColumn(int column) {
try{
int anz = getRowCount();
String[] r = new String[anz];
for(int i=0; i<anz; i++) {
r[i] = getString(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als String-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public String[] getStringColumn(String name) {
return getStringColumn(findColumnNumber(name));
}
/**
* Sucht nach einem bestimmtem Wert in einer Zeile.
* @param value Wert der gesucht werden soll
* @param column Nummer der Spalte, die durchsucht werden soll
* @return TableRow-Objekt der Zeile, wenn der Wert gefunden wurde, sonst null
*/
public TableRow findRow(String value, int column) {
for(int i=0; i<getRowCount(); i++) {
if(getString(i,column).equals(value)){
return getRow(i);
}
}
return null;
}
/**
* Sucht nach einem bestimmtem Wert in einer Zeile.
* @param value Wert der gesucht werden soll
* @param name Name der Spalte, die durchsucht werden soll
* @return TableRow-Objekt der Zeile, wenn der Wert gefunden wurde, sonst null
*/
public TableRow findRow(String value, String name) {
return findRow(value, findColumnNumber(name));
}
/**
* Kürzt alle Einträge der Tabelle um unnötige Leerzeichen am Anfang oder Ende
*/
public void trim() {
for(int y=0; y<getRowCount(); y++) {
for (int x =0; x<getColumnCount(); x++) {
setString(y,x,getString(y,x).trim());
}
}
}
}

View file

@ -0,0 +1,312 @@
/**
* Repräsentiert eine Zeile eines Table-Objekts.
* Erlaubt einen einfachen Zugriff auf die einzelnen Einträge in dieser Zeile.
*
* @author Thomas Schaller
* @version V1.0 vom 01.02.2019
*/
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.util.Scanner;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
import java.text.NumberFormat;
public class TableRow
{
// Verweis auf das ganze Dokument
private Document doc;
// Verweis auf die Zeile, für die dieses Objekt steht
private Element current;
// Verweis auf die Kopfzeile
private Element header;
// Für die Interpretation von Zahlenwerten
NumberFormat format = NumberFormat.getInstance();
// Ende Attribute
/**
* Erzeugt ein TableRow-Objekt.
* Diese Methode ist für den internen Gebraucht. Einige Methode der Table-Klasse erzeugen mit diesem Konstruktor TableRow-Objekte.
* @param doc JDOM-Dokument, das für die ganze Tabelle steht.
* @param row JDOM-Element, das für die aktuelle Zeile steht.
*/
public TableRow(Document doc, Element row) {
this.doc = doc;
this.current = row;
this.header = doc.getRootElement().getChild("Header");
}
/**
* Liefert die Anzahl der Spalten der Zeile.
* @return Anzahl der Spalten
*/
public int getColumnCount() {
return header.getChildren().size();
}
/**
* Liefert den Titel einer Spalte
* @param i Nummer der Spalte
* @return Name der Spalte
*/
public String getColumnTitle(int i) {
if(i< getColumnCount()) {
return ((List<Element>) (header.getChildren())).get(i).getText();
} else {
return "";
}
}
/**
* Liefert die Nummer einer Spalte
* @param name Name der Spalte
* @return Nummer der Spalte
*/
public int getColumn(String name) {
List<Element> columns = header.getChildren();
int i = 0;
while (i < columns.size()) {
if (columns.get(i).getText().toLowerCase().equals(name.toLowerCase())) {
return i;
}
i++;
} // end of while
return -1;
}
/**
* Erzeugt eine neue Zeile mit i Spalten
* Wenn bisher nicht genügend Spalten vorhanden sind, werden automatisch neue Spalten hinzugefügt (auch zum Header)
* @param i Anzahl der Spalten
*/
private Element buildRow(int i) {
List<Element> columns = header.getChildren();
Element entry=null;
for(int j=0; j<=i; j++) {
if(j==columns.size()) {
Element h = new Element("Column");
h.setAttribute("type", "unknown");
header.addContent(h);
columns = header.getChildren();
}
if(j==current.getChildren().size()) {
entry = new Element("Entry");
current.addContent(entry);
}
}
return entry;
}
/**
* Erzeugt eine neue Zeile.
* Es werden genügend Spalten erzeugt, dass ein Wert in Spalte "name" eingetragen werden kann
* @param name Name der Spalte
*/
private Element buildRow(String name) {
List<Element> columns = header.getChildren();
int i = 0;
for(Element c: columns) {
if(c.getText().toLowerCase().equals(name.toLowerCase())) {
return buildRow(i);
}
i++;
}
return null;
}
/**
* Liefert den Wert einer Zelle als String
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public String getString(int i) {
if(i >= current.getContent().size()) return "";
Element e = (Element) current.getContent(i) ;
if(e!=null) {
return e.getText();
} else {
return "";
}
}
/**
* Liefert den Wert einer Zelle als String
* @param name Name der Spalte
* @return Wert der Zelle
*/
public String getString(String name) {
return getString(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als String
* @param i Nummer der Spalte
* @param text neuer Wert der Zelle
*/
public void setString(int i, String text) {
Element e = buildRow(i);
if(e!=null) e.setText(text);
}
/**
* Setzt den Wert einer Zelle als String
* @param name Name der Spalte
* @param text neuer Wert der Zelle
*/
public void setString(String name, String text) {
Element e = buildRow(name);
if(e!=null) e.setText(text);
}
/**
* Liefert den Wert einer Zelle als Int-Zahl
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public int getInt(int i) {
try{
Element e = (Element) current.getContent(i) ;
return Integer.parseInt(e.getText());
} catch(Exception e) {
return 0;
}
}
/**
* Liefert den Wert einer Zelle als Int-Zahl
* @param name Name der Spalte
* @return Wert der Zelle
*/
public int getInt(String name) {
return getInt(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als Int-Zahl
* @param i Nummer der Spalte
* @param value neuer Wert der Zelle
*/
public void setInt(int i,int value) {
Element e = buildRow(i);
if(e!=null) e.setText(""+value);
}
/**
* Setzt den Wert einer Zelle als Int-Zahl
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setInt(String name, int value) {
Element e = buildRow(name);
if(e!=null) e.setText(""+value);
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public float getFloat(int i) {
try{
Element e = (Element) current.getContent(i) ;
return Float.parseFloat(e.getText().replace(",","."));
} catch(Exception e) {
return 0;
}
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param name Name der Spalte
* @return Wert der Zelle
*/
public float getFloat(String name) {
return getFloat(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param i Nummer der Spalte
* @param value neuer Wert der Zelle
*/
public void setFloat(int i,float value) {
Element e = buildRow(i);
if(e!=null) e.setText(format.format(value));
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setFloat(String name, float value) {
Element e = buildRow(name);
if(e!=null) e.setText(format.format(value));
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public double getDouble(int i) {
try{
Element e = (Element) current.getContent(i) ;
return Double.parseDouble(e.getText().replace(",","."));
} catch(Exception e) {
return 0;
}
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param name Name der Spalte
* @return Wert der Zelle
*/
public double getDouble(String name) {
return getDouble(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param i Nummer der Spalte
* @param value neuer Wert der Zelle
*/
public void setDouble(int i,double value) {
Element e = buildRow(i);
if(e!=null) e.setText(format.format(value));
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setDouble(String name, double value) {
Element e = buildRow(name);
if(e!=null) e.setText(format.format(value));
}
}

View file

@ -0,0 +1,637 @@
/**
* Klasse zum Vereinfachten Zugriff auf XML-Dokumente
* Diese Klasse ist für den Einsatz in der Schule gedacht und soll den Schülern
* einen einfachen Zugriff auf XML-Dokumente ermöglichen. Die zur Verfügung
* stehenden Befehle sind wie in Processing realisiert.
* Dabei ist jeder Teilbaum des Dokuments wieder als XML-Objekt zugreifbar, das
* intern auf die gleiche XML-Dokumentstruktur zugreift.
* Dies ermöglicht bei unsachgemäßem Gebrauch die XML-Struktur zu zerstören. Im
* normalen Gebrauch sollte dies aber nicht relevant sein.
*
* Benötigt: jdom-1.1.3.jar
* @author Thomas Schaller
* @version 1.0 vom 31.01.2019
*/
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
public class XML {
// Anfang Attribute
// XML-Dokumentstruktur
private Document doc;
// Zeiger auf das aktuelle Element
private Element current;
// Ende Attribute
/**
* Erzeugt ein leeres XMLDokument
*/
public XML() {
this.doc = new Document();
this.current = null;
}
/**
* Erzeugt ein XML-Dokument aus einer Datei
* @param filename Dateiname der XML-Datei
*/
public XML(String filename) {
loadXML(filename);
}
/**
* interner Konstruktor, um ein XML Objekt zu erzeugen, das auf einen bestimmten Knoten verweist
* @param doc die XML-Dokumentstruktur
* @param current Zeiger auf das aktuelle Element
*/
private XML(Document doc, Element current) {
this.doc = doc;
this.current = current;
}
// Anfang Methoden
/** Öffnet das durch den Dateinamen gegebene Dokument
* @param filename Dateiname des XML-Files
*/
public void loadXML(String filename) {
doc = null;
File f = new File(filename);
try {
// Das Dokument erstellen
SAXBuilder builder = new SAXBuilder();
doc = builder.build(f);
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// Zeiger im Baum auf Root-Element
current = doc.getRootElement();
}
/** Speichert den XML-Baum im angegebenen Dateinamen
* @param filename Dateiname des XML-Files
*/
public void saveXML(String filename) {
try {
// new XMLOutputter().output(doc, System.out);
XMLOutputter xmlOutput = new XMLOutputter();
// display nice nice
xmlOutput.setFormat(Format.getPrettyFormat());
File f = new File(filename);
FileOutputStream outputFile = new FileOutputStream(f);
System.out.println("Speicher in : "+f.getAbsolutePath() );
xmlOutput.output(doc, outputFile);
outputFile.close();
System.out.println("File Saved!");
} catch (IOException io) {
System.out.println(io.getMessage());
}
}
//----------------------------------------------- Zeigerbewegungen --------------------------------------------------
/**
* liefert ein XML-Objekt, das auf den Vaterknoten des aktuellen Elements zeigt.
* @return Vater des aktuellen Objekts.
*/
public XML getParent() {
if(current != null) {
Element parent = current.getParentElement();
if (parent == null) {
return null;
} else {
return new XML(doc, parent);
}
}
return null;
}
/**
* Überprüft, ob das Element irgendwelche Kinder hat oder nicht, und gibt das Ergebnis als boolean zurück.
* @return true, wenn Kinder vorhanden sind, sonst false
*/
public boolean hasChildren() {
if (current == null) {
return doc.hasRootElement();
} else {
return current.getChildren().size()>0;
}
}
/**
* Ermittelt die Namen aller Kinder des Elements und gibt die Namen als ein Array von Strings zurück.
* Dies ist dasselbe wie das Durchlaufen und Aufrufen von getName() auf jedem untergeordneten Element einzeln.
* @return Liste aller Namen der Kinder
*/
public String[] listChildren() {
if (current == null) {
if(doc.hasRootElement()) {
String[] names = new String[0];
names[0] = doc.getRootElement().getName();
return names;
} else {
return null;
}
} else {
List<Element> ch_element = current.getChildren();
String[] names = new String[ch_element.size()];
for(int i=0; i < ch_element.size() ; i++) {
names[i] = ch_element.get(i).getName();
}
return names;
}
}
/**
* Liefert alle Kinder des Elements als Array von XML-Objekten.
* @return Array der Kinder als XML-Objekte
*/
public XML[] getChildren() {
if (current == null) {
if(doc.hasRootElement()) {
XML[] ch_xml = new XML[1];
ch_xml[0] = new XML(doc, doc.getRootElement());
return ch_xml;
} else {
return null;
}
} else {
List<Element> ch_element = current.getChildren();
XML[] ch_xml = new XML[ch_element.size()];
for(int i=0; i < ch_element.size() ; i++) {
ch_xml[i] = new XML(doc, ch_element.get(i));
}
return ch_xml;
}
}
/**
* Liefert bestimmte Kinder des Elements als Array von XML-Objekten.
* Die Methode gibt dabei alle Kinder zurück, die dem angegebenen Namen entsprechen.
* @param name Name der gesuchten Kind-Objekte
* @return Array der Kinder als XML-Objekte
*/
public XML[] getChildren(String name) {
if (current == null) {
if(doc.hasRootElement()) {
XML[] ch_xml = new XML[1];
ch_xml[0] = new XML(doc, doc.getRootElement());
if(doc.getRootElement().getName().equals(name)){
return ch_xml;
} else {
return null;
}
} else {
return null;
}
} else {
List<Element> ch_element = current.getChildren(name);
XML[] ch_xml = new XML[ch_element.size()];
for(int i=0; i < ch_element.size() ; i++) {
ch_xml[i] = new XML(doc, ch_element.get(i));
}
return ch_xml;
}
}
/**
* Liefert das erste Kind des Elements mit einem bestimmten Namen.
* Die Methode gibt das erste Kind zurück, das dem angegebenen Namen entsprechen.
* @param name Name des gesuchten Kind-Objektes
* @return Kind als XML-Objekt
*/
public XML getChild(String name) {
if (current == null) {
Element e = doc.getRootElement();
if (e.getName().equals(name)) {
return new XML(doc, e);
} else {
return null;
}
} else {
String[] names = name.split("/");
Element e = current;
int i = 0;
while(i < names.length) {
e = e.getChild(names[i]);
if (e==null) return null;
i++;
}
return new XML(doc, e);
}
}
/**
* Liefert das i. Kind des Elements.
* Die Methode gibt das i. Kind des aktuellen Elements zurück.
* @param i Nummer des Kindes
* @return Kind als XML-Objekt
*/
public XML getChild(int i) {
if (current == null) {
return new XML(doc, doc.getRootElement());
} else {
List<Element> ch_element = current.getChildren();
if (i>=ch_element.size()) return null;
return new XML(doc, ch_element.get(i));
}
}
//--------------------------------------------------- Methoden für das aktuelle Element -------------------------------------------------
/**
* Frage den Namen des aktuellen Elements ab
* @return Namen des Elements
*/
public String getName() {
if (current==null) return "";
return current.getName();
}
/**
* Setze den Namen des aktuellen Elements.
* @param name Neuer Name des Elements
*/
public void setName(String name) {
if (current==null) return;
current.setName(name);
}
/**
* liefert die Anzahl der Attribute eines Elements.
* @return Anzahl des Attribute
*/
public int getAttributeCount() {
if (current == null) return 0;
return current.getAttributes().size();
}
/**
* liefert zurück, ob das aktuelle Element Attribute hat .
* @return true, wenn es Attribute gibt
*/
public boolean hasAttribute() {
if (current == null) return false;
return current.getAttributes().size()>0;
}
/**
* Ruft alle Attribute des angegebenen Elements ab und gibt sie als Array von Strings zurück.
* @return Liste der Attributnamen
*/
public String[] listAttributes() {
if (current == null) return null;
List<Attribute> attr = current.getAttributes();
String[] names = new String[attr.size()];
for(int i=0; i < attr.size() ; i++) {
names[i] = attr.get(i).getName();
}
return names;
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs
*/
public String getString(String attribute) {
if (current==null) return "";
return current.getAttributeValue(attribute);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs
*/
public String getString(String attribute, String defaultValue) {
if (current==null) return defaultValue;
return current.getAttributeValue(attribute,defaultValue);
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param text neuer Wert des Attributs
*/
public void setString(String attribute, String text) {
if (current==null) return;
current.setAttribute(attribute, text);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs als Integer-Zahl
*/
public int getInt(String attribute) {
if (current==null) return 0;
try{
int i = Integer.parseInt(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return 0; }
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs als Integer-Zahl
*/
public int getInt(String attribute, int defaultValue) {
if (current==null) return defaultValue;
try{
int i = Integer.parseInt(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param value neuer Wert des Attributs
*/
public void setInt(String attribute, int value) {
if (current==null) return;
current.setAttribute(attribute, ""+value);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs als Float-Zahl
*/
public float getFloat(String attribute) {
if (current==null) return 0;
try{
float i = Float.parseFloat(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return 0; }
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs als Float-Zahl
*/
public float getFloat(String attribute, float defaultValue) {
if (current==null) return defaultValue;
try{
float i = Float.parseFloat(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param value neuer Wert des Attributs
*/
public void setFloat(String attribute, float value) {
if (current==null) return;
current.setAttribute(attribute, ""+value);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs als Double-Zahl
*/
public double getDouble(String attribute) {
if (current==null) return 0;
try{
double i = Double.parseDouble(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return 0; }
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs als double-Zahl
*/
public double getDouble(String attribute, double defaultValue) {
if (current==null) return defaultValue;
try{
double i = Double.parseDouble(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param value neuer Wert des Attributs
*/
public void setDouble(String attribute, double value) {
if (current==null) return;
current.setAttribute(attribute, ""+value);
}
/**
* Fragt den Inhalt/Text des aktuellen Elements ab
* @return Inhalt des Elements
*/
public String getContent() {
if ( current==null) return "";
return current.getText();
}
/**
* Fragt den Inhalt/Text des aktuellen Elements ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardtext
* @return Inhalt des Elements
*/
public String getContent(String defaultValue) {
if ( current==null) return defaultValue;
String t = current.getText();
if(t.equals("")) t = defaultValue;
return t;
}
/**
* Setzt den Inhalt/Text des aktuellen Elements
* @param text Neuer Inhalt des Elements
*/
public void setContent(String text) {
if ( current==null) return;
current.setText(text);
}
/**
* Fragt den Inhalt des aktuellen Elements als Integerzahl ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardwert
* @return Inhalt des Elements
*/ public int getIntContent(int defaultValue) {
if ( current==null) return defaultValue;
try{
int i = Integer.parseInt(current.getText());
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Fragt den Inhalt des aktuellen Elements als Integerzahl ab
* @return Inhalt des Elements
*/
public int getIntContent() {
if ( current==null) return 0;
try{
int i = Integer.parseInt(current.getText());
return i;
} catch(Exception e) { return 0; }
}
/**
* Setzt den Inhalt des aktuellen Elements
* @param value Neuer Inhalt des Elements
*/
public void setIntContent(int value) {
if ( current==null) return;
current.setText(""+value);
}
/**
* Fragt den Inhalt des aktuellen Elements als Floatzahl ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardwert
* @return Inhalt des Elements
*/
public float getFloatContent(float defaultValue) {
if ( current==null) return defaultValue;
try{
float i = Float.parseFloat(current.getText());
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Fragt den Inhalt des aktuellen Elements als Floatzahl ab
* @return Inhalt des Elements
*/
public float getFloatContent() {
if ( current==null) return 0;
try{
float i = Float.parseFloat(current.getText());
return i;
} catch(Exception e) { return 0; }
}
/**
* Setzt den Inhalt des aktuellen Elements
* @param value Neuer Inhalt des Elements
*/
public void setFloatContent(float value) {
if ( current==null) return;
current.setText(""+value);
}
/**
* Fragt den Inhalt des aktuellen Elements als Doublezahl ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardwert
* @return Inhalt des Elements
*/
public double getDoubleContent(double defaultValue) {
if ( current==null) return defaultValue;
try{
double i = Double.parseDouble(current.getText());
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Fragt den Inhalt des aktuellen Elements als Doublezahl ab
* @return Inhalt des Elements
*/
public double getDoubleContent() {
if ( current==null) return 0;
try{
double i = Double.parseDouble(current.getText());
return i;
} catch(Exception e) { return 0; }
}
/**
* Setzt den Inhalt des aktuellen Elements
* @param value Neuer Inhalt des Elements
*/
public void setDoubleContent(double value) {
if ( current==null) return;
current.setText(""+value);
}
// ----------------------------------------------- XML-Struktur aufbauen ------------------------------------------------
/** Erzeuge neues Element nach der aktuellen Position und setze dieses als aktuelles Element
* @param name Name des neuen Elements
* @return neues Element als XML-Objekt
*/
public XML addChild(String name) {
Element e = new Element(name);
if(current == null){ // man ist auf Root-Ebene
doc.setRootElement(e);
}
else {
current.addContent(e);
} // end of if-else
return new XML(doc, e);
}
/**
* liefert das aktuelle Element als jdom-Element-Objekt
* @return aktuelles Element
*/
private Element getCurrent() {
return current;
}
/**
* löscht ein Kind des aktuellen Knotens.
* Ist kid kein Kind des aktuellen Elements passiert gar nichts.
* @param kid XML-Objekt des Kindes
*/
public void removeChild(XML kid) {
if (current == null) return;
Element e = kid.getCurrent();
int index = current.indexOf(e);
if(index >= 0) { current.removeContent(e);}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -0,0 +1,108 @@
#Greenfoot project file
class.Balkendiagramm.image=balken.png
class.Balkendiagramm.superclass=PictureViewer
class.MyWorld.superclass=greenfoot.World
class.Picture.superclass=
class.PictureViewer.image=bilderrahmen.png
class.PictureViewer.superclass=greenfoot.Actor
class.Table.superclass=
class.TableRow.superclass=
class.XML.superclass=
dependency1.from=PictureViewer
dependency1.to=Picture
dependency1.type=UsesDependency
dependency2.from=Table
dependency2.to=TableRow
dependency2.type=UsesDependency
dependency3.from=Picture
dependency3.to=PictureViewer
dependency3.type=UsesDependency
dependency4.from=MyWorld
dependency4.to=Balkendiagramm
dependency4.type=UsesDependency
editor.fx.0.height=739
editor.fx.0.width=816
editor.fx.0.x=226
editor.fx.0.y=61
height=885
mainWindow.height=881
mainWindow.width=1318
mainWindow.x=40
mainWindow.y=40
package.numDependencies=4
package.numTargets=7
project.charset=UTF-8
publish.hasSource=false
publish.locked=true
publish.longDesc=
publish.shortDesc=
publish.tags=
publish.title=
publish.url=
readme.height=58
readme.name=@README
readme.width=47
readme.x=10
readme.y=10
simulation.speed=97
target1.height=50
target1.name=PictureViewer
target1.showInterface=false
target1.type=ClassTarget
target1.typeParameters=
target1.width=100
target1.x=0
target1.y=0
target2.height=50
target2.name=Table
target2.showInterface=false
target2.type=ClassTarget
target2.typeParameters=
target2.width=80
target2.x=0
target2.y=0
target3.height=50
target3.name=Balkendiagramm
target3.showInterface=false
target3.type=ClassTarget
target3.typeParameters=
target3.width=120
target3.x=0
target3.y=0
target4.height=50
target4.name=Picture
target4.showInterface=false
target4.type=ClassTarget
target4.typeParameters=
target4.width=80
target4.x=0
target4.y=0
target5.height=50
target5.name=XML
target5.showInterface=false
target5.type=ClassTarget
target5.typeParameters=
target5.width=100
target5.x=0
target5.y=0
target6.height=50
target6.name=TableRow
target6.showInterface=false
target6.type=ClassTarget
target6.typeParameters=
target6.width=80
target6.x=0
target6.y=0
target7.height=50
target7.name=MyWorld
target7.showInterface=false
target7.type=ClassTarget
target7.typeParameters=
target7.width=80
target7.x=0
target7.y=0
version=3.0.0
width=1350
world.lastInstantiated=MyWorld
xPosition=368
yPosition=100

View file

@ -0,0 +1,69 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.Font;
/**
* Balkendiagramm für int-Array, Zahlen werden zufällig erzeugt.
*
* @author Schaller
* @version 29.11.18
*/
public class Balkendiagramm extends PictureViewer
{
// Liste mit allen Werten
int[] zahlen;
// Schriften
Font kleineSchrift;
Font grosseSchrift;
public Balkendiagramm() {
size(1000, 700);
background(0);
kleineSchrift = new Font( Font.SANS_SERIF, Font.PLAIN, 12 );
grosseSchrift = new Font( Font.SANS_SERIF, Font.PLAIN, 20 );
// Zufallszahlen erzeugen und anzeigen
erzeugeZufallsarray(20);
zeichneBalken();
}
public int getZufallszahl(int min, int max) {
java.util.Random r = new java.util.Random();
return r.nextInt(max-min+1)+min;
}
public void erzeugeZufallsarray(int laenge) {
// ToDo: Neues Array der richtigen Länge erzeugen
// ToDo: Jedes Element mit einer Zufallszahl belegen
}
public void zeichneBalken() {
clear();
// Überschrift
fill(255,255,255);
textFont(grosseSchrift);
text("Balkendiagramm", 2, 20);
textFont(kleineSchrift);
// Alle Einträge darstellen
for (int i = 0; i< zahlen.length; i++) {
fill(20,30,170);
// Balkendiagramm zeichnen
rect(120, 25+i*15, zahlen[i]+1, 13);
// Beschriftung
fill(255,255,255);
text("i="+i, 2, 35+i*15);
text("zahlen["+i+"]="+zahlen[i], 30, 35+i*15);
}
}
}

View file

@ -0,0 +1,36 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
/**
* Ergänzen Sie hier eine Beschreibung für die Klasse MyWorld.
*
* @author (Ihr Name)
* @version (eine Versionsnummer oder ein Datum)
*/
public class MyWorld extends World
{
/**
* Konstruktor für Objekte der Klasse MyWorld
*
*/
public MyWorld()
{
// Erstellt eine neue Welt mit 1200x900 Pixeln
super(1000, 700, 1);
prepare();
}
/**
* Bereite die Welt für den Programmstart vor.
* Das heißt: Erzeuge die Anfangs-Objekte und füge sie der Welt hinzu.
*/
private void prepare()
{
Balkendiagramm balkendiagramm = new Balkendiagramm();
addObject(balkendiagramm,500,350);
}
}

View file

@ -0,0 +1,699 @@
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.util.Vector;
import javax.imageio.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
import java.awt.geom.AffineTransform;
/**
*
* Bildklasse für die Simulation von Processing-Befehlen
*
* Diese Klasse stellt ein BufferedImage bereit, in das mit Processing-Befehlen gezeichnet
* werden kann.
* Zusätzlich kann ein Bildanzeiger über jede Änderung des Bildes informiert werden,
* um "Zurück"-Befehle zu ermöglichen. Der Bildanzeiger ist entweder eine normale Java
* ScrollPane oder ein Actor aus Greenfoot.
* Die Dokumentation der einzelnen Zeichenmethoden ist der Processing-Reference
* (https://processing.org/reference/ steht unter CC-Lizenz: https://creativecommons.org/)
* entnommen und mit Deepl.com ins Deutsche übersetzt.
*
* @version 1.0 from 23.01.2019
* @author Thomas Schaller (ZPG Informatik Klasse 9)
*/
public class Picture{
// Einstellungmöglichkeiten für das Zeichnen von Rechtecken und Ellipsen
// RADIUS = Mittelpunkt+Radius wird gegeben, CENTER = Mittelpunkt und Breite/Höhe wird gegeben,
// CORNER = Linke obere Ecke + Breite/Höhe, CORNERS = Linke obere und rechte untere Ecke
public static final int RADIUS = 1;
public static final int CENTER = 2;
public static final int CORNER = 3;
public static final int CORNERS = 4;
// gespeichertes Bild,
private BufferedImage image;
// aktuelle Farbeinstellungen
private Color background;
private Color pencolor;
private Color fillcolor;
// aktuelle Stiftdicke
private double stroke;
// akkteller Koordinatenmodus von Rechtecken und Ellipsen
private int ellipseMode = CENTER;
private int rectMode = CORNER;
// aktueller Font
private Font textfont = null;
// muss ein Bildanzeiger benachrichtigt werden
private PictureViewer observer = null;
private boolean autorefresh = true;
/**
* Erzeugt ein Bild mit Standardgröße 500x400
*/
public Picture() {
this(500,400);
}
/**
* Erzeugt ein Bild der angegeben Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public Picture(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein Bild aus einer Datei
* @param filename Dateiname des Bildes
*/
public Picture(String filename) {
load(filename);
}
/**
* Erzeugt ein Bild der angegebenen Größe mit festgelegtem Hintergrund
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds
*/
public Picture(int width, int height, String background) {
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
this.background = decode(background);
this.pencolor = new Color(0,0,0);
this.stroke = 1;
this.fillcolor = null;
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(this.background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Legt fest, wer das Bild anzeigt.
* Diese ermöglicht die Benachrichtung des Observers, wenn sich das Bild ändert.
* @param observer Anzeiger des Bildes
*/
public void setObserver(PictureViewer observer) {
this.observer= observer;
}
/**
* Direktes Setzen des Bildes (für interne Zwecke)
* @param b Bild, das gespeichert werden soll.
*/
public void setImage(BufferedImage b) {
image = b;
}
/**
* Direktes Abfragen des Bildes (für interne Zwecke)
* @return Bild, das gerade gespeichert ist.
*/
public BufferedImage getImage() {
return image;
}
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
pushImage();
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getWidth() {
return image.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getHeight() {
return image.getHeight();
}
/**
* Erzeugt eine Kopie des Bildes und übergibt sie an den Observer (falls existent), damit dieser die Versionen speichern kann
*/
private void pushImage() {
if(observer != null) {
observer.pushImage();
}
}
/**
* Legt fest, ob nach jedem Zeichenbefehl automatisch das Bild auch in
* der Oberfläche aktualisiert wird. Die Einstellung "false" beschleunigt
* das Zeichnen aufwändiger Bilder und verhindert "Flackern".
* Das Neuzeichnen kann durch die Methode "refresh" gezielt ausgelöst werden.
* @param autorefresh true = nach jedem Zeichenbefehl die Anzeige aktualisieren, false= nur durch die Methode refresh neu zeichnen
*/
public void setAutoRefresh(boolean autoRefresh) {
this.autorefresh = autoRefresh;
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
private void repaint() {
if(observer != null && autorefresh) {
observer.repaint();
}
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
public void refresh() {
if(observer != null) {
observer.repaint();
}
}
// ----------------------------------------- Zeichenfunktionen -----------------------------------------------
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
pushImage();
image = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,image.getWidth()-1, image.getHeight()-1);
repaint();
}
/**
* Konvertiert die in einem bestimmten Modus gegebenen Koordinaten in die Java-übliche Links_Oben_Breite_Höhe Version
* Die Änderungen werden direkt im Array vorgenommen
* @param coord Array mit vier Koordinateneinträgen im gegebenen Modus
* @param mode Modus der Koordinaten (CORNER, CORNERS, RADIUS oder CENTER)
*/
private void convert(int[] coord, int mode) {
switch(mode) {
case CORNER: break;
case CORNERS: coord[2] -= coord[0]; coord[3] -= coord[1]; break;
case RADIUS: coord[2] *= 2; coord[3] *=2;
case CENTER: coord[0] -= coord[2]/2; coord[1] -= coord[3]/2;
}
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
rectMode = mode;
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
ellipseMode = mode;
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if (stroke > 0) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawLine(x1, y1, x2, y2);
}
repaint();
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, rectMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillRect(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawRect(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, ellipseMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillOval(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawOval(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
int px[] = {x1, x2, x3};
int py[] = {y1, y2, y3};
polygon(px, py);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
int px[] = {x1, x2, x3, x4};
int py[] = {y1, y2, y3, y4};
polygon(px, py);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillPolygon(x,y, y.length);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawPolygon(x, y, x.length);
}
repaint();
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
ellipse(x,y,1, 1);
}
// ----------------------------------------- Schriftdarstellung -----------------------------------------------
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param s Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String s, int x, int y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(pencolor != null) {
g.setColor(fillcolor);
g.setStroke(new BasicStroke((float) stroke));
g.setFont(textfont);
g.drawString(s, x, y);
}
repaint();
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
this.textfont = font;
}
// ----------------------------------------- Farbfestlegungen -----------------------------------------------
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(String color) {
try{
return new Color(
Integer.valueOf( color.substring( 0, 2 ), 16 ),
Integer.valueOf( color.substring( 2, 4 ), 16 ),
Integer.valueOf( color.substring( 4, 6 ), 16 ) );
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(int color) {
try{
if(color >=0 && color < 256) {
return new Color(color,color,color);
} else {
int r = color / 0x010000 % 0xFF;
int g = color / 0x000100 % 0xFF;
int b = color % 0xFF;
System.out.println(""+r+","+g+","+b);
return new Color(r, g, b );
}
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
this.pencolor = decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
this.pencolor=decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
this.pencolor = new Color(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
this.pencolor = null;
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
this.stroke = width;
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
this.fillcolor = decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
this.fillcolor=decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
this.fillcolor = new Color(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
this.fillcolor = null;
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
if(c < 256) {
this.background=new Color(c,c,c);
} else {
int r = c / 0x010000;
int g = c / 0x000100 % 0xFF;
int b = c % 0xFF;
this.background= new Color(r, g, b );
}
this.clear();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
this.background=new Color(r,g,b);
this.clear();
}
// ----------------------------------------- Dateioperationen -----------------------------------------------
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
try{
this.image = ImageIO.read(new File(filename));
this.background = decode("D0D0D0");
this.pencolor = new Color(0,0,0);
this.fillcolor = null;
this.stroke = 1;
this.repaint();
} catch(Exception e) {
System.out.println("Fehler beim Einlesen der Bilddatei");
}
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
try{
String[] fn = filename.split("\\.");
if (fn.length== 1) {
ImageIO.write(image, "PNG", new File(filename+".png"));
} else {
if (fn.length == 2 && (fn[1].toUpperCase().equals("PNG") ||
fn[1].toUpperCase().equals("GIF"))){
ImageIO.write(image, fn[1], new File(filename));
}else {
System.out.println("Unbekanntes Bildformat");
}
}
} catch(Exception e) {
System.out.println("Fehler beim Speichern");
}
}
// ----------------------------------------- Sonstiges -----------------------------------------------
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
Color[][] pixel = new Color[image.getWidth()][image.getHeight()];
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
pixel[x][y] = new java.awt.Color(image.getRGB(x,y));
}
}
return pixel;
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
size(pixel.length,pixel[0].length);
Graphics2D g = (Graphics2D) image.getGraphics();
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
g.setColor(pixel[x][y]);
g.fillRect(x, y, 1, 1);
}
}
repaint();
}
/**
* Hilfsfunktion zum Verzögern der Ausgabe
* @param millis Wartezeit in Millisekunden
*/
public void delay(int millis) {
try{
Thread.sleep(millis);
} catch(Exception e) {
}
}
}

View file

@ -0,0 +1,499 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.awt.Font;
import java.util.Vector;
import java.awt.Color;
import javax.imageio.*;
import java.io.*;
/**
* Der PictureViewer ist ein Actor, der in der Lage ist ein
* Objekt der Klasse Picture anzuzeigen. Zusätzlich können
* mehrere Verarbeitungsschritte gespeichert werden, um ein
* "zurück"-Funktion zu ermöglichen.
*
* @author Thomas Schaller
* @version V1.0 vom 10.02.2019
*/
public class PictureViewer extends Actor
{
public static final int FIT = -1;
public static final int NORMAL = 1;
private static final int ANZ_BACK = 0;
private double zoom;
protected Picture picture = null;
private Vector<BufferedImage> history;
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der Größe 500x400
*/
public PictureViewer() {
this(500,400);
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public PictureViewer(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds als HEX-String (z.B. "FF3A45")
*/
public PictureViewer(int width, int height, String background) {
picture = new Picture(width,height, background);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild aus einer Bilddatei
* @param filename Name des Bildes
*/
public PictureViewer(String filename) {
picture = new Picture(filename);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Speichert das übergebene Bild in der History.
* @param b zu speicherndes Bild
*/
public void pushImage() {
if( this.ANZ_BACK > 0) {
if(history.size() == this.ANZ_BACK) {
history.removeElementAt(0);
}
BufferedImage b = new BufferedImage(picture.getWidth(), picture.getHeight(), picture.getImage().getType());
Graphics g = b.getGraphics();
g.drawImage(picture.getImage(), 0, 0, null);
g.dispose();
history.add(b);
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
private void popImage() {
int anz = history.size();
if(anz>0) {
BufferedImage i = history.get(anz-1);
history.removeElementAt(anz-1);
picture.setImage(i);
repaint();
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
public void back() {
popImage();
}
/**
* Setzt den Zoom-Faktor für das Bild.
* Als Zoomfaktor sind auch die Konstanten Bildanzeiger.FIT (auf Bildschirmgröße zoomen) und Bildanzeiger.NORMAL (100%) möglich.
* @param factor Zoomfaktor (1.0 = 100%).
*/
public void setZoom(double zoom) {
this.zoom = zoom;
repaint();
}
/**
* Setzt die automatische Neuanzeige des Bildes.
* Mit dieser Methode kann man einstellen, ob nach jedem Zeichenbefehl
* die Anzeige auf dem Bildschirm aktualisiert werden soll. Bei sehr
* vielen Zeichenbefehlen wird die Ausgabe dadurch sehr langsam. Es reicht
* eine Anzeige am Ende der Zeichenbefehle. Rufen Sie dann für das Neuzeichnen
* die Methode refresh() auf.
* @param autoRefresh true, wenn nach jedem Zeichenbefehl die Anzeige aktualisiert werden soll.
*/
public void setAutoRefresh(boolean autoRefresh) {
picture.setAutoRefresh(autoRefresh);
}
/**
* Sorgt für die Aktualisierung der Bildschrimanzeige. Das aktuelle Bild
* wird dadurch angezeigt. Durch Einstellung von autoRefresh kann die
* Anzeige automatisiert werden.
*/
public void refresh() {
repaint();
}
/**
* Setzt das angezeigt Bild neu und beachtet dabei den Zoomfaktor.
*/
public void repaint() {
double faktor = zoom;
if (zoom == FIT) {
double faktorw = (double) this.getWorld().getWidth() / picture.getWidth();
double faktorh = (double) this.getWorld().getHeight() / picture.getHeight();
faktor = Math.min(faktorw, faktorh);
}
int gfi_width = (int) (picture.getWidth()*faktor);
int gfi_height = (int) (picture.getHeight()*faktor);
setImage(new GreenfootImage(gfi_width, gfi_height));
Graphics2D g = (Graphics2D) this.getImage().getAwtImage().getGraphics();
g.drawImage(picture.getImage(),0,0,gfi_width, gfi_height, 0, 0, picture.getWidth(), picture.getHeight(), null);
g.setColor(new java.awt.Color(0,0,0));
g.setStroke(new BasicStroke((float) 1));
g.drawRect(0,0,gfi_width-1, gfi_height-1);
}
// Wrappermethoden
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
picture.size(width, height);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getImageWidth() {
return picture.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getImageHeight() {
return picture.getHeight();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
picture.background(c);
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
picture.background(r,g,b);
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
picture.line(x1,y1,x2,y2);
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
picture.rect(a,b,c,d);
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
picture.ellipse(a,b,c,d);
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
picture.triangle(x1,y1,x2,y2,x3,y3);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
picture.quad(x1,y1,x2,y2,x3,y3,x4,y4);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
picture.polygon(x,y);
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
picture.point(x,y);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
picture.rectMode(mode);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
picture.ellipseMode(mode);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
picture.stroke(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
picture.noStroke();
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
picture.strokeWeight(width);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
picture.fill(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
picture.noFill();
}
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
picture.clear();
}
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
picture.load(filename);
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
picture.save(filename);
}
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param t Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String t, int x, int y) {
picture.text(t,x,y);
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
picture.textFont(font);
}
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
return picture.getPixelArray();
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
picture.setPixelArray(pixel);
}
}

View file

@ -0,0 +1,14 @@
------------------------------------------------------------------------
Dies ist die README-Datei des Projekts. Hier sollten Sie Ihr Projekt
beschreiben.
Erzählen Sie dem Leser (jemand, der nichts über dieses Projekt weiss),
alles, was er/sie wissen muss. Üblicherweise sollte der Kommentar
zumindest die folgenden Angaben umfassen:
------------------------------------------------------------------------
PROJEKTBEZEICHNUNG:
PROJEKTZWECK:
VERSION oder DATUM:
WIE IST DAS PROJEKT ZU STARTEN:
AUTOR(EN):
BENUTZERHINWEISE:

View file

@ -0,0 +1,894 @@
/**
* Die Klasse Table vereinfacht den Zugriff auf CSV-Dateien.
* Die Klassen Table und TableRow ermöglichen einen einfachen Zugriff auf tabellenbasierte
* Dokumente.
*
* @author Thomas Schaller
* @version 1.0 vom 01.02.2019
*/
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.util.Scanner;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
public class Table
{
// Standardtrennzeichen für Spalten
private static final char DEFAULT_SEPARATOR = ';';
// Standardmarkierung für Texte
private static final char DEFAULT_QUOTE = '"';
// Standardtrennzeichen für Dezimalzahlen
private static final char DEFAULT_COMMA = ',';
// mögliche Spaltentypen
private static final String UNKNOWN ="UNKOWN";
private static final String INT = "INTEGER";
private static final String DOUBLE = "DOUBLE";
private static final String FLOAT = "FLOAT";
// interne Verwaltung des Dokuments als JDOM-Document-Objekt
private Document doc;
// Verweis auf Element für Kopfzeile
private Element header;
// Ende Attribute
/**
* Erzeugt leeres Tabellen-Dokument.
*/
public Table() {
this.doc = new Document();
doc.setRootElement(new Element("CSV-Data"));
this.header = new Element("Header");
doc.getRootElement().addContent(header);
}
/**
* Erzeugt Tabellen-Dokument aus einer CSV-Datei.
* Liest den Inhalt einer Datei und erstellt ein Tabellenobjekt mit seinen Werten.
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
* @param separator Trennzeichen für Spalten (meist ';' oder ',' oder '\t' für Tab)
* @param quote Kennung für Texte (meist '"').
*/
public Table(String filename, String options, char separator, char quote) {
loadCSV(filename, options, separator, quote);
}
/**
* Erzeugt Tabellen-Dokument aus einer CSV-Datei.
* Liest den Inhalt einer Datei und erstellt ein Tabellenobjekt mit seinen Werten (Separator = ';', Kennung für Text = '"').
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
*/
public Table(String filename, String options) {
loadCSV(filename, options);
}
/**
* Erzeugt Tabellen-Dokument aus einer CSV-Datei.
* Liest den Inhalt einer Datei ohne Kopfzeile und erstellt ein Tabellenobjekt mit seinen Werten (Separator = ';', Kennung für Text = '"').
* @param filename Dateiname der CSV-Datei.
*/
public Table(String filename) {
loadCSV(filename);
}
// Anfang Methoden
/**
* Liest den Inhalt einer CSV-Datei ohne Kopfzeile (Separator = ';', Kennung für Text = '"').
* @param filename Dateiname der CSV-Datei.
*/
public void loadCSV(String filename) {
loadCSV(filename, "");
}
/**
* Liest den Inhalt einer CSV-Datei (Separator = ';', Kennung für Text = '"').
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
*/
public void loadCSV(String filename, String options) {
loadCSV(filename, options, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
}
/**
* Liest den Inhalt einer CSV-Datei.
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
* @param separator Trennzeichen für Spalten (meist ';' oder ',' oder '\t' für Tab)
* @param quote Kennung für Texte (meist '"').
*/
public void loadCSV(String filename, String options, char separator, char quote) {
doc = new Document();
doc.setRootElement(new Element("CSV-Data"));
header = new Element("Header");
doc.getRootElement().addContent(header);
try {
File f = new File(filename);
Scanner scanner = new Scanner(new File(filename));
if(options.toLowerCase().contains("header") && scanner.hasNext()) {
List<String> entries = parseLine(scanner.nextLine(), separator, quote);
int i= 0;
for(String s : entries) {
Element entry = new Element("Column");
header.addContent(entry);
entry.setText(s);
entry.setAttribute("type", "unknown");
i++;
}
}
List<Element> cols = header.getChildren();
while (scanner.hasNext()) {
Element line = new Element("Row");
doc.getRootElement().addContent(line);
List<String> entries = parseLine(scanner.nextLine(), separator, quote);
int i= 0;
for(String s : entries) {
if(i==cols.size()) {
Element entry = new Element("Column");
entry.setAttribute("type", "unknown");
header.addContent(entry);
cols = header.getChildren();
}
Element entry = new Element("Entry");
entry.setText(s);
line.addContent(entry);
i++;
}
}
scanner.close();
} catch (Exception e) {
System.out.println("Fehler beim Lesen der CSV-Datei");
}
}
/**
* Speichert das aktuelle Dokument als CSV-Datei ohne Kopfzeile (Separator = ';', Kennung für Text = '"').
* @param filename Dateiname der CSV-Datei.
*/
public void saveCSV(String filename) {
saveCSV(filename, "");
}
/**
* Speichert das aktuelle Dokument als CSV-Datei (Separator = ';', Kennung für Text = '"').
* Wenn die Datei eine Kopfzeile enthalten, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile haben soll,
* dann lassen Sie einfach die Option "header" weg.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile haben soll.
* @param filename Dateiname der CSV-Datei.
*/
public void saveCSV(String filename, String options) {
saveCSV(filename, options, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
}
/**
* Speichert das aktuelle Dokument als CSV-Datei.
* Wenn die Datei eine Kopfzeile enthalten, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile haben soll,
* dann lassen Sie einfach die Option "header" weg.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile haben soll.
* @param filename Dateiname der CSV-Datei.
* @param separator Trennzeichen für Spalten (meist ';' oder ',' oder '\t' für Tab)
* @param quote Kennung für Texte (meist '"').
*/
public void saveCSV(String filename, String options, char separator, char quote){
try{
File f = new File(filename);
PrintStream outputFile = new PrintStream (f);
System.out.println("Speicher in : "+f.getAbsolutePath());
List<Element> columns = header.getChildren();
String sq = ""+quote;
String ss = ""+separator;
if(quote =='"') sq = "\"";
if(separator =='"') ss = "\"";
if(options.toLowerCase().contains("header")) {
String h = "";
for(Element c : columns) {
h += ss + sq + c.getText()+sq;
}
outputFile.println(h.substring(1));
}
for(int i = 0; i<getRowCount(); i++) {
String l = "";
for(String s: getStringRow(i)) {
if(s.contains(""+separator)) {
if(quote == '"' && s.contains("\"")) {
s = s.replace("\"","\"\"");
}
l += ss + sq + s+sq;
} else {
l += ss+s;
}
}
outputFile.println(l.substring(1));
}
outputFile.close();
}
catch(Exception e) {
System.out.println("Fehler beim Schreiben der Datei");
}
}
/** Speichert die Tabelle als XML-Dokument.
* @param filename Dateiname des XML-Files
*/
public void saveXML(String filename) {
try {
// new XMLOutputter().output(doc, System.out);
XMLOutputter xmlOutput = new XMLOutputter();
// display nice nice
xmlOutput.setFormat(Format.getPrettyFormat());
File f = new File(filename);
FileOutputStream outputFile = new FileOutputStream(f);
System.out.println("Speicher in : "+f.getAbsolutePath() );
xmlOutput.output(doc, outputFile);
outputFile.close();
System.out.println("File Saved!");
} catch (IOException io) {
System.out.println(io.getMessage());
}
}
//----------------------------------------------- Zeigerbewegungen --------------------------------------------------
/** HIlfsfunktion für die Analyse einer Dateizeile
* @param cvsLine Zeile aus der Datei
* @return Liste von String für die einzelnen Spalten
*/
private List<String> parseLine(String cvsLine) {
return parseLine(cvsLine, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
}
/** HIlfsfunktion für die Analyse einer Dateizeile
* @param cvsLine Zeile aus der Datei
* @param sparator Trennzeichen für die Spalten
* @return Liste von String für die einzelnen Spalten
*/
private List<String> parseLine(String cvsLine, char separator) {
return parseLine(cvsLine, separator, DEFAULT_QUOTE);
}
/** HIlfsfunktion für die Analyse einer Dateizeile
* @param cvsLine Zeile aus der Datei
* @param sparator Trennzeichen für die Spalten
* @param customQuote Kennung für Strings
* @return Liste von String für die einzelnen Spalten
*/
private List<String> parseLine(String cvsLine, char separator, char customQuote) {
List<String> result = new ArrayList<>();
//if empty, return!
if (cvsLine == null && cvsLine.isEmpty()) {
return result;
}
//ggf. Default-Value laden
if (customQuote == ' ') {
customQuote = DEFAULT_QUOTE;
}
if (separator == ' ') {
separator = DEFAULT_SEPARATOR;
}
StringBuffer curVal = new StringBuffer();
boolean inQuotes = false;
boolean startCollectChar = false;
boolean doubleQuotesInColumn = false;
char[] chars = cvsLine.toCharArray();
for (char ch : chars) {
if (inQuotes) { // aktueller Text ist in Quotes eingeschlossen
startCollectChar = true;
if (ch == customQuote) { // Quotes werden beendet, aber Achtung bei "" => Metazeichen
inQuotes = false;
if (ch == '\"') {
doubleQuotesInColumn = true;
}
} else {
if (ch == '\"' && !doubleQuotesInColumn) {
doubleQuotesInColumn = true;
} else {
curVal.append(ch);
doubleQuotesInColumn = false;
}
}
} else {
if (ch == customQuote) {
inQuotes = true;
//Fixed : allow "" in empty quote enclosed
if (ch == '\"'){
if(doubleQuotesInColumn) {
curVal.append('"');
doubleQuotesInColumn = false;
} else doubleQuotesInColumn = true;
}
}
else {
doubleQuotesInColumn = false;
if (ch == separator) {
result.add(curVal.toString());
curVal = new StringBuffer();
startCollectChar = false;
} else if (ch == '\r') {
//ignore LF characters
continue;
} else if (ch == '\n') {
//the end, break!
break;
} else {
curVal.append(ch);
}
}
}
}
result.add(curVal.toString());
return result;
}
/**
* Sucht die Nummer einer durch Namen gegebenen Spalte.
* @param name Name der Spalte
* @return Nummer der Spalte
*/
private int findColumnNumber(String name) {
List<Element> columns = header.getChildren();
int i = 0;
for(Element c : columns) {
if (c.getText().toLowerCase().equals(name.toLowerCase())) {
return i;
}
i++;
}
return -1;
}
/**
* Fügt eine neue Spalte am Ende der Tabelle an.
*/
public void addColumn() {
Element entry = new Element("Column");
entry.setAttribute("type", Table.UNKNOWN);
header.addContent(entry);
}
/**
* Fügt eine neue Spalte am Ende der Tabelle an und benennt sie.
* @param title Bezeichnung der Spalte
*/
public void addColumn(String title) {
addColumn();
Element nc = ((List<Element>)(header.getChildren())).get(header.getChildren().size()-1);
nc.setText(title);
}
/**
* Fügt eine neue Spalte am Ende der Tabelle an und benennt und typisiert sie.
* @param title Bezeichnung der Spalte
* @param type Typ der Spalte (UNKNOWN, DOUBLE, INTEGER, FLOAT)
*/
public void addColumn(String title, String type) {
addColumn(title);
Element nc = ((List<Element>)(header.getChildren())).get(header.getChildren().size()-1);
nc.setAttribute("type", type);
}
/**
* Löscht eine Spalte.
* @param i Nummer der Spalte.
*/
public void removeColumn(int i) {
List<Element> lines = doc.getRootElement().getChildren();
for(Element l : lines) {
if(l.getChildren().size()>i) l.removeContent(i);
}
}
/**
* Löscht eine Spalte
* @param name Name der Spalte
*/
public void removeColumn(String name) {
try{
removeColumn(findColumnNumber(name));
} catch(Exception e) { System.out.println("Unbekannter Spaltenname");}
}
/**
* Liefert die Anzahl der Spalten in der Tabelle
* @return Anzahl der Spalten
*/
public int getColumnCount() {
return header.getChildren().size();
}
/**
* Liefert die Anzahl der Zeilen in der Tabelle
* @return Anzahl der Zeilen
*/
public int getRowCount() {
return doc.getRootElement().getChildren().size()-1;
}
/**
* Löscht alle Zeilen der Tabelle.
* Die Spaltenüberschriften und Typen bleiben erhalten.
*/
public void clearRows() {
doc.getRootElement().removeChildren("Row");
}
/**
* Fügt eine neue Zeile an das Ende der Tabelle an.
* @return ein TableRow-Objekt für diese neue Zeile
*/
public TableRow addRow() {
Element row = new Element("Row");
doc.getRootElement().addContent(row);
return new TableRow(doc, row);
}
/**
* Löscht eine Zeile
* @param i Nummer der Zeile
*/
public void removeRow(int i) {
if(i<getRowCount()) {
doc.getRootElement().removeContent(i);
}
}
/**
* Liefert eine Zeile der Tabelle
* @param i Nummer der Zeile
* @return TableRow-Objekt für diese Zeile
*/
public TableRow getRow(int i) {
if(i<getRowCount()) {
List<Element> rows = doc.getRootElement().getChildren();
return new TableRow(doc, rows.get(i+1));
}
return null;
}
/**
* Liefert die ganze Tabelle als Array von TableRow-Objekten
* @return Array von TableRow-Objekten
*/
public TableRow[] rows() {
TableRow[] rows = new TableRow[getRowCount()];
for(int i = 0; i < getRowCount(); i++) {
rows[i] = getRow(i);
}
return rows;
}
/**
* Liefert den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public int getInt(int row, int column) {
return getRow(row).getInt(column);
}
/**
* Liefert den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public int getInt(int row, String name) {
return getRow(row).getInt(name);
}
/**
* Setzt den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @param value neuer Wert der Zelle
*/
public void setInt(int row, int column,int value) {
getRow(row).setInt(column, value);
}
/**
* Setzt den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setInt(int row, String name, int value) {
getRow(row).setInt(name, value);
}
/**
* Liefert alle Werte einer Zeile als Integer-Array.
* @param row Nummer der Zeile
* @return int-Array, dass alle Werte der Zeile enthält
*/
public int[] getIntRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
int[] r = new int[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getInt(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Integer-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public int[] getIntColumn(int column) {
try{
int anz = getRowCount();
int[] r = new int[anz];
for(int i=0; i<anz; i++) {
r[i] = getInt(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Integer-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public int[] getIntColumn(String name) {
return getIntColumn(findColumnNumber(name));
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public float getFloat(int row, int column) {
return getRow(row).getFloat(column);
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public float getFloat(int row, String name) {
return getRow(row).getFloat(name);
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @param value neuer Wert der Zelle
*/
public void setFloat(int row, int column,float value) {
getRow(row).setFloat(column, value);
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setFloat(int row, String name, float value) {
getRow(row).setFloat(name, value);
}
/**
* Liefert alle Werte einer Zeile als Float-Array.
* @param row Nummer der Zeile
* @return int-Array, dass alle Werte der Zeile enthält
*/
public float[] getFloatRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
float[] r = new float[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getFloat(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Float-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public float[] getFloatColumn(int column) {
try{
int anz = getRowCount();
float[] r = new float[anz];
for(int i=0; i<anz; i++) {
r[i] = getFloat(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Float-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public float[] getFloatColumn(String name) {
return getFloatColumn(findColumnNumber(name));
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public double getDouble(int row, int column) {
return getRow(row).getDouble(column);
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public double getDouble(int row, String name) {
return getRow(row).getDouble(name);
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @param value neuer Wert der Zelle
*/
public void setDouble(int row, int column,double value) {
getRow(row).setDouble(column, value);
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setDouble(int row, String name, double value) {
getRow(row).setDouble(name, value);
}
/**
* Liefert alle Werte einer Spalte als Double-Array.
* @param row Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public double[] getDoubleRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
double[] r = new double[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getDouble(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Double-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public double[] getDoubleColumn(int column) {
try{
int anz = getRowCount();
double[] r = new double[anz];
for(int i=0; i<anz; i++) {
r[i] = getDouble(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Double-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public double[] getDoubleColumn(String name) {
return getDoubleColumn(findColumnNumber(name));
}
/**
* Liefert den Wert einer Zelle als String
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public String getString(int row, int column) {
return getRow(row).getString(column);
}
/**
* Liefert den Wert einer Zelle als String
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public String getString(int row, String name) {
return getRow(row).getString(name);
}
/**
* Setzt den Wert einer Zelle als String
* @param row Zeilennummer
* @param column Spaltennummer
* @param text neuer Wert der Zelle
*/
public void setString(int row, int column,String text) {
getRow(row).setString(column, text);
}
/**
* Setzt den Wert einer Zelle als String
* @param row Zeilennummer
* @param name Name der Spalte
* @param text neuer Wert der Zelle
*/
public void setString(int row, String name, String text) {
getRow(row).setString(name, text);
}
/**
* Liefert alle Werte einer Spalte als String-Array.
* @param row Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public String[] getStringRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
String[] r = new String[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getString(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als String-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public String[] getStringColumn(int column) {
try{
int anz = getRowCount();
String[] r = new String[anz];
for(int i=0; i<anz; i++) {
r[i] = getString(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als String-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public String[] getStringColumn(String name) {
return getStringColumn(findColumnNumber(name));
}
/**
* Sucht nach einem bestimmtem Wert in einer Zeile.
* @param value Wert der gesucht werden soll
* @param column Nummer der Spalte, die durchsucht werden soll
* @return TableRow-Objekt der Zeile, wenn der Wert gefunden wurde, sonst null
*/
public TableRow findRow(String value, int column) {
for(int i=0; i<getRowCount(); i++) {
if(getString(i,column).equals(value)){
return getRow(i);
}
}
return null;
}
/**
* Sucht nach einem bestimmtem Wert in einer Zeile.
* @param value Wert der gesucht werden soll
* @param name Name der Spalte, die durchsucht werden soll
* @return TableRow-Objekt der Zeile, wenn der Wert gefunden wurde, sonst null
*/
public TableRow findRow(String value, String name) {
return findRow(value, findColumnNumber(name));
}
/**
* Kürzt alle Einträge der Tabelle um unnötige Leerzeichen am Anfang oder Ende
*/
public void trim() {
for(int y=0; y<getRowCount(); y++) {
for (int x =0; x<getColumnCount(); x++) {
setString(y,x,getString(y,x).trim());
}
}
}
}

View file

@ -0,0 +1,312 @@
/**
* Repräsentiert eine Zeile eines Table-Objekts.
* Erlaubt einen einfachen Zugriff auf die einzelnen Einträge in dieser Zeile.
*
* @author Thomas Schaller
* @version V1.0 vom 01.02.2019
*/
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.util.Scanner;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
import java.text.NumberFormat;
public class TableRow
{
// Verweis auf das ganze Dokument
private Document doc;
// Verweis auf die Zeile, für die dieses Objekt steht
private Element current;
// Verweis auf die Kopfzeile
private Element header;
// Für die Interpretation von Zahlenwerten
NumberFormat format = NumberFormat.getInstance();
// Ende Attribute
/**
* Erzeugt ein TableRow-Objekt.
* Diese Methode ist für den internen Gebraucht. Einige Methode der Table-Klasse erzeugen mit diesem Konstruktor TableRow-Objekte.
* @param doc JDOM-Dokument, das für die ganze Tabelle steht.
* @param row JDOM-Element, das für die aktuelle Zeile steht.
*/
public TableRow(Document doc, Element row) {
this.doc = doc;
this.current = row;
this.header = doc.getRootElement().getChild("Header");
}
/**
* Liefert die Anzahl der Spalten der Zeile.
* @return Anzahl der Spalten
*/
public int getColumnCount() {
return header.getChildren().size();
}
/**
* Liefert den Titel einer Spalte
* @param i Nummer der Spalte
* @return Name der Spalte
*/
public String getColumnTitle(int i) {
if(i< getColumnCount()) {
return ((List<Element>) (header.getChildren())).get(i).getText();
} else {
return "";
}
}
/**
* Liefert die Nummer einer Spalte
* @param name Name der Spalte
* @return Nummer der Spalte
*/
public int getColumn(String name) {
List<Element> columns = header.getChildren();
int i = 0;
while (i < columns.size()) {
if (columns.get(i).getText().toLowerCase().equals(name.toLowerCase())) {
return i;
}
i++;
} // end of while
return -1;
}
/**
* Erzeugt eine neue Zeile mit i Spalten
* Wenn bisher nicht genügend Spalten vorhanden sind, werden automatisch neue Spalten hinzugefügt (auch zum Header)
* @param i Anzahl der Spalten
*/
private Element buildRow(int i) {
List<Element> columns = header.getChildren();
Element entry=null;
for(int j=0; j<=i; j++) {
if(j==columns.size()) {
Element h = new Element("Column");
h.setAttribute("type", "unknown");
header.addContent(h);
columns = header.getChildren();
}
if(j==current.getChildren().size()) {
entry = new Element("Entry");
current.addContent(entry);
}
}
return entry;
}
/**
* Erzeugt eine neue Zeile.
* Es werden genügend Spalten erzeugt, dass ein Wert in Spalte "name" eingetragen werden kann
* @param name Name der Spalte
*/
private Element buildRow(String name) {
List<Element> columns = header.getChildren();
int i = 0;
for(Element c: columns) {
if(c.getText().toLowerCase().equals(name.toLowerCase())) {
return buildRow(i);
}
i++;
}
return null;
}
/**
* Liefert den Wert einer Zelle als String
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public String getString(int i) {
if(i >= current.getContent().size()) return "";
Element e = (Element) current.getContent(i) ;
if(e!=null) {
return e.getText();
} else {
return "";
}
}
/**
* Liefert den Wert einer Zelle als String
* @param name Name der Spalte
* @return Wert der Zelle
*/
public String getString(String name) {
return getString(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als String
* @param i Nummer der Spalte
* @param text neuer Wert der Zelle
*/
public void setString(int i, String text) {
Element e = buildRow(i);
if(e!=null) e.setText(text);
}
/**
* Setzt den Wert einer Zelle als String
* @param name Name der Spalte
* @param text neuer Wert der Zelle
*/
public void setString(String name, String text) {
Element e = buildRow(name);
if(e!=null) e.setText(text);
}
/**
* Liefert den Wert einer Zelle als Int-Zahl
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public int getInt(int i) {
try{
Element e = (Element) current.getContent(i) ;
return Integer.parseInt(e.getText());
} catch(Exception e) {
return 0;
}
}
/**
* Liefert den Wert einer Zelle als Int-Zahl
* @param name Name der Spalte
* @return Wert der Zelle
*/
public int getInt(String name) {
return getInt(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als Int-Zahl
* @param i Nummer der Spalte
* @param value neuer Wert der Zelle
*/
public void setInt(int i,int value) {
Element e = buildRow(i);
if(e!=null) e.setText(""+value);
}
/**
* Setzt den Wert einer Zelle als Int-Zahl
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setInt(String name, int value) {
Element e = buildRow(name);
if(e!=null) e.setText(""+value);
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public float getFloat(int i) {
try{
Element e = (Element) current.getContent(i) ;
return Float.parseFloat(e.getText().replace(",","."));
} catch(Exception e) {
return 0;
}
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param name Name der Spalte
* @return Wert der Zelle
*/
public float getFloat(String name) {
return getFloat(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param i Nummer der Spalte
* @param value neuer Wert der Zelle
*/
public void setFloat(int i,float value) {
Element e = buildRow(i);
if(e!=null) e.setText(format.format(value));
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setFloat(String name, float value) {
Element e = buildRow(name);
if(e!=null) e.setText(format.format(value));
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public double getDouble(int i) {
try{
Element e = (Element) current.getContent(i) ;
return Double.parseDouble(e.getText().replace(",","."));
} catch(Exception e) {
return 0;
}
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param name Name der Spalte
* @return Wert der Zelle
*/
public double getDouble(String name) {
return getDouble(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param i Nummer der Spalte
* @param value neuer Wert der Zelle
*/
public void setDouble(int i,double value) {
Element e = buildRow(i);
if(e!=null) e.setText(format.format(value));
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setDouble(String name, double value) {
Element e = buildRow(name);
if(e!=null) e.setText(format.format(value));
}
}

View file

@ -0,0 +1,637 @@
/**
* Klasse zum Vereinfachten Zugriff auf XML-Dokumente
* Diese Klasse ist für den Einsatz in der Schule gedacht und soll den Schülern
* einen einfachen Zugriff auf XML-Dokumente ermöglichen. Die zur Verfügung
* stehenden Befehle sind wie in Processing realisiert.
* Dabei ist jeder Teilbaum des Dokuments wieder als XML-Objekt zugreifbar, das
* intern auf die gleiche XML-Dokumentstruktur zugreift.
* Dies ermöglicht bei unsachgemäßem Gebrauch die XML-Struktur zu zerstören. Im
* normalen Gebrauch sollte dies aber nicht relevant sein.
*
* Benötigt: jdom-1.1.3.jar
* @author Thomas Schaller
* @version 1.0 vom 31.01.2019
*/
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
public class XML {
// Anfang Attribute
// XML-Dokumentstruktur
private Document doc;
// Zeiger auf das aktuelle Element
private Element current;
// Ende Attribute
/**
* Erzeugt ein leeres XMLDokument
*/
public XML() {
this.doc = new Document();
this.current = null;
}
/**
* Erzeugt ein XML-Dokument aus einer Datei
* @param filename Dateiname der XML-Datei
*/
public XML(String filename) {
loadXML(filename);
}
/**
* interner Konstruktor, um ein XML Objekt zu erzeugen, das auf einen bestimmten Knoten verweist
* @param doc die XML-Dokumentstruktur
* @param current Zeiger auf das aktuelle Element
*/
private XML(Document doc, Element current) {
this.doc = doc;
this.current = current;
}
// Anfang Methoden
/** Öffnet das durch den Dateinamen gegebene Dokument
* @param filename Dateiname des XML-Files
*/
public void loadXML(String filename) {
doc = null;
File f = new File(filename);
try {
// Das Dokument erstellen
SAXBuilder builder = new SAXBuilder();
doc = builder.build(f);
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// Zeiger im Baum auf Root-Element
current = doc.getRootElement();
}
/** Speichert den XML-Baum im angegebenen Dateinamen
* @param filename Dateiname des XML-Files
*/
public void saveXML(String filename) {
try {
// new XMLOutputter().output(doc, System.out);
XMLOutputter xmlOutput = new XMLOutputter();
// display nice nice
xmlOutput.setFormat(Format.getPrettyFormat());
File f = new File(filename);
FileOutputStream outputFile = new FileOutputStream(f);
System.out.println("Speicher in : "+f.getAbsolutePath() );
xmlOutput.output(doc, outputFile);
outputFile.close();
System.out.println("File Saved!");
} catch (IOException io) {
System.out.println(io.getMessage());
}
}
//----------------------------------------------- Zeigerbewegungen --------------------------------------------------
/**
* liefert ein XML-Objekt, das auf den Vaterknoten des aktuellen Elements zeigt.
* @return Vater des aktuellen Objekts.
*/
public XML getParent() {
if(current != null) {
Element parent = current.getParentElement();
if (parent == null) {
return null;
} else {
return new XML(doc, parent);
}
}
return null;
}
/**
* Überprüft, ob das Element irgendwelche Kinder hat oder nicht, und gibt das Ergebnis als boolean zurück.
* @return true, wenn Kinder vorhanden sind, sonst false
*/
public boolean hasChildren() {
if (current == null) {
return doc.hasRootElement();
} else {
return current.getChildren().size()>0;
}
}
/**
* Ermittelt die Namen aller Kinder des Elements und gibt die Namen als ein Array von Strings zurück.
* Dies ist dasselbe wie das Durchlaufen und Aufrufen von getName() auf jedem untergeordneten Element einzeln.
* @return Liste aller Namen der Kinder
*/
public String[] listChildren() {
if (current == null) {
if(doc.hasRootElement()) {
String[] names = new String[0];
names[0] = doc.getRootElement().getName();
return names;
} else {
return null;
}
} else {
List<Element> ch_element = current.getChildren();
String[] names = new String[ch_element.size()];
for(int i=0; i < ch_element.size() ; i++) {
names[i] = ch_element.get(i).getName();
}
return names;
}
}
/**
* Liefert alle Kinder des Elements als Array von XML-Objekten.
* @return Array der Kinder als XML-Objekte
*/
public XML[] getChildren() {
if (current == null) {
if(doc.hasRootElement()) {
XML[] ch_xml = new XML[1];
ch_xml[0] = new XML(doc, doc.getRootElement());
return ch_xml;
} else {
return null;
}
} else {
List<Element> ch_element = current.getChildren();
XML[] ch_xml = new XML[ch_element.size()];
for(int i=0; i < ch_element.size() ; i++) {
ch_xml[i] = new XML(doc, ch_element.get(i));
}
return ch_xml;
}
}
/**
* Liefert bestimmte Kinder des Elements als Array von XML-Objekten.
* Die Methode gibt dabei alle Kinder zurück, die dem angegebenen Namen entsprechen.
* @param name Name der gesuchten Kind-Objekte
* @return Array der Kinder als XML-Objekte
*/
public XML[] getChildren(String name) {
if (current == null) {
if(doc.hasRootElement()) {
XML[] ch_xml = new XML[1];
ch_xml[0] = new XML(doc, doc.getRootElement());
if(doc.getRootElement().getName().equals(name)){
return ch_xml;
} else {
return null;
}
} else {
return null;
}
} else {
List<Element> ch_element = current.getChildren(name);
XML[] ch_xml = new XML[ch_element.size()];
for(int i=0; i < ch_element.size() ; i++) {
ch_xml[i] = new XML(doc, ch_element.get(i));
}
return ch_xml;
}
}
/**
* Liefert das erste Kind des Elements mit einem bestimmten Namen.
* Die Methode gibt das erste Kind zurück, das dem angegebenen Namen entsprechen.
* @param name Name des gesuchten Kind-Objektes
* @return Kind als XML-Objekt
*/
public XML getChild(String name) {
if (current == null) {
Element e = doc.getRootElement();
if (e.getName().equals(name)) {
return new XML(doc, e);
} else {
return null;
}
} else {
String[] names = name.split("/");
Element e = current;
int i = 0;
while(i < names.length) {
e = e.getChild(names[i]);
if (e==null) return null;
i++;
}
return new XML(doc, e);
}
}
/**
* Liefert das i. Kind des Elements.
* Die Methode gibt das i. Kind des aktuellen Elements zurück.
* @param i Nummer des Kindes
* @return Kind als XML-Objekt
*/
public XML getChild(int i) {
if (current == null) {
return new XML(doc, doc.getRootElement());
} else {
List<Element> ch_element = current.getChildren();
if (i>=ch_element.size()) return null;
return new XML(doc, ch_element.get(i));
}
}
//--------------------------------------------------- Methoden für das aktuelle Element -------------------------------------------------
/**
* Frage den Namen des aktuellen Elements ab
* @return Namen des Elements
*/
public String getName() {
if (current==null) return "";
return current.getName();
}
/**
* Setze den Namen des aktuellen Elements.
* @param name Neuer Name des Elements
*/
public void setName(String name) {
if (current==null) return;
current.setName(name);
}
/**
* liefert die Anzahl der Attribute eines Elements.
* @return Anzahl des Attribute
*/
public int getAttributeCount() {
if (current == null) return 0;
return current.getAttributes().size();
}
/**
* liefert zurück, ob das aktuelle Element Attribute hat .
* @return true, wenn es Attribute gibt
*/
public boolean hasAttribute() {
if (current == null) return false;
return current.getAttributes().size()>0;
}
/**
* Ruft alle Attribute des angegebenen Elements ab und gibt sie als Array von Strings zurück.
* @return Liste der Attributnamen
*/
public String[] listAttributes() {
if (current == null) return null;
List<Attribute> attr = current.getAttributes();
String[] names = new String[attr.size()];
for(int i=0; i < attr.size() ; i++) {
names[i] = attr.get(i).getName();
}
return names;
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs
*/
public String getString(String attribute) {
if (current==null) return "";
return current.getAttributeValue(attribute);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs
*/
public String getString(String attribute, String defaultValue) {
if (current==null) return defaultValue;
return current.getAttributeValue(attribute,defaultValue);
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param text neuer Wert des Attributs
*/
public void setString(String attribute, String text) {
if (current==null) return;
current.setAttribute(attribute, text);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs als Integer-Zahl
*/
public int getInt(String attribute) {
if (current==null) return 0;
try{
int i = Integer.parseInt(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return 0; }
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs als Integer-Zahl
*/
public int getInt(String attribute, int defaultValue) {
if (current==null) return defaultValue;
try{
int i = Integer.parseInt(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param value neuer Wert des Attributs
*/
public void setInt(String attribute, int value) {
if (current==null) return;
current.setAttribute(attribute, ""+value);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs als Float-Zahl
*/
public float getFloat(String attribute) {
if (current==null) return 0;
try{
float i = Float.parseFloat(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return 0; }
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs als Float-Zahl
*/
public float getFloat(String attribute, float defaultValue) {
if (current==null) return defaultValue;
try{
float i = Float.parseFloat(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param value neuer Wert des Attributs
*/
public void setFloat(String attribute, float value) {
if (current==null) return;
current.setAttribute(attribute, ""+value);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs als Double-Zahl
*/
public double getDouble(String attribute) {
if (current==null) return 0;
try{
double i = Double.parseDouble(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return 0; }
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs als double-Zahl
*/
public double getDouble(String attribute, double defaultValue) {
if (current==null) return defaultValue;
try{
double i = Double.parseDouble(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param value neuer Wert des Attributs
*/
public void setDouble(String attribute, double value) {
if (current==null) return;
current.setAttribute(attribute, ""+value);
}
/**
* Fragt den Inhalt/Text des aktuellen Elements ab
* @return Inhalt des Elements
*/
public String getContent() {
if ( current==null) return "";
return current.getText();
}
/**
* Fragt den Inhalt/Text des aktuellen Elements ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardtext
* @return Inhalt des Elements
*/
public String getContent(String defaultValue) {
if ( current==null) return defaultValue;
String t = current.getText();
if(t.equals("")) t = defaultValue;
return t;
}
/**
* Setzt den Inhalt/Text des aktuellen Elements
* @param text Neuer Inhalt des Elements
*/
public void setContent(String text) {
if ( current==null) return;
current.setText(text);
}
/**
* Fragt den Inhalt des aktuellen Elements als Integerzahl ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardwert
* @return Inhalt des Elements
*/ public int getIntContent(int defaultValue) {
if ( current==null) return defaultValue;
try{
int i = Integer.parseInt(current.getText());
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Fragt den Inhalt des aktuellen Elements als Integerzahl ab
* @return Inhalt des Elements
*/
public int getIntContent() {
if ( current==null) return 0;
try{
int i = Integer.parseInt(current.getText());
return i;
} catch(Exception e) { return 0; }
}
/**
* Setzt den Inhalt des aktuellen Elements
* @param value Neuer Inhalt des Elements
*/
public void setIntContent(int value) {
if ( current==null) return;
current.setText(""+value);
}
/**
* Fragt den Inhalt des aktuellen Elements als Floatzahl ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardwert
* @return Inhalt des Elements
*/
public float getFloatContent(float defaultValue) {
if ( current==null) return defaultValue;
try{
float i = Float.parseFloat(current.getText());
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Fragt den Inhalt des aktuellen Elements als Floatzahl ab
* @return Inhalt des Elements
*/
public float getFloatContent() {
if ( current==null) return 0;
try{
float i = Float.parseFloat(current.getText());
return i;
} catch(Exception e) { return 0; }
}
/**
* Setzt den Inhalt des aktuellen Elements
* @param value Neuer Inhalt des Elements
*/
public void setFloatContent(float value) {
if ( current==null) return;
current.setText(""+value);
}
/**
* Fragt den Inhalt des aktuellen Elements als Doublezahl ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardwert
* @return Inhalt des Elements
*/
public double getDoubleContent(double defaultValue) {
if ( current==null) return defaultValue;
try{
double i = Double.parseDouble(current.getText());
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Fragt den Inhalt des aktuellen Elements als Doublezahl ab
* @return Inhalt des Elements
*/
public double getDoubleContent() {
if ( current==null) return 0;
try{
double i = Double.parseDouble(current.getText());
return i;
} catch(Exception e) { return 0; }
}
/**
* Setzt den Inhalt des aktuellen Elements
* @param value Neuer Inhalt des Elements
*/
public void setDoubleContent(double value) {
if ( current==null) return;
current.setText(""+value);
}
// ----------------------------------------------- XML-Struktur aufbauen ------------------------------------------------
/** Erzeuge neues Element nach der aktuellen Position und setze dieses als aktuelles Element
* @param name Name des neuen Elements
* @return neues Element als XML-Objekt
*/
public XML addChild(String name) {
Element e = new Element(name);
if(current == null){ // man ist auf Root-Ebene
doc.setRootElement(e);
}
else {
current.addContent(e);
} // end of if-else
return new XML(doc, e);
}
/**
* liefert das aktuelle Element als jdom-Element-Objekt
* @return aktuelles Element
*/
private Element getCurrent() {
return current;
}
/**
* löscht ein Kind des aktuellen Knotens.
* Ist kid kein Kind des aktuellen Elements passiert gar nichts.
* @param kid XML-Objekt des Kindes
*/
public void removeChild(XML kid) {
if (current == null) return;
Element e = kid.getCurrent();
int index = current.indexOf(e);
if(index >= 0) { current.removeContent(e);}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -0,0 +1,90 @@
#Greenfoot project file
class.Balkendiagramm.image=balken.png
class.PictureViewer.image=bilderrahmen.png
dependency1.from=MyWorld
dependency1.to=Balkendiagramm
dependency1.type=UsesDependency
dependency2.from=PictureViewer
dependency2.to=Picture
dependency2.type=UsesDependency
dependency3.from=Table
dependency3.to=TableRow
dependency3.type=UsesDependency
dependency4.from=Picture
dependency4.to=PictureViewer
dependency4.type=UsesDependency
editor.fx.0.height=739
editor.fx.0.width=816
editor.fx.0.x=552
editor.fx.0.y=100
height=885
package.numDependencies=4
package.numTargets=7
project.charset=UTF-8
publish.hasSource=false
publish.locked=true
publish.longDesc=
publish.shortDesc=
publish.tags=
publish.title=
publish.url=
readme.height=58
readme.name=@README
readme.width=47
readme.x=10
readme.y=10
simulation.speed=97
target1.height=50
target1.name=PictureViewer
target1.showInterface=false
target1.type=ClassTarget
target1.width=100
target1.x=0
target1.y=0
target2.height=50
target2.name=Table
target2.showInterface=false
target2.type=ClassTarget
target2.width=80
target2.x=0
target2.y=0
target3.height=50
target3.name=Balkendiagramm
target3.showInterface=false
target3.type=ClassTarget
target3.width=120
target3.x=0
target3.y=0
target4.height=50
target4.name=Picture
target4.showInterface=false
target4.type=ClassTarget
target4.width=80
target4.x=0
target4.y=0
target5.height=50
target5.name=XML
target5.showInterface=false
target5.type=ClassTarget
target5.width=100
target5.x=0
target5.y=0
target6.height=50
target6.name=TableRow
target6.showInterface=false
target6.type=ClassTarget
target6.width=80
target6.x=0
target6.y=0
target7.height=50
target7.name=MyWorld
target7.showInterface=false
target7.type=ClassTarget
target7.width=80
target7.x=0
target7.y=0
version=3.0.0
width=1350
world.lastInstantiated=MyWorld
xPosition=449
yPosition=138

View file

@ -0,0 +1,75 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.Font;
/**
* Balkendiagramm für int-Array, Zahlen werden aus CSV-Datei gelesen.
*
* @author Schaller
* @version 29.11.18
*/
public class Balkendiagramm extends PictureViewer
{
// Liste mit allen Werten
// Deklariere ein Array zahlen für die Punkte und ein Array namen für die Spielernamen
//------------
// TODO
//------------
// Schriften
Font kleineSchrift;
Font grosseSchrift;
public Balkendiagramm() {
size(1000, 700);
background(0);
kleineSchrift = new Font( Font.SANS_SERIF, Font.PLAIN, 12 );
grosseSchrift = new Font( Font.SANS_SERIF, Font.PLAIN, 20 );
// CSV-Datei laden und anzeigen
ladeTabelle("punkte.csv");
zeichneBalken();
}
public void ladeTabelle(String name) {
// Tabelle aus CSV-Datei laden
Table csv = new Table(name,"header",',','"');
// Initialisiere Arrays, in die alle Zeilen der Tabelle passen
// Die Anzahl der gespeicherten Zeilen bekommt man mit csv.getRowCount()
//------------
// TODO
//------------
// Fülle die Arrays mit Werten aus der Tabelle
// Mit csv.getInt(zeilennummer, "Name der Spalte") oder csv.getInt(zeilennummer, spaltennummer)
// bekommt man die Werte der Tabelleneinträge als Integer-Wert
// Informiere dich unter https://processing.org/reference/Table.html, welche Methode geeignet ist,
// um die Namen der Spieler als String zu bekommen. getInt hilft hier nicht weiter.
//------------
// TODO
//------------
}
public void zeichneBalken() {
clear();
// Überschrift
fill(255,255,255);
textFont(grosseSchrift);
text("Punkte", 2, 20);
textFont(kleineSchrift);
// Alle Einträge darstellen
// lasse alle Ergebnisse der Spieler in der Form
// SpielerXY 234 XXXXXXXXXXXXXXXX
// SpielerZY 12 XX
// usw.
// darstellen. Wandle dazu dein Programm, um die Werte eines Arrays darzustelle ab.
//------------
// TODO
//------------
}
}

View file

@ -0,0 +1,36 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
/**
* Ergänzen Sie hier eine Beschreibung für die Klasse MyWorld.
*
* @author (Ihr Name)
* @version (eine Versionsnummer oder ein Datum)
*/
public class MyWorld extends World
{
/**
* Konstruktor für Objekte der Klasse MyWorld
*
*/
public MyWorld()
{
// Erstellt eine neue Welt mit 1200x900 Pixeln
super(1000, 700, 1);
prepare();
}
/**
* Bereite die Welt für den Programmstart vor.
* Das heißt: Erzeuge die Anfangs-Objekte und füge sie der Welt hinzu.
*/
private void prepare()
{
Balkendiagramm balkendiagramm = new Balkendiagramm();
addObject(balkendiagramm,500,350);
}
}

View file

@ -0,0 +1,699 @@
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.util.Vector;
import javax.imageio.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
import java.awt.geom.AffineTransform;
/**
*
* Bildklasse für die Simulation von Processing-Befehlen
*
* Diese Klasse stellt ein BufferedImage bereit, in das mit Processing-Befehlen gezeichnet
* werden kann.
* Zusätzlich kann ein Bildanzeiger über jede Änderung des Bildes informiert werden,
* um "Zurück"-Befehle zu ermöglichen. Der Bildanzeiger ist entweder eine normale Java
* ScrollPane oder ein Actor aus Greenfoot.
* Die Dokumentation der einzelnen Zeichenmethoden ist der Processing-Reference
* (https://processing.org/reference/ steht unter CC-Lizenz: https://creativecommons.org/)
* entnommen und mit Deepl.com ins Deutsche übersetzt.
*
* @version 1.0 from 23.01.2019
* @author Thomas Schaller (ZPG Informatik Klasse 9)
*/
public class Picture{
// Einstellungmöglichkeiten für das Zeichnen von Rechtecken und Ellipsen
// RADIUS = Mittelpunkt+Radius wird gegeben, CENTER = Mittelpunkt und Breite/Höhe wird gegeben,
// CORNER = Linke obere Ecke + Breite/Höhe, CORNERS = Linke obere und rechte untere Ecke
public static final int RADIUS = 1;
public static final int CENTER = 2;
public static final int CORNER = 3;
public static final int CORNERS = 4;
// gespeichertes Bild,
private BufferedImage image;
// aktuelle Farbeinstellungen
private Color background;
private Color pencolor;
private Color fillcolor;
// aktuelle Stiftdicke
private double stroke;
// akkteller Koordinatenmodus von Rechtecken und Ellipsen
private int ellipseMode = CENTER;
private int rectMode = CORNER;
// aktueller Font
private Font textfont = null;
// muss ein Bildanzeiger benachrichtigt werden
private PictureViewer observer = null;
private boolean autorefresh = true;
/**
* Erzeugt ein Bild mit Standardgröße 500x400
*/
public Picture() {
this(500,400);
}
/**
* Erzeugt ein Bild der angegeben Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public Picture(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein Bild aus einer Datei
* @param filename Dateiname des Bildes
*/
public Picture(String filename) {
load(filename);
}
/**
* Erzeugt ein Bild der angegebenen Größe mit festgelegtem Hintergrund
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds
*/
public Picture(int width, int height, String background) {
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
this.background = decode(background);
this.pencolor = new Color(0,0,0);
this.stroke = 1;
this.fillcolor = null;
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(this.background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Legt fest, wer das Bild anzeigt.
* Diese ermöglicht die Benachrichtung des Observers, wenn sich das Bild ändert.
* @param observer Anzeiger des Bildes
*/
public void setObserver(PictureViewer observer) {
this.observer= observer;
}
/**
* Direktes Setzen des Bildes (für interne Zwecke)
* @param b Bild, das gespeichert werden soll.
*/
public void setImage(BufferedImage b) {
image = b;
}
/**
* Direktes Abfragen des Bildes (für interne Zwecke)
* @return Bild, das gerade gespeichert ist.
*/
public BufferedImage getImage() {
return image;
}
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
pushImage();
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,width-1, height-1);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getWidth() {
return image.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getHeight() {
return image.getHeight();
}
/**
* Erzeugt eine Kopie des Bildes und übergibt sie an den Observer (falls existent), damit dieser die Versionen speichern kann
*/
private void pushImage() {
if(observer != null) {
observer.pushImage();
}
}
/**
* Legt fest, ob nach jedem Zeichenbefehl automatisch das Bild auch in
* der Oberfläche aktualisiert wird. Die Einstellung "false" beschleunigt
* das Zeichnen aufwändiger Bilder und verhindert "Flackern".
* Das Neuzeichnen kann durch die Methode "refresh" gezielt ausgelöst werden.
* @param autorefresh true = nach jedem Zeichenbefehl die Anzeige aktualisieren, false= nur durch die Methode refresh neu zeichnen
*/
public void setAutoRefresh(boolean autoRefresh) {
this.autorefresh = autoRefresh;
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
private void repaint() {
if(observer != null && autorefresh) {
observer.repaint();
}
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
public void refresh() {
if(observer != null) {
observer.repaint();
}
}
// ----------------------------------------- Zeichenfunktionen -----------------------------------------------
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
pushImage();
image = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
Graphics2D g = (Graphics2D) this.image.getGraphics();
g.setColor(background);
g.fillRect(0,0,image.getWidth()-1, image.getHeight()-1);
repaint();
}
/**
* Konvertiert die in einem bestimmten Modus gegebenen Koordinaten in die Java-übliche Links_Oben_Breite_Höhe Version
* Die Änderungen werden direkt im Array vorgenommen
* @param coord Array mit vier Koordinateneinträgen im gegebenen Modus
* @param mode Modus der Koordinaten (CORNER, CORNERS, RADIUS oder CENTER)
*/
private void convert(int[] coord, int mode) {
switch(mode) {
case CORNER: break;
case CORNERS: coord[2] -= coord[0]; coord[3] -= coord[1]; break;
case RADIUS: coord[2] *= 2; coord[3] *=2;
case CENTER: coord[0] -= coord[2]/2; coord[1] -= coord[3]/2;
}
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
rectMode = mode;
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
ellipseMode = mode;
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if (stroke > 0) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawLine(x1, y1, x2, y2);
}
repaint();
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, rectMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillRect(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawRect(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
int[] coord = {a,b,c,d};
convert(coord, ellipseMode);
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillOval(coord[0], coord[1], coord[2], coord[3]);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawOval(coord[0], coord[1], coord[2], coord[3]);
}
repaint();
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
int px[] = {x1, x2, x3};
int py[] = {y1, y2, y3};
polygon(px, py);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
int px[] = {x1, x2, x3, x4};
int py[] = {y1, y2, y3, y4};
polygon(px, py);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(fillcolor != null) {
g.setColor(fillcolor);
g.fillPolygon(x,y, y.length);
}
if(pencolor != null) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
g.drawPolygon(x, y, x.length);
}
repaint();
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
ellipse(x,y,1, 1);
}
// ----------------------------------------- Schriftdarstellung -----------------------------------------------
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param s Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String s, int x, int y) {
pushImage();
Graphics2D g = (Graphics2D) image.getGraphics();
if(pencolor != null) {
g.setColor(fillcolor);
g.setStroke(new BasicStroke((float) stroke));
g.setFont(textfont);
g.drawString(s, x, y);
}
repaint();
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
this.textfont = font;
}
// ----------------------------------------- Farbfestlegungen -----------------------------------------------
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(String color) {
try{
return new Color(
Integer.valueOf( color.substring( 0, 2 ), 16 ),
Integer.valueOf( color.substring( 2, 4 ), 16 ),
Integer.valueOf( color.substring( 4, 6 ), 16 ) );
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Hilfsfunktion zur Interpretation von Farben
*/
private Color decode(int color) {
try{
if(color >=0 && color < 256) {
return new Color(color,color,color);
} else {
int r = color / 0x010000 % 0xFF;
int g = color / 0x000100 % 0xFF;
int b = color % 0xFF;
System.out.println(""+r+","+g+","+b);
return new Color(r, g, b );
}
} catch (Exception e) {
System.out.println("Falscher Farbcode");
return Color.BLACK;
}
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
this.pencolor = decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
this.pencolor=decode(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
this.pencolor = new Color(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
this.pencolor = null;
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
this.stroke = width;
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
this.fillcolor = decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
this.fillcolor=decode(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
this.fillcolor = new Color(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
this.fillcolor = null;
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
if(c < 256) {
this.background=new Color(c,c,c);
} else {
int r = c / 0x010000;
int g = c / 0x000100 % 0xFF;
int b = c % 0xFF;
this.background= new Color(r, g, b );
}
this.clear();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
this.background=new Color(r,g,b);
this.clear();
}
// ----------------------------------------- Dateioperationen -----------------------------------------------
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
try{
this.image = ImageIO.read(new File(filename));
this.background = decode("D0D0D0");
this.pencolor = new Color(0,0,0);
this.fillcolor = null;
this.stroke = 1;
this.repaint();
} catch(Exception e) {
System.out.println("Fehler beim Einlesen der Bilddatei");
}
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
try{
String[] fn = filename.split("\\.");
if (fn.length== 1) {
ImageIO.write(image, "PNG", new File(filename+".png"));
} else {
if (fn.length == 2 && (fn[1].toUpperCase().equals("PNG") ||
fn[1].toUpperCase().equals("GIF"))){
ImageIO.write(image, fn[1], new File(filename));
}else {
System.out.println("Unbekanntes Bildformat");
}
}
} catch(Exception e) {
System.out.println("Fehler beim Speichern");
}
}
// ----------------------------------------- Sonstiges -----------------------------------------------
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
Color[][] pixel = new Color[image.getWidth()][image.getHeight()];
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
pixel[x][y] = new java.awt.Color(image.getRGB(x,y));
}
}
return pixel;
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
size(pixel.length,pixel[0].length);
Graphics2D g = (Graphics2D) image.getGraphics();
for(int x=0; x < image.getWidth(); x++){
for(int y=0; y < image.getHeight(); y++) {
g.setColor(pixel[x][y]);
g.fillRect(x, y, 1, 1);
}
}
repaint();
}
/**
* Hilfsfunktion zum Verzögern der Ausgabe
* @param millis Wartezeit in Millisekunden
*/
public void delay(int millis) {
try{
Thread.sleep(millis);
} catch(Exception e) {
}
}
}

View file

@ -0,0 +1,499 @@
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot und MouseInfo)
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.BasicStroke;
import java.awt.Font;
import java.util.Vector;
import java.awt.Color;
import javax.imageio.*;
import java.io.*;
/**
* Der PictureViewer ist ein Actor, der in der Lage ist ein
* Objekt der Klasse Picture anzuzeigen. Zusätzlich können
* mehrere Verarbeitungsschritte gespeichert werden, um ein
* "zurück"-Funktion zu ermöglichen.
*
* @author Thomas Schaller
* @version V1.0 vom 10.02.2019
*/
public class PictureViewer extends Actor
{
public static final int FIT = -1;
public static final int NORMAL = 1;
private static final int ANZ_BACK = 0;
private double zoom;
protected Picture picture = null;
private Vector<BufferedImage> history;
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der Größe 500x400
*/
public PictureViewer() {
this(500,400);
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public PictureViewer(int width, int height) {
this(width,height, "D0D0D0");
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild der angegebenen Größe
* @param width Breite des Bildes
* @param height Höhe des Bildes
* @param background Farbe des Hintergrunds als HEX-String (z.B. "FF3A45")
*/
public PictureViewer(int width, int height, String background) {
picture = new Picture(width,height, background);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Erzeugt ein ScrollPanel mit integriertem Bild aus einer Bilddatei
* @param filename Name des Bildes
*/
public PictureViewer(String filename) {
picture = new Picture(filename);
picture.setObserver(this);
this.history = new Vector<BufferedImage>();
this.zoom = NORMAL;
repaint();
}
/**
* Speichert das übergebene Bild in der History.
* @param b zu speicherndes Bild
*/
public void pushImage() {
if( this.ANZ_BACK > 0) {
if(history.size() == this.ANZ_BACK) {
history.removeElementAt(0);
}
BufferedImage b = new BufferedImage(picture.getWidth(), picture.getHeight(), picture.getImage().getType());
Graphics g = b.getGraphics();
g.drawImage(picture.getImage(), 0, 0, null);
g.dispose();
history.add(b);
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
private void popImage() {
int anz = history.size();
if(anz>0) {
BufferedImage i = history.get(anz-1);
history.removeElementAt(anz-1);
picture.setImage(i);
repaint();
}
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
public void back() {
popImage();
}
/**
* Setzt den Zoom-Faktor für das Bild.
* Als Zoomfaktor sind auch die Konstanten Bildanzeiger.FIT (auf Bildschirmgröße zoomen) und Bildanzeiger.NORMAL (100%) möglich.
* @param factor Zoomfaktor (1.0 = 100%).
*/
public void setZoom(double zoom) {
this.zoom = zoom;
repaint();
}
/**
* Setzt die automatische Neuanzeige des Bildes.
* Mit dieser Methode kann man einstellen, ob nach jedem Zeichenbefehl
* die Anzeige auf dem Bildschirm aktualisiert werden soll. Bei sehr
* vielen Zeichenbefehlen wird die Ausgabe dadurch sehr langsam. Es reicht
* eine Anzeige am Ende der Zeichenbefehle. Rufen Sie dann für das Neuzeichnen
* die Methode refresh() auf.
* @param autoRefresh true, wenn nach jedem Zeichenbefehl die Anzeige aktualisiert werden soll.
*/
public void setAutoRefresh(boolean autoRefresh) {
picture.setAutoRefresh(autoRefresh);
}
/**
* Sorgt für die Aktualisierung der Bildschrimanzeige. Das aktuelle Bild
* wird dadurch angezeigt. Durch Einstellung von autoRefresh kann die
* Anzeige automatisiert werden.
*/
public void refresh() {
repaint();
}
/**
* Setzt das angezeigt Bild neu und beachtet dabei den Zoomfaktor.
*/
public void repaint() {
double faktor = zoom;
if (zoom == FIT) {
double faktorw = (double) this.getWorld().getWidth() / picture.getWidth();
double faktorh = (double) this.getWorld().getHeight() / picture.getHeight();
faktor = Math.min(faktorw, faktorh);
}
int gfi_width = (int) (picture.getWidth()*faktor);
int gfi_height = (int) (picture.getHeight()*faktor);
setImage(new GreenfootImage(gfi_width, gfi_height));
Graphics2D g = (Graphics2D) this.getImage().getAwtImage().getGraphics();
g.drawImage(picture.getImage(),0,0,gfi_width, gfi_height, 0, 0, picture.getWidth(), picture.getHeight(), null);
g.setColor(new java.awt.Color(0,0,0));
g.setStroke(new BasicStroke((float) 1));
g.drawRect(0,0,gfi_width-1, gfi_height-1);
}
// Wrappermethoden
/**
* Definiert die Dimension der Breite und Höhe des Anzeigefensters in Pixeleinheiten.
* Die eingebauten Variablen Breite und Höhe werden durch die an diese Funktion übergebenen Parameter festgelegt. So weist beispielsweise
* der Befehl size(640, 480) der Variablen Breite 640 und der Variablen Höhe 480 zu.
* @param width Breite des Bildes
* @param height Höhe des Bildes
*/
public void size(int width, int height){
picture.size(width, height);
}
/**
* Liefert die Breite des Bildes zurück.
* @return Breite des Bildes
*/
public int getImageWidth() {
return picture.getWidth();
}
/**
* Liefert die Höhe des Bildes zurück.
* @return Höhe des Bildes
*/
public int getImageHeight() {
return picture.getHeight();
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param c Farbe für den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void background(int c) {
picture.background(c);
}
/**
* Die Funktion background() setzt die Farbe, die für den Hintergrund des Bildes verwendet wird. Der Standardhintergrund ist hellgrau.
* Es ist nicht möglich, den Alpha-Parameter Transparenz mit Hintergrundfarben auf der Hauptzeichnungsoberfläche zu verwenden.
* @param r Rotanteil (0-255) der Hintergrundfarbe
* @param g Grünanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
public void background(int r, int g, int b) {
picture.background(r,g,b);
}
/**
* Zeichnet eine Linie (einen direkten Weg zwischen zwei Punkten) auf den Bildschirm.
* Um eine Linie einzufärben, verwenden Sie die {@link #stroke(int, int, int) stroke()} Funktion. Eine Zeile kann nicht gefüllt werden, daher hat die Funktion fill() keinen
* Einfluss auf die Farbe einer Zeile. Linien werden standardmäßig mit einer Breite von einem Pixel gezeichnet, dies kann jedoch mit der Funktion
* {@link #strokeWeight(double) strokeWeight()} geändert werden.
* @param x1 x-Koordinate des 1. Punktes
* @param y1 y-Koordinate des 1. Punktes
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
public void line(int x1, int y1, int x2, int y2) {
picture.line(x1,y1,x2,y2);
}
/**
* Zeichnet ein Rechteck auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position der linken oberen Ecke fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #rectMode(int) rectMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param b meist die y-Koordinate der linken oberen Ecke (kann durch rectMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch rectMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch rectMode() geändert werden).
*
*/
public void rect(int a, int b, int c, int d) {
picture.rect(a,b,c,d);
}
/**
* Zeichnet eine Ellipse/Kreis auf das Bild.
* Standardmäßig legen die ersten beiden Parameter die Position des Mittelpunkts fest, der dritte die Breite und der vierte die Höhe.
* Die Art und Weise, wie diese Parameter interpretiert werden, kann jedoch mit der Funktion {@link #ellipseMode(int) ellipseMode()} geändert werden.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param a meist die x-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param b meist die y-Koordinate des Mittelpunkts (kann durch ellipseMode() geändert werden).
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geändert werden).
* @param d meist die Höhe des Rechtecks (kann durch ellipseMode() geändert werden).
*
*/
public void ellipse(int a, int b, int c, int d) {
picture.ellipse(a,b,c,d);
}
/**
* Zeichnet ein Dreieck auf das Bild.
* Ein Dreieck ist eine Ebene, die durch die Verbindung von drei Punkten entsteht. Die ersten beiden Argumente spezifizieren den
* ersten Punkt, die mittleren beiden Argumente spezifizieren den zweiten Punkt und die letzten beiden Argumente spezifizieren den dritten Punkt.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
picture.triangle(x1,y1,x2,y2,x3,y3);
}
/**
* Zeichnet ein Viereck auf das Bild.
* Ein Viereck ist ein vierseitiges Polygon. Es ist ähnlich wie ein Rechteck, aber die Winkel zwischen seinen Kanten
* sind nicht auf neunzig Grad beschränkt. Das erste Paar von Parametern (x1,y1) setzt den ersten Scheitelpunkt und die nachfolgenden
* Paare sollten im Uhrzeigersinn oder gegen den Uhrzeigersinn um die definierte Form herum verlaufen.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x1 meist die x-Koordinate des 1. Punkts.
* @param y1 meist die y-Koordinate des 1. Punkts.
* @param x2 meist die x-Koordinate des 2. Punkts.
* @param y2 meist die y-Koordinate des 2. Punkts.
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
picture.quad(x1,y1,x2,y2,x3,y3,x4,y4);
}
/**
* Zeichnet ein Polygon auf das Bild.
* Gleich lange Listen von x und y-Koordinaten bestimmen die Eckpunkte des Polygons.
* Durch den Befehl {@link #fill(int,int,int) fill()} /{@link #noFill() noFill()} kann die Füllfarbe des Rechtecks gewählt werden, durch {@link #stroke(int, int, int) stroke()}/{@link #noStroke() noStroke()} die Rahmenfarbe.
* @param x Liste der x-Koordinaten der Punkte.
* @param y Liste der y-Koordinaten der Punkte.
*/
public void polygon(int[] x, int[] y) {
picture.polygon(x,y);
}
/**
* Zeichnet einen Punkt, d.h. einen Kreis in der Dimension eines Pixels.
* Der erste Parameter ist der x-Wert für den Punkt, der zweite Wert ist der y-Wert für den Punkt.
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
public void point(int x, int y) {
picture.point(x,y);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Rechtecken.
* Ändert die Position, von der aus Rechtecke gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an rect() übergeben werden, interpretiert werden.
* Der Standardmodus ist rectMode(Bild.CORNER), der die ersten beiden Parameter von rect() als die linke obere Ecke der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von rect() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* rectMode(Bild.CENTER) interpretiert die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* rectMode(RADIUS) verwendet auch die ersten beiden Parameter von rect() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void rectMode(int mode) {
picture.rectMode(mode);
}
/**
* Ändert den Koordinaten-Modus beim Zeichnen von Kreisen/Ellipsen.
* Ändert die Position, von der aus Kreise/Ellipsen gezeichnet werden, indem es die Art und Weise ändert, wie Parameter, die an ellipse() übergeben werden, interpretiert werden.
* Der Standardmodus ist ellipseMode(Bild.CENTER), der die ersten beiden Parameter von ellipse() als Mittelpunkt der Form interpretiert,
* während der dritte und vierte Parameter seine Breite und Höhe sind.
* ellipseMode(Bild.CORNER) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als Breite und Höhe der Form.
* ellipseMode(Bild.CORNERS) interpretiert die ersten beiden Parameter von ellipse() als die Position einer Ecke
* und die dritten und vierten Parameter als die Position der gegenüberliegenden Ecke.
* ellipseMode(RADIUS) verwendet auch die ersten beiden Parameter von ellipse() als Mittelpunkt der Form,
* verwendet aber den dritten und vierten Parameter, um die Hälfte der Breite und Höhe der Formen festzulegen.
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
public void ellipseMode(int mode) {
picture.ellipseMode(mode);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
public void stroke(String pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void stroke(int pencolor) {
picture.stroke(pencolor);
}
/**
* Legt die Farbe fest, mit der Linien und Ränder um Formen gezeichnet werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben
* @param r Rotanteil (0-255) der Stiftfarbe
* @param g Grünanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
public void stroke(int r, int g, int b) {
picture.stroke(r,g,b);
}
/**
* Legt fest, dass keine Linien oder Ränder um Formen gezeichnet werden soll.
*/
public void noStroke() {
picture.noStroke();
}
/**
* Legt die Breite des Strichs für Linien, Punkte und den Rand um Formen fest.
* Alle Breiten werden in Pixeleinheiten angegeben.
* @param width Breite in Pixel
*/
public void strokeWeight(double width) {
picture.strokeWeight(width);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird hexadezimal in Form der RGB angegeben: z.B. "CCFFAA" oder "004E23". Die Syntax verwendet sechs Ziffern - je zwei für die roten, grünen und blauen Komponenten,
* um eine Farbe anzugeben (genau wie Farben typischerweise in HTML und CSS angegeben werden).
* @param fillcolor Füllfarbe in Hexadezimaldarstellung
*/
public void fill(String fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird entweder als Graustufe (0-255) oder als 3-Byte RGB-Wert angegeben.
* @param fillcolor Füllfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiß, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
public void fill(int fillcolor) {
picture.fill(fillcolor);
}
/**
* Legt die Farbe fest, mit der Formen gefüllt werden.
* Diese Farbe wird komponentenweise als RGB-Wert angegeben.
* @param r Rotanteil (0-255) der Füllfarbe
* @param g Grünanteil (0-255) der Füllfarbe
* @param b Blauanteil (0-255) der Füllfarbe
*/
public void fill(int r, int g, int b) {
picture.fill(r,g,b);
}
/** Legt fest, dass die Formen nicht gefüllt werden sollen.
*/
public void noFill() {
picture.noFill();
}
/**
* Löscht den Inhalt des Bildes.
* Der Hintergrund wird mit der Hintergrundfarbe neu gefüllt.
*/
public void clear(){
picture.clear();
}
/**
* Lädt ein Bild aus dem Dateisystem.
* Lädt ein Bild von einem Datenträger und setzt Stiftfarbe und Füllfarbe auf Standardwerte zurück.
* @param filename Dateiname des Bildes
*/
public void load(String filename) {
picture.load(filename);
}
/**
* Speichert ein Bild.
* Speichert ein Bild auf einem Datenträger. Zulässig sind die Dateiformate PNG und GIF. Die Dateiendung legt den Typ fest.
* Standardmäßig wird die Dateiendung .png ergänzt, wenn keine angegeben ist.
* @param filename Dateiname des Bildes
*/
public void save(String filename) {
picture.save(filename);
}
/**
* Gibt einen Text an den gegebenen Koordinaten aus
* Zur Ausgabe des Textes wird der ausgewählte Font verwendet. Dieser muss vorher mit {@link #textFont(Font) textFont() } festgelegt.
* @param t Text, der angezeigt werden soll
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
public void text(String t, int x, int y) {
picture.text(t,x,y);
}
/**
* Legt die Schriftart für Textausgaben fest.
* Jeder übliche Java-Font kann verwendet werden. Er kann mit z.B. Font f = new Font( "Arial", Font.PLAIN, 14 ); definiert werden.
* @param font ein Font-Objekt
*/
public void textFont(Font font) {
picture.textFont(font);
}
/**
* Liefert das Bild als zweidimensionales Pixel-Array.
* @return zweidimensionales Array von Color-Objekten, die den Pixeln des Bildes entsprechen.
*/
public Color[][] getPixelArray() {
return picture.getPixelArray();
}
/**
* Setzt das Bild neu auf Basis des Pixel-Arrays.
* Die Größe des Bildes wird nicht automatisch an das Array angepasst.
* @param pixel zweidimensionales Array von Color-Objekten
*/
public void setPixelArray(Color[][] pixel) {
picture.setPixelArray(pixel);
}
}

View file

@ -0,0 +1,14 @@
------------------------------------------------------------------------
Dies ist die README-Datei des Projekts. Hier sollten Sie Ihr Projekt
beschreiben.
Erzählen Sie dem Leser (jemand, der nichts über dieses Projekt weiss),
alles, was er/sie wissen muss. Üblicherweise sollte der Kommentar
zumindest die folgenden Angaben umfassen:
------------------------------------------------------------------------
PROJEKTBEZEICHNUNG:
PROJEKTZWECK:
VERSION oder DATUM:
WIE IST DAS PROJEKT ZU STARTEN:
AUTOR(EN):
BENUTZERHINWEISE:

View file

@ -0,0 +1,894 @@
/**
* Die Klasse Table vereinfacht den Zugriff auf CSV-Dateien.
* Die Klassen Table und TableRow ermöglichen einen einfachen Zugriff auf tabellenbasierte
* Dokumente.
*
* @author Thomas Schaller
* @version 1.0 vom 01.02.2019
*/
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.util.Scanner;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
public class Table
{
// Standardtrennzeichen für Spalten
private static final char DEFAULT_SEPARATOR = ';';
// Standardmarkierung für Texte
private static final char DEFAULT_QUOTE = '"';
// Standardtrennzeichen für Dezimalzahlen
private static final char DEFAULT_COMMA = ',';
// mögliche Spaltentypen
private static final String UNKNOWN ="UNKOWN";
private static final String INT = "INTEGER";
private static final String DOUBLE = "DOUBLE";
private static final String FLOAT = "FLOAT";
// interne Verwaltung des Dokuments als JDOM-Document-Objekt
private Document doc;
// Verweis auf Element für Kopfzeile
private Element header;
// Ende Attribute
/**
* Erzeugt leeres Tabellen-Dokument.
*/
public Table() {
this.doc = new Document();
doc.setRootElement(new Element("CSV-Data"));
this.header = new Element("Header");
doc.getRootElement().addContent(header);
}
/**
* Erzeugt Tabellen-Dokument aus einer CSV-Datei.
* Liest den Inhalt einer Datei und erstellt ein Tabellenobjekt mit seinen Werten.
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
* @param separator Trennzeichen für Spalten (meist ';' oder ',' oder '\t' für Tab)
* @param quote Kennung für Texte (meist '"').
*/
public Table(String filename, String options, char separator, char quote) {
loadCSV(filename, options, separator, quote);
}
/**
* Erzeugt Tabellen-Dokument aus einer CSV-Datei.
* Liest den Inhalt einer Datei und erstellt ein Tabellenobjekt mit seinen Werten (Separator = ';', Kennung für Text = '"').
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
*/
public Table(String filename, String options) {
loadCSV(filename, options);
}
/**
* Erzeugt Tabellen-Dokument aus einer CSV-Datei.
* Liest den Inhalt einer Datei ohne Kopfzeile und erstellt ein Tabellenobjekt mit seinen Werten (Separator = ';', Kennung für Text = '"').
* @param filename Dateiname der CSV-Datei.
*/
public Table(String filename) {
loadCSV(filename);
}
// Anfang Methoden
/**
* Liest den Inhalt einer CSV-Datei ohne Kopfzeile (Separator = ';', Kennung für Text = '"').
* @param filename Dateiname der CSV-Datei.
*/
public void loadCSV(String filename) {
loadCSV(filename, "");
}
/**
* Liest den Inhalt einer CSV-Datei (Separator = ';', Kennung für Text = '"').
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
*/
public void loadCSV(String filename, String options) {
loadCSV(filename, options, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
}
/**
* Liest den Inhalt einer CSV-Datei.
* Wenn die Datei eine Kopfzeile enthält, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile hat,
* dann lassen Sie einfach die Option "header" weg.
* @param filename Dateiname der CSV-Datei.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile enthält.
* @param separator Trennzeichen für Spalten (meist ';' oder ',' oder '\t' für Tab)
* @param quote Kennung für Texte (meist '"').
*/
public void loadCSV(String filename, String options, char separator, char quote) {
doc = new Document();
doc.setRootElement(new Element("CSV-Data"));
header = new Element("Header");
doc.getRootElement().addContent(header);
try {
File f = new File(filename);
Scanner scanner = new Scanner(new File(filename));
if(options.toLowerCase().contains("header") && scanner.hasNext()) {
List<String> entries = parseLine(scanner.nextLine(), separator, quote);
int i= 0;
for(String s : entries) {
Element entry = new Element("Column");
header.addContent(entry);
entry.setText(s);
entry.setAttribute("type", "unknown");
i++;
}
}
List<Element> cols = header.getChildren();
while (scanner.hasNext()) {
Element line = new Element("Row");
doc.getRootElement().addContent(line);
List<String> entries = parseLine(scanner.nextLine(), separator, quote);
int i= 0;
for(String s : entries) {
if(i==cols.size()) {
Element entry = new Element("Column");
entry.setAttribute("type", "unknown");
header.addContent(entry);
cols = header.getChildren();
}
Element entry = new Element("Entry");
entry.setText(s);
line.addContent(entry);
i++;
}
}
scanner.close();
} catch (Exception e) {
System.out.println("Fehler beim Lesen der CSV-Datei");
}
}
/**
* Speichert das aktuelle Dokument als CSV-Datei ohne Kopfzeile (Separator = ';', Kennung für Text = '"').
* @param filename Dateiname der CSV-Datei.
*/
public void saveCSV(String filename) {
saveCSV(filename, "");
}
/**
* Speichert das aktuelle Dokument als CSV-Datei (Separator = ';', Kennung für Text = '"').
* Wenn die Datei eine Kopfzeile enthalten, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile haben soll,
* dann lassen Sie einfach die Option "header" weg.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile haben soll.
* @param filename Dateiname der CSV-Datei.
*/
public void saveCSV(String filename, String options) {
saveCSV(filename, options, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
}
/**
* Speichert das aktuelle Dokument als CSV-Datei.
* Wenn die Datei eine Kopfzeile enthalten, fügen Sie "header" in den Parameter options ein. Wenn die Datei keine Kopfzeile haben soll,
* dann lassen Sie einfach die Option "header" weg.
* @param options Geben Sie hier "header" an, wenn die Datei eine Kopfzeile haben soll.
* @param filename Dateiname der CSV-Datei.
* @param separator Trennzeichen für Spalten (meist ';' oder ',' oder '\t' für Tab)
* @param quote Kennung für Texte (meist '"').
*/
public void saveCSV(String filename, String options, char separator, char quote){
try{
File f = new File(filename);
PrintStream outputFile = new PrintStream (f);
System.out.println("Speicher in : "+f.getAbsolutePath());
List<Element> columns = header.getChildren();
String sq = ""+quote;
String ss = ""+separator;
if(quote =='"') sq = "\"";
if(separator =='"') ss = "\"";
if(options.toLowerCase().contains("header")) {
String h = "";
for(Element c : columns) {
h += ss + sq + c.getText()+sq;
}
outputFile.println(h.substring(1));
}
for(int i = 0; i<getRowCount(); i++) {
String l = "";
for(String s: getStringRow(i)) {
if(s.contains(""+separator)) {
if(quote == '"' && s.contains("\"")) {
s = s.replace("\"","\"\"");
}
l += ss + sq + s+sq;
} else {
l += ss+s;
}
}
outputFile.println(l.substring(1));
}
outputFile.close();
}
catch(Exception e) {
System.out.println("Fehler beim Schreiben der Datei");
}
}
/** Speichert die Tabelle als XML-Dokument.
* @param filename Dateiname des XML-Files
*/
public void saveXML(String filename) {
try {
// new XMLOutputter().output(doc, System.out);
XMLOutputter xmlOutput = new XMLOutputter();
// display nice nice
xmlOutput.setFormat(Format.getPrettyFormat());
File f = new File(filename);
FileOutputStream outputFile = new FileOutputStream(f);
System.out.println("Speicher in : "+f.getAbsolutePath() );
xmlOutput.output(doc, outputFile);
outputFile.close();
System.out.println("File Saved!");
} catch (IOException io) {
System.out.println(io.getMessage());
}
}
//----------------------------------------------- Zeigerbewegungen --------------------------------------------------
/** HIlfsfunktion für die Analyse einer Dateizeile
* @param cvsLine Zeile aus der Datei
* @return Liste von String für die einzelnen Spalten
*/
private List<String> parseLine(String cvsLine) {
return parseLine(cvsLine, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
}
/** HIlfsfunktion für die Analyse einer Dateizeile
* @param cvsLine Zeile aus der Datei
* @param sparator Trennzeichen für die Spalten
* @return Liste von String für die einzelnen Spalten
*/
private List<String> parseLine(String cvsLine, char separator) {
return parseLine(cvsLine, separator, DEFAULT_QUOTE);
}
/** HIlfsfunktion für die Analyse einer Dateizeile
* @param cvsLine Zeile aus der Datei
* @param sparator Trennzeichen für die Spalten
* @param customQuote Kennung für Strings
* @return Liste von String für die einzelnen Spalten
*/
private List<String> parseLine(String cvsLine, char separator, char customQuote) {
List<String> result = new ArrayList<>();
//if empty, return!
if (cvsLine == null && cvsLine.isEmpty()) {
return result;
}
//ggf. Default-Value laden
if (customQuote == ' ') {
customQuote = DEFAULT_QUOTE;
}
if (separator == ' ') {
separator = DEFAULT_SEPARATOR;
}
StringBuffer curVal = new StringBuffer();
boolean inQuotes = false;
boolean startCollectChar = false;
boolean doubleQuotesInColumn = false;
char[] chars = cvsLine.toCharArray();
for (char ch : chars) {
if (inQuotes) { // aktueller Text ist in Quotes eingeschlossen
startCollectChar = true;
if (ch == customQuote) { // Quotes werden beendet, aber Achtung bei "" => Metazeichen
inQuotes = false;
if (ch == '\"') {
doubleQuotesInColumn = true;
}
} else {
if (ch == '\"' && !doubleQuotesInColumn) {
doubleQuotesInColumn = true;
} else {
curVal.append(ch);
doubleQuotesInColumn = false;
}
}
} else {
if (ch == customQuote) {
inQuotes = true;
//Fixed : allow "" in empty quote enclosed
if (ch == '\"'){
if(doubleQuotesInColumn) {
curVal.append('"');
doubleQuotesInColumn = false;
} else doubleQuotesInColumn = true;
}
}
else {
doubleQuotesInColumn = false;
if (ch == separator) {
result.add(curVal.toString());
curVal = new StringBuffer();
startCollectChar = false;
} else if (ch == '\r') {
//ignore LF characters
continue;
} else if (ch == '\n') {
//the end, break!
break;
} else {
curVal.append(ch);
}
}
}
}
result.add(curVal.toString());
return result;
}
/**
* Sucht die Nummer einer durch Namen gegebenen Spalte.
* @param name Name der Spalte
* @return Nummer der Spalte
*/
private int findColumnNumber(String name) {
List<Element> columns = header.getChildren();
int i = 0;
for(Element c : columns) {
if (c.getText().toLowerCase().equals(name.toLowerCase())) {
return i;
}
i++;
}
return -1;
}
/**
* Fügt eine neue Spalte am Ende der Tabelle an.
*/
public void addColumn() {
Element entry = new Element("Column");
entry.setAttribute("type", Table.UNKNOWN);
header.addContent(entry);
}
/**
* Fügt eine neue Spalte am Ende der Tabelle an und benennt sie.
* @param title Bezeichnung der Spalte
*/
public void addColumn(String title) {
addColumn();
Element nc = ((List<Element>)(header.getChildren())).get(header.getChildren().size()-1);
nc.setText(title);
}
/**
* Fügt eine neue Spalte am Ende der Tabelle an und benennt und typisiert sie.
* @param title Bezeichnung der Spalte
* @param type Typ der Spalte (UNKNOWN, DOUBLE, INTEGER, FLOAT)
*/
public void addColumn(String title, String type) {
addColumn(title);
Element nc = ((List<Element>)(header.getChildren())).get(header.getChildren().size()-1);
nc.setAttribute("type", type);
}
/**
* Löscht eine Spalte.
* @param i Nummer der Spalte.
*/
public void removeColumn(int i) {
List<Element> lines = doc.getRootElement().getChildren();
for(Element l : lines) {
if(l.getChildren().size()>i) l.removeContent(i);
}
}
/**
* Löscht eine Spalte
* @param name Name der Spalte
*/
public void removeColumn(String name) {
try{
removeColumn(findColumnNumber(name));
} catch(Exception e) { System.out.println("Unbekannter Spaltenname");}
}
/**
* Liefert die Anzahl der Spalten in der Tabelle
* @return Anzahl der Spalten
*/
public int getColumnCount() {
return header.getChildren().size();
}
/**
* Liefert die Anzahl der Zeilen in der Tabelle
* @return Anzahl der Zeilen
*/
public int getRowCount() {
return doc.getRootElement().getChildren().size()-1;
}
/**
* Löscht alle Zeilen der Tabelle.
* Die Spaltenüberschriften und Typen bleiben erhalten.
*/
public void clearRows() {
doc.getRootElement().removeChildren("Row");
}
/**
* Fügt eine neue Zeile an das Ende der Tabelle an.
* @return ein TableRow-Objekt für diese neue Zeile
*/
public TableRow addRow() {
Element row = new Element("Row");
doc.getRootElement().addContent(row);
return new TableRow(doc, row);
}
/**
* Löscht eine Zeile
* @param i Nummer der Zeile
*/
public void removeRow(int i) {
if(i<getRowCount()) {
doc.getRootElement().removeContent(i);
}
}
/**
* Liefert eine Zeile der Tabelle
* @param i Nummer der Zeile
* @return TableRow-Objekt für diese Zeile
*/
public TableRow getRow(int i) {
if(i<getRowCount()) {
List<Element> rows = doc.getRootElement().getChildren();
return new TableRow(doc, rows.get(i+1));
}
return null;
}
/**
* Liefert die ganze Tabelle als Array von TableRow-Objekten
* @return Array von TableRow-Objekten
*/
public TableRow[] rows() {
TableRow[] rows = new TableRow[getRowCount()];
for(int i = 0; i < getRowCount(); i++) {
rows[i] = getRow(i);
}
return rows;
}
/**
* Liefert den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public int getInt(int row, int column) {
return getRow(row).getInt(column);
}
/**
* Liefert den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public int getInt(int row, String name) {
return getRow(row).getInt(name);
}
/**
* Setzt den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @param value neuer Wert der Zelle
*/
public void setInt(int row, int column,int value) {
getRow(row).setInt(column, value);
}
/**
* Setzt den Wert einer Zelle als Integer-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setInt(int row, String name, int value) {
getRow(row).setInt(name, value);
}
/**
* Liefert alle Werte einer Zeile als Integer-Array.
* @param row Nummer der Zeile
* @return int-Array, dass alle Werte der Zeile enthält
*/
public int[] getIntRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
int[] r = new int[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getInt(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Integer-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public int[] getIntColumn(int column) {
try{
int anz = getRowCount();
int[] r = new int[anz];
for(int i=0; i<anz; i++) {
r[i] = getInt(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Integer-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public int[] getIntColumn(String name) {
return getIntColumn(findColumnNumber(name));
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public float getFloat(int row, int column) {
return getRow(row).getFloat(column);
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public float getFloat(int row, String name) {
return getRow(row).getFloat(name);
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @param value neuer Wert der Zelle
*/
public void setFloat(int row, int column,float value) {
getRow(row).setFloat(column, value);
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setFloat(int row, String name, float value) {
getRow(row).setFloat(name, value);
}
/**
* Liefert alle Werte einer Zeile als Float-Array.
* @param row Nummer der Zeile
* @return int-Array, dass alle Werte der Zeile enthält
*/
public float[] getFloatRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
float[] r = new float[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getFloat(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Float-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public float[] getFloatColumn(int column) {
try{
int anz = getRowCount();
float[] r = new float[anz];
for(int i=0; i<anz; i++) {
r[i] = getFloat(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Float-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public float[] getFloatColumn(String name) {
return getFloatColumn(findColumnNumber(name));
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public double getDouble(int row, int column) {
return getRow(row).getDouble(column);
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public double getDouble(int row, String name) {
return getRow(row).getDouble(name);
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param column Spaltennummer
* @param value neuer Wert der Zelle
*/
public void setDouble(int row, int column,double value) {
getRow(row).setDouble(column, value);
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param row Zeilennummer
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setDouble(int row, String name, double value) {
getRow(row).setDouble(name, value);
}
/**
* Liefert alle Werte einer Spalte als Double-Array.
* @param row Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public double[] getDoubleRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
double[] r = new double[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getDouble(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Double-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public double[] getDoubleColumn(int column) {
try{
int anz = getRowCount();
double[] r = new double[anz];
for(int i=0; i<anz; i++) {
r[i] = getDouble(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als Double-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public double[] getDoubleColumn(String name) {
return getDoubleColumn(findColumnNumber(name));
}
/**
* Liefert den Wert einer Zelle als String
* @param row Zeilennummer
* @param column Spaltennummer
* @return Wert der Zelle
*/
public String getString(int row, int column) {
return getRow(row).getString(column);
}
/**
* Liefert den Wert einer Zelle als String
* @param row Zeilennummer
* @param name Name der Spalte
* @return Wert der Zelle
*/
public String getString(int row, String name) {
return getRow(row).getString(name);
}
/**
* Setzt den Wert einer Zelle als String
* @param row Zeilennummer
* @param column Spaltennummer
* @param text neuer Wert der Zelle
*/
public void setString(int row, int column,String text) {
getRow(row).setString(column, text);
}
/**
* Setzt den Wert einer Zelle als String
* @param row Zeilennummer
* @param name Name der Spalte
* @param text neuer Wert der Zelle
*/
public void setString(int row, String name, String text) {
getRow(row).setString(name, text);
}
/**
* Liefert alle Werte einer Spalte als String-Array.
* @param row Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public String[] getStringRow(int row) {
try{
TableRow trow = getRow(row);
int anz = getColumnCount();
String[] r = new String[anz];
for(int i=0; i<anz; i++) {
r[i] = trow.getString(i);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als String-Array.
* @param column Nummer der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public String[] getStringColumn(int column) {
try{
int anz = getRowCount();
String[] r = new String[anz];
for(int i=0; i<anz; i++) {
r[i] = getString(i, column);
}
return r;
} catch (Exception e) {
return null;
}
}
/**
* Liefert alle Werte einer Spalte als String-Array.
* @param name Name der Spalte
* @return int-Array, dass alle Werte der Spalte enthält
*/
public String[] getStringColumn(String name) {
return getStringColumn(findColumnNumber(name));
}
/**
* Sucht nach einem bestimmtem Wert in einer Zeile.
* @param value Wert der gesucht werden soll
* @param column Nummer der Spalte, die durchsucht werden soll
* @return TableRow-Objekt der Zeile, wenn der Wert gefunden wurde, sonst null
*/
public TableRow findRow(String value, int column) {
for(int i=0; i<getRowCount(); i++) {
if(getString(i,column).equals(value)){
return getRow(i);
}
}
return null;
}
/**
* Sucht nach einem bestimmtem Wert in einer Zeile.
* @param value Wert der gesucht werden soll
* @param name Name der Spalte, die durchsucht werden soll
* @return TableRow-Objekt der Zeile, wenn der Wert gefunden wurde, sonst null
*/
public TableRow findRow(String value, String name) {
return findRow(value, findColumnNumber(name));
}
/**
* Kürzt alle Einträge der Tabelle um unnötige Leerzeichen am Anfang oder Ende
*/
public void trim() {
for(int y=0; y<getRowCount(); y++) {
for (int x =0; x<getColumnCount(); x++) {
setString(y,x,getString(y,x).trim());
}
}
}
}

View file

@ -0,0 +1,312 @@
/**
* Repräsentiert eine Zeile eines Table-Objekts.
* Erlaubt einen einfachen Zugriff auf die einzelnen Einträge in dieser Zeile.
*
* @author Thomas Schaller
* @version V1.0 vom 01.02.2019
*/
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.util.Scanner;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
import java.text.NumberFormat;
public class TableRow
{
// Verweis auf das ganze Dokument
private Document doc;
// Verweis auf die Zeile, für die dieses Objekt steht
private Element current;
// Verweis auf die Kopfzeile
private Element header;
// Für die Interpretation von Zahlenwerten
NumberFormat format = NumberFormat.getInstance();
// Ende Attribute
/**
* Erzeugt ein TableRow-Objekt.
* Diese Methode ist für den internen Gebraucht. Einige Methode der Table-Klasse erzeugen mit diesem Konstruktor TableRow-Objekte.
* @param doc JDOM-Dokument, das für die ganze Tabelle steht.
* @param row JDOM-Element, das für die aktuelle Zeile steht.
*/
public TableRow(Document doc, Element row) {
this.doc = doc;
this.current = row;
this.header = doc.getRootElement().getChild("Header");
}
/**
* Liefert die Anzahl der Spalten der Zeile.
* @return Anzahl der Spalten
*/
public int getColumnCount() {
return header.getChildren().size();
}
/**
* Liefert den Titel einer Spalte
* @param i Nummer der Spalte
* @return Name der Spalte
*/
public String getColumnTitle(int i) {
if(i< getColumnCount()) {
return ((List<Element>) (header.getChildren())).get(i).getText();
} else {
return "";
}
}
/**
* Liefert die Nummer einer Spalte
* @param name Name der Spalte
* @return Nummer der Spalte
*/
public int getColumn(String name) {
List<Element> columns = header.getChildren();
int i = 0;
while (i < columns.size()) {
if (columns.get(i).getText().toLowerCase().equals(name.toLowerCase())) {
return i;
}
i++;
} // end of while
return -1;
}
/**
* Erzeugt eine neue Zeile mit i Spalten
* Wenn bisher nicht genügend Spalten vorhanden sind, werden automatisch neue Spalten hinzugefügt (auch zum Header)
* @param i Anzahl der Spalten
*/
private Element buildRow(int i) {
List<Element> columns = header.getChildren();
Element entry=null;
for(int j=0; j<=i; j++) {
if(j==columns.size()) {
Element h = new Element("Column");
h.setAttribute("type", "unknown");
header.addContent(h);
columns = header.getChildren();
}
if(j==current.getChildren().size()) {
entry = new Element("Entry");
current.addContent(entry);
}
}
return entry;
}
/**
* Erzeugt eine neue Zeile.
* Es werden genügend Spalten erzeugt, dass ein Wert in Spalte "name" eingetragen werden kann
* @param name Name der Spalte
*/
private Element buildRow(String name) {
List<Element> columns = header.getChildren();
int i = 0;
for(Element c: columns) {
if(c.getText().toLowerCase().equals(name.toLowerCase())) {
return buildRow(i);
}
i++;
}
return null;
}
/**
* Liefert den Wert einer Zelle als String
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public String getString(int i) {
if(i >= current.getContent().size()) return "";
Element e = (Element) current.getContent(i) ;
if(e!=null) {
return e.getText();
} else {
return "";
}
}
/**
* Liefert den Wert einer Zelle als String
* @param name Name der Spalte
* @return Wert der Zelle
*/
public String getString(String name) {
return getString(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als String
* @param i Nummer der Spalte
* @param text neuer Wert der Zelle
*/
public void setString(int i, String text) {
Element e = buildRow(i);
if(e!=null) e.setText(text);
}
/**
* Setzt den Wert einer Zelle als String
* @param name Name der Spalte
* @param text neuer Wert der Zelle
*/
public void setString(String name, String text) {
Element e = buildRow(name);
if(e!=null) e.setText(text);
}
/**
* Liefert den Wert einer Zelle als Int-Zahl
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public int getInt(int i) {
try{
Element e = (Element) current.getContent(i) ;
return Integer.parseInt(e.getText());
} catch(Exception e) {
return 0;
}
}
/**
* Liefert den Wert einer Zelle als Int-Zahl
* @param name Name der Spalte
* @return Wert der Zelle
*/
public int getInt(String name) {
return getInt(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als Int-Zahl
* @param i Nummer der Spalte
* @param value neuer Wert der Zelle
*/
public void setInt(int i,int value) {
Element e = buildRow(i);
if(e!=null) e.setText(""+value);
}
/**
* Setzt den Wert einer Zelle als Int-Zahl
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setInt(String name, int value) {
Element e = buildRow(name);
if(e!=null) e.setText(""+value);
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public float getFloat(int i) {
try{
Element e = (Element) current.getContent(i) ;
return Float.parseFloat(e.getText().replace(",","."));
} catch(Exception e) {
return 0;
}
}
/**
* Liefert den Wert einer Zelle als Float-Zahl
* @param name Name der Spalte
* @return Wert der Zelle
*/
public float getFloat(String name) {
return getFloat(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param i Nummer der Spalte
* @param value neuer Wert der Zelle
*/
public void setFloat(int i,float value) {
Element e = buildRow(i);
if(e!=null) e.setText(format.format(value));
}
/**
* Setzt den Wert einer Zelle als Float-Zahl
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setFloat(String name, float value) {
Element e = buildRow(name);
if(e!=null) e.setText(format.format(value));
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param i Nummer der Spalte
* @return Wert der Zelle
*/
public double getDouble(int i) {
try{
Element e = (Element) current.getContent(i) ;
return Double.parseDouble(e.getText().replace(",","."));
} catch(Exception e) {
return 0;
}
}
/**
* Liefert den Wert einer Zelle als Double-Zahl
* @param name Name der Spalte
* @return Wert der Zelle
*/
public double getDouble(String name) {
return getDouble(getColumn(name));
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param i Nummer der Spalte
* @param value neuer Wert der Zelle
*/
public void setDouble(int i,double value) {
Element e = buildRow(i);
if(e!=null) e.setText(format.format(value));
}
/**
* Setzt den Wert einer Zelle als Double-Zahl
* @param name Name der Spalte
* @param value neuer Wert der Zelle
*/
public void setDouble(String name, double value) {
Element e = buildRow(name);
if(e!=null) e.setText(format.format(value));
}
}

View file

@ -0,0 +1,637 @@
/**
* Klasse zum Vereinfachten Zugriff auf XML-Dokumente
* Diese Klasse ist für den Einsatz in der Schule gedacht und soll den Schülern
* einen einfachen Zugriff auf XML-Dokumente ermöglichen. Die zur Verfügung
* stehenden Befehle sind wie in Processing realisiert.
* Dabei ist jeder Teilbaum des Dokuments wieder als XML-Objekt zugreifbar, das
* intern auf die gleiche XML-Dokumentstruktur zugreift.
* Dies ermöglicht bei unsachgemäßem Gebrauch die XML-Struktur zu zerstören. Im
* normalen Gebrauch sollte dies aber nicht relevant sein.
*
* Benötigt: jdom-1.1.3.jar
* @author Thomas Schaller
* @version 1.0 vom 31.01.2019
*/
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
public class XML {
// Anfang Attribute
// XML-Dokumentstruktur
private Document doc;
// Zeiger auf das aktuelle Element
private Element current;
// Ende Attribute
/**
* Erzeugt ein leeres XMLDokument
*/
public XML() {
this.doc = new Document();
this.current = null;
}
/**
* Erzeugt ein XML-Dokument aus einer Datei
* @param filename Dateiname der XML-Datei
*/
public XML(String filename) {
loadXML(filename);
}
/**
* interner Konstruktor, um ein XML Objekt zu erzeugen, das auf einen bestimmten Knoten verweist
* @param doc die XML-Dokumentstruktur
* @param current Zeiger auf das aktuelle Element
*/
private XML(Document doc, Element current) {
this.doc = doc;
this.current = current;
}
// Anfang Methoden
/** Öffnet das durch den Dateinamen gegebene Dokument
* @param filename Dateiname des XML-Files
*/
public void loadXML(String filename) {
doc = null;
File f = new File(filename);
try {
// Das Dokument erstellen
SAXBuilder builder = new SAXBuilder();
doc = builder.build(f);
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// Zeiger im Baum auf Root-Element
current = doc.getRootElement();
}
/** Speichert den XML-Baum im angegebenen Dateinamen
* @param filename Dateiname des XML-Files
*/
public void saveXML(String filename) {
try {
// new XMLOutputter().output(doc, System.out);
XMLOutputter xmlOutput = new XMLOutputter();
// display nice nice
xmlOutput.setFormat(Format.getPrettyFormat());
File f = new File(filename);
FileOutputStream outputFile = new FileOutputStream(f);
System.out.println("Speicher in : "+f.getAbsolutePath() );
xmlOutput.output(doc, outputFile);
outputFile.close();
System.out.println("File Saved!");
} catch (IOException io) {
System.out.println(io.getMessage());
}
}
//----------------------------------------------- Zeigerbewegungen --------------------------------------------------
/**
* liefert ein XML-Objekt, das auf den Vaterknoten des aktuellen Elements zeigt.
* @return Vater des aktuellen Objekts.
*/
public XML getParent() {
if(current != null) {
Element parent = current.getParentElement();
if (parent == null) {
return null;
} else {
return new XML(doc, parent);
}
}
return null;
}
/**
* Überprüft, ob das Element irgendwelche Kinder hat oder nicht, und gibt das Ergebnis als boolean zurück.
* @return true, wenn Kinder vorhanden sind, sonst false
*/
public boolean hasChildren() {
if (current == null) {
return doc.hasRootElement();
} else {
return current.getChildren().size()>0;
}
}
/**
* Ermittelt die Namen aller Kinder des Elements und gibt die Namen als ein Array von Strings zurück.
* Dies ist dasselbe wie das Durchlaufen und Aufrufen von getName() auf jedem untergeordneten Element einzeln.
* @return Liste aller Namen der Kinder
*/
public String[] listChildren() {
if (current == null) {
if(doc.hasRootElement()) {
String[] names = new String[0];
names[0] = doc.getRootElement().getName();
return names;
} else {
return null;
}
} else {
List<Element> ch_element = current.getChildren();
String[] names = new String[ch_element.size()];
for(int i=0; i < ch_element.size() ; i++) {
names[i] = ch_element.get(i).getName();
}
return names;
}
}
/**
* Liefert alle Kinder des Elements als Array von XML-Objekten.
* @return Array der Kinder als XML-Objekte
*/
public XML[] getChildren() {
if (current == null) {
if(doc.hasRootElement()) {
XML[] ch_xml = new XML[1];
ch_xml[0] = new XML(doc, doc.getRootElement());
return ch_xml;
} else {
return null;
}
} else {
List<Element> ch_element = current.getChildren();
XML[] ch_xml = new XML[ch_element.size()];
for(int i=0; i < ch_element.size() ; i++) {
ch_xml[i] = new XML(doc, ch_element.get(i));
}
return ch_xml;
}
}
/**
* Liefert bestimmte Kinder des Elements als Array von XML-Objekten.
* Die Methode gibt dabei alle Kinder zurück, die dem angegebenen Namen entsprechen.
* @param name Name der gesuchten Kind-Objekte
* @return Array der Kinder als XML-Objekte
*/
public XML[] getChildren(String name) {
if (current == null) {
if(doc.hasRootElement()) {
XML[] ch_xml = new XML[1];
ch_xml[0] = new XML(doc, doc.getRootElement());
if(doc.getRootElement().getName().equals(name)){
return ch_xml;
} else {
return null;
}
} else {
return null;
}
} else {
List<Element> ch_element = current.getChildren(name);
XML[] ch_xml = new XML[ch_element.size()];
for(int i=0; i < ch_element.size() ; i++) {
ch_xml[i] = new XML(doc, ch_element.get(i));
}
return ch_xml;
}
}
/**
* Liefert das erste Kind des Elements mit einem bestimmten Namen.
* Die Methode gibt das erste Kind zurück, das dem angegebenen Namen entsprechen.
* @param name Name des gesuchten Kind-Objektes
* @return Kind als XML-Objekt
*/
public XML getChild(String name) {
if (current == null) {
Element e = doc.getRootElement();
if (e.getName().equals(name)) {
return new XML(doc, e);
} else {
return null;
}
} else {
String[] names = name.split("/");
Element e = current;
int i = 0;
while(i < names.length) {
e = e.getChild(names[i]);
if (e==null) return null;
i++;
}
return new XML(doc, e);
}
}
/**
* Liefert das i. Kind des Elements.
* Die Methode gibt das i. Kind des aktuellen Elements zurück.
* @param i Nummer des Kindes
* @return Kind als XML-Objekt
*/
public XML getChild(int i) {
if (current == null) {
return new XML(doc, doc.getRootElement());
} else {
List<Element> ch_element = current.getChildren();
if (i>=ch_element.size()) return null;
return new XML(doc, ch_element.get(i));
}
}
//--------------------------------------------------- Methoden für das aktuelle Element -------------------------------------------------
/**
* Frage den Namen des aktuellen Elements ab
* @return Namen des Elements
*/
public String getName() {
if (current==null) return "";
return current.getName();
}
/**
* Setze den Namen des aktuellen Elements.
* @param name Neuer Name des Elements
*/
public void setName(String name) {
if (current==null) return;
current.setName(name);
}
/**
* liefert die Anzahl der Attribute eines Elements.
* @return Anzahl des Attribute
*/
public int getAttributeCount() {
if (current == null) return 0;
return current.getAttributes().size();
}
/**
* liefert zurück, ob das aktuelle Element Attribute hat .
* @return true, wenn es Attribute gibt
*/
public boolean hasAttribute() {
if (current == null) return false;
return current.getAttributes().size()>0;
}
/**
* Ruft alle Attribute des angegebenen Elements ab und gibt sie als Array von Strings zurück.
* @return Liste der Attributnamen
*/
public String[] listAttributes() {
if (current == null) return null;
List<Attribute> attr = current.getAttributes();
String[] names = new String[attr.size()];
for(int i=0; i < attr.size() ; i++) {
names[i] = attr.get(i).getName();
}
return names;
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs
*/
public String getString(String attribute) {
if (current==null) return "";
return current.getAttributeValue(attribute);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs
*/
public String getString(String attribute, String defaultValue) {
if (current==null) return defaultValue;
return current.getAttributeValue(attribute,defaultValue);
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param text neuer Wert des Attributs
*/
public void setString(String attribute, String text) {
if (current==null) return;
current.setAttribute(attribute, text);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs als Integer-Zahl
*/
public int getInt(String attribute) {
if (current==null) return 0;
try{
int i = Integer.parseInt(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return 0; }
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs als Integer-Zahl
*/
public int getInt(String attribute, int defaultValue) {
if (current==null) return defaultValue;
try{
int i = Integer.parseInt(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param value neuer Wert des Attributs
*/
public void setInt(String attribute, int value) {
if (current==null) return;
current.setAttribute(attribute, ""+value);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs als Float-Zahl
*/
public float getFloat(String attribute) {
if (current==null) return 0;
try{
float i = Float.parseFloat(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return 0; }
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs als Float-Zahl
*/
public float getFloat(String attribute, float defaultValue) {
if (current==null) return defaultValue;
try{
float i = Float.parseFloat(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param value neuer Wert des Attributs
*/
public void setFloat(String attribute, float value) {
if (current==null) return;
current.setAttribute(attribute, ""+value);
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* @param attribute Name des Attributs
* @return Wert des Attributs als Double-Zahl
*/
public double getDouble(String attribute) {
if (current==null) return 0;
try{
double i = Double.parseDouble(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return 0; }
}
/**
* Fragt einen Attributwert des aktuellen Elements ab
* Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben
* @param attribute Name des Attributs
* @param defaultValue Standardwert, falls es das Attribut nicht gibt
* @return Wert des Attributs als double-Zahl
*/
public double getDouble(String attribute, double defaultValue) {
if (current==null) return defaultValue;
try{
double i = Double.parseDouble(current.getAttributeValue(attribute));
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Setzt einen Attributwert des aktuellen Elements
* @param attribute Name des Attributs
* @param value neuer Wert des Attributs
*/
public void setDouble(String attribute, double value) {
if (current==null) return;
current.setAttribute(attribute, ""+value);
}
/**
* Fragt den Inhalt/Text des aktuellen Elements ab
* @return Inhalt des Elements
*/
public String getContent() {
if ( current==null) return "";
return current.getText();
}
/**
* Fragt den Inhalt/Text des aktuellen Elements ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardtext
* @return Inhalt des Elements
*/
public String getContent(String defaultValue) {
if ( current==null) return defaultValue;
String t = current.getText();
if(t.equals("")) t = defaultValue;
return t;
}
/**
* Setzt den Inhalt/Text des aktuellen Elements
* @param text Neuer Inhalt des Elements
*/
public void setContent(String text) {
if ( current==null) return;
current.setText(text);
}
/**
* Fragt den Inhalt des aktuellen Elements als Integerzahl ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardwert
* @return Inhalt des Elements
*/ public int getIntContent(int defaultValue) {
if ( current==null) return defaultValue;
try{
int i = Integer.parseInt(current.getText());
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Fragt den Inhalt des aktuellen Elements als Integerzahl ab
* @return Inhalt des Elements
*/
public int getIntContent() {
if ( current==null) return 0;
try{
int i = Integer.parseInt(current.getText());
return i;
} catch(Exception e) { return 0; }
}
/**
* Setzt den Inhalt des aktuellen Elements
* @param value Neuer Inhalt des Elements
*/
public void setIntContent(int value) {
if ( current==null) return;
current.setText(""+value);
}
/**
* Fragt den Inhalt des aktuellen Elements als Floatzahl ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardwert
* @return Inhalt des Elements
*/
public float getFloatContent(float defaultValue) {
if ( current==null) return defaultValue;
try{
float i = Float.parseFloat(current.getText());
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Fragt den Inhalt des aktuellen Elements als Floatzahl ab
* @return Inhalt des Elements
*/
public float getFloatContent() {
if ( current==null) return 0;
try{
float i = Float.parseFloat(current.getText());
return i;
} catch(Exception e) { return 0; }
}
/**
* Setzt den Inhalt des aktuellen Elements
* @param value Neuer Inhalt des Elements
*/
public void setFloatContent(float value) {
if ( current==null) return;
current.setText(""+value);
}
/**
* Fragt den Inhalt des aktuellen Elements als Doublezahl ab
* Hat das Element keinen Inhalt wird der defaultValue zurückgegeben.
* @param defaultValue Standardwert
* @return Inhalt des Elements
*/
public double getDoubleContent(double defaultValue) {
if ( current==null) return defaultValue;
try{
double i = Double.parseDouble(current.getText());
return i;
} catch(Exception e) { return defaultValue; }
}
/**
* Fragt den Inhalt des aktuellen Elements als Doublezahl ab
* @return Inhalt des Elements
*/
public double getDoubleContent() {
if ( current==null) return 0;
try{
double i = Double.parseDouble(current.getText());
return i;
} catch(Exception e) { return 0; }
}
/**
* Setzt den Inhalt des aktuellen Elements
* @param value Neuer Inhalt des Elements
*/
public void setDoubleContent(double value) {
if ( current==null) return;
current.setText(""+value);
}
// ----------------------------------------------- XML-Struktur aufbauen ------------------------------------------------
/** Erzeuge neues Element nach der aktuellen Position und setze dieses als aktuelles Element
* @param name Name des neuen Elements
* @return neues Element als XML-Objekt
*/
public XML addChild(String name) {
Element e = new Element(name);
if(current == null){ // man ist auf Root-Ebene
doc.setRootElement(e);
}
else {
current.addContent(e);
} // end of if-else
return new XML(doc, e);
}
/**
* liefert das aktuelle Element als jdom-Element-Objekt
* @return aktuelles Element
*/
private Element getCurrent() {
return current;
}
/**
* löscht ein Kind des aktuellen Knotens.
* Ist kid kein Kind des aktuellen Elements passiert gar nichts.
* @param kid XML-Objekt des Kindes
*/
public void removeChild(XML kid) {
if (current == null) return;
Element e = kid.getCurrent();
int index = current.indexOf(e);
if(index >= 0) { current.removeContent(e);}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Some files were not shown because too many files have changed in this diff Show more