# Hightlight in Java



## Stone2k8 (12. Jun 2008)

Moin Leute, hab mal ne Frage an euch! und zwar programmiere ich gerade das Spiel Risiko in Java! Und im Spiel habe ich ja eine Landkarte mit verschieden Ländern drauf! Ich wollte mal fragen ob es in Java eine Funktion gibt die es ermöglicht einen bestimmten berecih dieser Landkarte(label) aufhellen zu lassen?Also quasi son rollover effekt...Wisst ihr da was??


----------



## Guest (12. Jun 2008)

Du packst die LandKarte in ein JLabel? Warum machst du sowas?  

Ich wüsst spontan nicht das JLabel da bestimmte Teile drin highliten könnt, aber ich würd das eh nicht auf ein JLabel
sondern auf ein JPanel zeichnen (einfach die paintComponent überschreiben und dort das Bild mit drawImage
zeichnen). Dann wär das mit dem Highliten sicherlich einfacher. Ausserdem kannst du dann auch noch andere Sachen
draufmalen...


----------



## Stone2k8 (12. Jun 2008)

Joa ich hab ein JLabel erstellt und dann per setIcon die Landkarte drauf gepackt! und das Label ist natürlich auf nem Jpanel! Was ist daran so falsch?


----------



## Guest (12. Jun 2008)

Ja grundsätzlich falsch ist da garnix dran. Aber du kannst halt wenig damit machen ausser es darstellen. Damit
wirste nicht glücklich denk ich...

Lass das JLabel weg und zeichne die Karte direkt auf das Panel. Wenn du die dann aus den einzelnen Ländern
zeichnen lässt kannst du fürs highliten einfach ein anderes Bild zeichnen (wenn du verstehst)

dafür musst du nur die paintComponent-Methode des Panels überschreiben (wenn du nicht weisst wie das geht frag
ruhig)
Da schreibst du dann sowas rein:


```
public void paintComponent(Graphics g1) { 
    super.paintComponent(g1); 
    g1.drawImage(deutschland,0, 0, null); //deutschland ist ein BufferedImage, Image, ... or what else
    g1.drawImage(pfalz,0, 0, null);           //pfalz ist ein BufferedImage, Image, ... or what else
    g1.drawImage(frankreich_highlited,0, 0, null); //frankreich_highlited ist ein BufferedImage, Image, ... 
    }
```

Noch besser ist du baust dir ne Methode die aus all deinen Ländern eine Landkarte zusammenmalt und nur dieses
Gesamtbild wird in der paintComponent gezeichnet.


----------



## Gast (12. Jun 2008)

hmm das verstehe ich nicht so ganz! Soll ich jetzt meine komplette Landkarte zerlegen in alle einzelnen Länder und die dann einzeln zusammen drawen? Das wäre irgendwie zu viel Arbeit hehe


----------



## Stone2k8 (14. Jun 2008)

Noch jemand ne andere Lösung??


----------



## Campino (15. Jun 2008)

Wenn du die Länder einzeln highlighten willst, ist das mMn die einzige Möglichkeit...


----------



## Stone2k8 (15. Jun 2008)

Naja also in dem Grössten open Source Risiko wird dieses Feature auch genutzt, bloss das ich in der source keine einzelnen Länder Grafiken finden kann! Das ist auch nur eine Karte...Die müssen das auch irgendwie hinbekommen haben! Bloss wie?

Hier ma der Link zum open Source Risk:

http://risk.sourceforge.net/download.shtml


----------



## m@nu (17. Jun 2008)

speicher dir in zwei arrays jeweils die x und y koordinaten der eckpunkte deiner länder auf deiner karte.


```
int [] xCoords = {1,3,5 /*usw.*/ };
int [] yCoords = {1,3,5 /*usw.*/ };
```

jetzt baust du dir eine eigene component, welche in ihrer paintComponent-methode die karte zeichnet.
soll ein land gehighlightet werden, zeichnest du per fillPolygon() die entsprechende fläche mit den x & y-koordinaten auf die karte.
fertig 

was ähnliches habe ich hier schon einmal gepostet...
:arrow: http://java-forum.org/de/viewtopic.php?p=135616#135616


----------



## Stone2k8 (17. Jun 2008)

Ja aber meine Länder sind doch nicht nicht eckig sondern haben immer verschiedene Formen! Und bei deiner Methode müsste ich doch auch alle Länder einzelnd gezeichnet haben oder nicht??


----------



## m@nu (18. Jun 2008)

die grenzen deiner länder sind rund?
normalerweise sind die grenze eines landes doch geradelinig gezogen, oder nicht? 

ja irgendwie musst du ja festlegen welches land wo liegt. dazu musst du die grenzen der einzelnen länder festlegen. das passiert über die angesprochenen koordinaten-arrays.
die karte selber bleibt die selbe.

zudem: wenn du z.b. auf den mauszeiger zwecks benutzereingabe reagieren willst, brauchst du die koordinaten so oder so auch wieder.


----------



## Stone2k8 (18. Jun 2008)

Naja meine Ländergrenzen sind nun mal nicht gerade hehe! Sind halt auch kurvif wie es Länder so an sich haben  Naja denke mal das deine Möglichkeit dann natürlich nicht klappen kann!

Ich frag mich nur wie das beim open Source Risk gemacht haben...


----------



## masta // thomas (18. Jun 2008)

Vielleicht kannst du hiermit was anfangen - hab ich irgendwann mal aus Langeweile oder zu Testzwecken gemacht...

FindColor.jar (Source im Archiv)


----------



## m@nu (18. Jun 2008)

hm, ja dann wirds schwierig.

hab mir die lösung von masta // thomas nicht angeschaut. aber dem jar-namen nach zu urteilen ist die variante recht rechenintensiv kann ich mir vorstellen.
da müsste man wahrscheinlich die karte im voraus analysieren um die grenze irgendwo im speicher zu halten.

aber: was wenn ein land nicht immer komplett die gleiche farbe hat?


----------



## Stone2k8 (18. Jun 2008)

Hab ihr euch den mal das Open source Risiko was ich weiter oben gepostet habe mal angeschaut? Oder vielleicht mal in die Src geschaut? Vielleicht könnt ihr ja was finden wie die es bewerkstelligen!

Danke an Masta, werde mir das gleich ma anschauen!


----------



## Stone2k8 (18. Jun 2008)

Yo Masta das Programm is gut...kann ich glaube ich verwenden, nur weiss ich noch nicht genau wie!  

Also ich benutze ja bei meiner Karte zusätzlich nen Bufferimage(Die gleiche Karte bloss das alle Länder nen anderen Hexcode haben) das wenn ich mit der maus auf ein Land klicke eine Methode unterscheiden kann zwischen den Ländern!

Also müsste ich doch quasi auch irgendwie mit deinem Code machen können das er wenn ich mit der Maus über ein Land fahre, er vom Bufferedimage den Hexcode sich holt und dann painted oder nicht...Aber wie mache ich das genau?


----------



## stone2k8 (18. Jun 2008)

Sooooooooooo habs jetzt hinbekommen deinen Code mit in meinen einzufügen...bekommen bloss folgende exception wenn er dies hier ausführen will:


```
int[] data = ((DataBufferInt) buffer.getRaster().getDataBuffer()).getData();
```

dann die Exception:


```
Exception in thread "Thread-2" java.lang.ClassCastException: java.awt.image.DataBufferByte cannot be cast to java.awt.image.DataBufferInt
```

Was hatn das zu bedeuten?


----------



## Krondor (18. Jun 2008)

Du könntest deine Länder intern als java.awt.Polygon darstellen.
Diese hat eine contains() - Funktion, welche angibt ob bestimmte Koordinaten in dem Polygon enthalten sind.

Du könntest dann per Java2D das Polygon zeichnen, welches eine ÄHNLICHE Form wie deine Länder haben sollte.
Um das Highlighting noch schöner zu machen könntest du das Polygon dann auch noch halb-transparent füllen.

Hab sowas ähnliches mal gemacht, weiß aber auch nur noch grob wie.


----------



## stone2k8 (19. Jun 2008)

Hi Kondor...kannst du das vielleicht noch etwas genauer erklären??


----------



## Krondor (19. Jun 2008)

Hab mal nen kleines Beispielprogramm geschrieben damit du siehst was ich meine.
Das gezeichnete Polygon könntest du dann über deine Grafik legen. 
Ich hab die Transparenz auch direkt eingebaut.
Die Linie ist nicht transparent, der Füllbereich schon.

Ich finde diese Methode halt am sinnvollsten. Du musst halt nur schauen, dass das Polygon grob zu deinen Ländern passt. Voila dann gehts. 

Viel Spaß damit.

Achso noch was. Das hier ist natürlich nur ein Beispielprogramm. Du solltest bei deinem Spiel halt schon mit MVC oder so arbeiten und das hier dann passend einfügen.



```
package polygon;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class PolygonTest 
extends JPanel 
implements MouseMotionListener {
	public static void main(String[] args) {
		JFrame frm = new JFrame();
		frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		JPanel pnl = new PolygonTest();
		frm.getContentPane().add(pnl);
		
		frm.setLocation(50, 50);
		frm.setSize(200, 200);
		frm.setVisible(true);
	}
	
	private Polygon poly;
	private boolean mouseInPoly = false;
	
	public PolygonTest() {
		int[] x = {20, 40, 70, 50, 10};
		int[] y = {10, 10, 30, 50, 40};
		int n = 5;
		poly = new Polygon(x, y, n);
		addMouseMotionListener(this);
	}
	
	

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		
	    Graphics2D g2d = (Graphics2D)g;
	    
	    //Composite dient dazu die durchsichtige Fläche zu zeichnen	    
	    //Alter Composite zum Zeichnen der Linie merken
	    Composite oldComposite = g2d.getComposite();
	    
	    //Durchsichtiger gefüllter Bereich, falls Maus drinnen ist
	    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2F));
	    
	    g2d.setColor(Color.BLUE);
	    if(mouseInPoly) {
	    	g2d.fill(poly);
	    }
	    
	    //Undurchsichtiger Rand
	    g2d.setComposite(oldComposite);
	    g2d.draw(poly);		
	}



	@Override
	public void mouseDragged(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public void mouseMoved(MouseEvent arg0) {
		int x = arg0.getX();
		int y = arg0.getY();
		
		if(poly.contains(x, y)) {
			mouseInPoly = true;
		}else {
			mouseInPoly = false;
		}
		
		repaint();
	}


	
	
}
```

Übrigens wollte ich auch mal nen Risiko schreiben und diese Idee kam mir genau dabei. 
Leider hatte ich nie genug Zeit das ganze fertig zu machen 

Falls du noch Probleme mit dem Java2D Kram haben solltest empfehle ich dir:
http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html#Java2D-Tutorial-Paint-Transparency


----------



## Gast (19. Jun 2008)

puhhhhhhhhh bin gerade im 2 Semester und weiss jetzt nicht wirklich wie den code bei mir im Programm mit einbaue hehe...Aber auf jeden Fasll Danke dafür!

Den Coe verstehe ich schon ansich, bloss hakt es gerade hier:


```
public PolygonTest() {
      int[] x = {20, 40, 70, 50, 10};
      int[] y = {10, 10, 30, 50, 40};
      int n = 5;
      poly = new Polygon(x, y, n);
      addMouseMotionListener(this);
   }
```

Wie trage ich denn da genau meine Länder ein??


----------



## stone2k8 (19. Jun 2008)

Mache ich für jedes meiner Länder ein Polygon? Dann pack ich diese ganzen Polygone in ein Vector! Dann wenn mouseMoved ist dann frag ich per for-schleife den Vector nach dem gesuchten Polygon ab und painte dann das Poly? Seh ich das so richtig?


----------



## Krondor (19. Jun 2008)

Also folgendes:

Du braucht für jedes Land ein eigenes Polygon.
Am besten machst du dir dazu eine Klasse Land oder Country oder wie auch immer wo du den Namen und das Polygon hinterlegst. Des Weiteren solltest du dir 

Die MouseMoved Methode wird per MouseMotionListener immer dann aufgerufen, wenn sich deine Maus bewegt und überprüft ob sich die Koordinaten der Maus in dem Polygon befinden. Falls ja wird die globale boolsche Variable mouseInPoly auf true gesetzt ansonsten auf false.

Hier solltest du halt alle Länder durchlaufen und überprüfen ob sich die Maus in dem jeweiligen Polygon befindet. Falls ja solltest du dir das in dem Land speichern.

In der Zeichenmethode paintComponent musst du dann wiederum die Länder durchlaufen und schauen ob ein Land gehighlighted werden soll. Wenn ja highlighte das Polygon per g2d.fill(poly) oder g2d.draw(poly) wobei poly dann das Polygon des jeweiligen Landes ist.


z.B.

Ist Maus in Polygon eines Landes?

```
public void mouseMoved(MouseEvent arg0) {
      int x = arg0.getX();
      int y = arg0.getY();
      
      for(int i=0;i<laender.length;i++) {

      Polygon poly = laender[i].getPolygon();
      if(poly.contains(x, y)) {
         laender[i].setMouseInPoly(true);
      }else {
         laender[i].setMouseInPoly(false);
      }

      }
      
      repaint();
   }
```


Zeichenmethode (grob):

```
Land[] laender = ....

for(int i=0;i<laender.length;i++) {
  if(laender[i].isMouseInPoly()) {
    g2d.draw(laender[i].getPolygon());
  }
}
```

So ähnlich halt


----------



## Gast (19. Jun 2008)

Jo dank dir...Jetzt weiss ich wie ich es machen muss...Dank dir! Aber wird nen bisschen dauern bis ich es geschafft habe denke ich


----------



## Krondor (19. Jun 2008)

Jup das ganze ist definitiv nicht so einfach wie man sich das vorstellt.
Vor allem weil du halt neu in dem Bereich bist.

Das drum rum kann einem ganz schön oft sorgen bereit und zwar spätestens dann wenn man einen Mehrspielermodus oder eine KI einbauen will.  Aber probier mal. Man kann dabei nur lernen


----------



## stone2k8 (19. Jun 2008)

Hmmm hab das ganze jetzt mal in mein Spiel eingebaut...Eclipse meckert nicht, aber es tut sich nichts wenn ich über meine Länder fahre...Also es kommt nichts...Kein Highlight, kein Fehler! Und nu?


----------



## stone2k8 (19. Jun 2008)

Achja muss das nicht hier 
	
	
	
	





```
@Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
```

richtig so heissen 
	
	
	
	





```
@Override
   public void paintComponents(Graphics g) {
      super.paintComponents(g);
```
??


----------



## stone2k8 (19. Jun 2008)

Achja nochwas...geht das vielleicht nicht weil meine Karte auf nem JLabel liegt und nicht direkt auf dem Panel gezeichnet ist??


----------



## Krondor (20. Jun 2008)

Hmmmm...

kannste deinen Quellcode mal posten? Also ich persönlich würde sowas auf ein JPanel zeichnen und nicht auf ein Label...  ???:L 

Ohne Quellcode fällt mir eine Aussage schwer...


----------



## Gast (20. Jun 2008)

Welchen Quellcoide brauchste? Den von meiner kompletten GUI? Ja ich hätte es ja auch auf nem JPanel gezeichnet hätte ich es vorher gewusst...Ich kannte mich noch nicht so aus und da hab ich nen Label genommen weil ich da per setIcon nen bild drauf machen konnte...

Naja hier mal nen Auszug wie ich den Code bei mir eingefügt habe...:


```
private void karteLabelMouseMoved(java.awt.event.MouseEvent evt) {                                      
    int x = evt.getX();
    int y = evt.getY();
     
    for(int i = 0; i < rv.laenderPlusBesetzerVector().size(); i++) {
        Polygon poly = rv.laenderPlusBesetzerVector().elementAt(i).getPolygon();
        if(poly.contains(x, y)) {
            rv.laenderPlusBesetzerVector().elementAt(i).setMouseInPoly(true);
        }else {
            rv.laenderPlusBesetzerVector().elementAt(i).setMouseInPoly(false);
        }

        }
     
      karteLabel.repaint(); 
      
}
```

So das ist einmal die MouseMoved Funktion...und jetzt hier die Paint Components...


```
@Override
    public void paintComponents(Graphics g) {
      super.paintComponents(g);
      
       Graphics2D g2d = (Graphics2D)g;
      
       //Composite dient dazu die durchsichtige FlÃƒÆ’Ã‚Â¤che zu zeichnen      
       //Alter Composite zum Zeichnen der Linie merken
       Composite oldComposite = g2d.getComposite();
      
       //Durchsichtiger gefÃƒÆ’Ã‚Â¼llter Bereich, falls Maus drinnen ist
       g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2F));
      
       g2d.setColor(Color.BLUE);
       int i = 0;
       for (i = 0; i < rv.laenderPlusBesetzerVector().size(); i++) {
            if(rv.laenderPlusBesetzerVector().elementAt(i).isMouseInPoly()) {
                g2d.fill(rv.laenderPlusBesetzerVector().elementAt(i).getPolygon());
                
            }
       }
       
      
       //Undurchsichtiger Rand
       g2d.setComposite(oldComposite);
       g2d.draw(rv.laenderPlusBesetzerVector().elementAt(i).getPolygon());      
   }
```


----------



## Guest (21. Jun 2008)

Wenn du jedem Polygon eine Farbe gibst, könntest du auch immer wenn die Maus drüber ist, die Farbe mit 
brighter() oder darker() verändern.


----------



## stone2k8 (22. Jun 2008)

Hey Krodon hast dir den Code mal angeschaut??


----------



## Krondor (23. Jun 2008)

Gast hat gesagt.:
			
		

> Naja hier mal nen Auszug wie ich den Code bei mir eingefügt habe...:



Also ich finde das sieht schon ganz vernünftig so aus.

Ich finde jetzt mal den Namen der Methode "karteLabelMouseMoved" sehr seltsam. Wird diese überhaupt von deinem MouseListener aufgerufen?

Es ist ja mal so, dass man normalerweise in der View-Klasse einen MouseMotionListener implementiert. Bei diesem muss man dann 2 Methoden mouseMoved und mouseDragged (glaube ich) implementieren und den MouseListener per addMouseMotionListener() an die View dran hängen. 

Immer wenn sich nun die Maus bewegt oder etwas per drag & drop verschiebt wird die passende Methode aufgerufen.
Hier solltest du die Sachen aus deiner Methode karteLabelMouseMoved rein tun, bzw. auf deine Methode zugreifen. Falls du das nicht tust oder einfach nur den Listener nicht bei der View anmeldest (per addMouseMotionListener() ) kann das ganze nicht funktionieren.

Du könntest mal die Methode debuggen oder aber auch einfach ein System.out.println() rein tun und gucken ob was ausgegeben wird, wenn du die Maus bewegst....

Sorry dass ich jetzt erst antworte, ich war am Wochenende ohne Internet auf Achse 


P.S.: Krodon ist ein doofer Name ... *LACH*


----------



## stone2k8 (23. Jun 2008)

Hey Nein das ist nicht das Problem...die Methode karteLabelmouseMoved wird aufgerufen...Das Problem ist nur das er bei mir meckert wenn ich versuche die paintComponent zu überschreiben! Er sagt mir nämlich das es diese Methode nicht gibt! Und das liegt wohl wiederum daran das meine GUI(die übrigens komplett in einer Klasse ist) nicht von JPanel sondern von JFrame erbt!

So hab das ganze mal versucht mit der paint() Methode...damit funktioniert es! Bloss das das eingefärbte Polygon beim bewegen der Maus in diesem Polygon flackert und ich noch Probleme mit den X und Y Positionen habe!


----------



## Krondor (23. Jun 2008)

Am besten ist es, wenn du dir eine eigene Klasse für das JPanel schreibst und eine eigene Klasse schreibst, welche von JFrame erbt, welche dann dein JPanel verwendet.

So hast du eine logische Trennung zwischen beidem.

Das JPanel ist halt für die Darstellung von Grafiken gedacht und nicht das JFrame.

Des Weiteren kannst du dann die Methode überschreiben.

Deshalb benutzt man normalerweise für solche Anwendungen auch das MVC - Pattern (http://en.wikipedia.org/wiki/Model-view-controller), mit welchem man die Daten von der Anzeige trennt.

Normalerweise wäre dann dein Model deine Klasse zum halten der Daten, deine View dein JPanel und deine Control-Klassen würden das ganze steuern.

Dein JFrame käme dann hinzu um deine Views zusammen zu fassen und den ganzen Kram darzustellen


----------



## stone2k8 (23. Jun 2008)

Naja bin halt gerade relativ am Anfang von Java und habe jetzt meine Gui mit Netbeans per Drag and Drop erstellt...Und Netbeans hat nunmal alles in eine Klasse gemacht! Oder kann man das mit Netbeans auch irgendwie anders regeln??


----------



## Floonry (26. Jul 2008)

birch carroll movie times newest hit movie


----------



## Floonry (27. Jul 2008)

reefer madness musical movie high def movies


----------

