|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Jul 2005
Messaggi: 584
|
creare una mappa in java
volendo realizzare con java swing qlc di simile a una mappa cliccabile (ad esempio ho un immagine che rappresenta l'italia e voglio cliccare sulle diverse regioni per verificare un evento) come bisogna procedere, potete darmi qlc suggerimento ed è una cosa fattibile utilizzando java?
grazie!!! |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
L'idea più "manuale" (senza usare classi ad hoc) è questa: 1) Carichi l'immagine e la piazzi in una precisa posizione (sai in pratica le coordinate x e y, relative alla finestra, in cui si trova l'angolo superiore sinistro dell'immagine). 2) Conoscendo anche le dimensioni dell'immagine calcolata (e le sai facilmente), ti basta catturare gli eventi "click" del mouse: nella relativa callback, in cui conosci la posizione del mouse in quel momento, puoi sapere DOVE l'utente ha cliccato, e reagire di conseguenza. Ovviamente puoi affinare molto la cosa, ad esempio crei una sorta di "backbuffer" per l'immagine (una matrice in cui ogni elemento rappresenta una regione dell'immagine - come se suddividessi in tanti quadrati l'immagine di partenza) ed al click del mouse attivi una precisa regione (un elemento del backbuffer). EDIT: Nel caso vuoi procedere con il "backbuffer", ti consiglio di dare un'occhiata alla classe ImageObserver di java.awt
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson Ultima modifica di -fidel- : 16-05-2007 alle 10:25. |
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Jul 2005
Messaggi: 584
|
ma se la zona dove devo cliccare contiene nello stesso rettangolo/quadrato anche una parte di di un'alta regione, cioè non ho forme regolari (es. l'italia con le varie regioni e a ogni regione è associato un evento "clic" del mouse)
hai per favore il link a qualche esempio? grazie!!! |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Jul 2002
Messaggi: 4334
|
Non e' banale, ma...
Se hai il controllo sulla mappa (se la fai tu) potresti adottare questo accorgimento: Colori le varie regioni (es. dell'Italia) ognuna di un diverso colore, e quando rilevi il click del mouse basta che controlli il colore del pixel, e sai su che regione hai cliccato!
__________________
|Java Base| |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Quella di lovaz è una soluzione particolarmente acuta. Ti consente, in effetti, di creare immagini cliccabili senza dover passare per uno strumento autonomo di definizione delle regioni. Ed è anche semplice da realizzare, sia teoricamente che praticamente.
Rispetto all'alternativa, cioè l'uso di poligoni vettoriali (a là image map html), consuma un po' più di memoria. Ma vale l'equazione classica cpu = 1 / memoria. Ecco come si potrebbe fare. Pigli l'immagine da rendere interattiva. Ne crei una copia e la colori per regione, con GIMP. In un file di testo (o xml o come preferisci) tieni traccia delle associazioni regione-colore. Tipo: RGB(255, 255, 255) = Lazio RGB(0, 0, 0) = Emilia Romagna RGB(100, 100, 100) = Molise eccetera (ok, non le so tutte A questo punto hai per le mani due immagini e un file. La cartina, la cartina colorata e il file delle associazioni colore-regione. E sei a posto. Proietti sullo schermo la cartina normale. Carichi in memoria la cartina colorata. Carichi le associazioni colore-regione in una mappa, nel senso della struttura dati (Map<Color, String>) Al click del mouse sulla cartina prendi il colore del pixel sulla cartina in memoria int argb = cartina.getRGB(mouse.getX(), mouse.getY()); Color pixelColor = new Color(argb); Col colore ottieni la regione: String regione = mappaColoriRegioni.get(pixelColor); E una volta che sei in grado di identificare la regione sei a cavallo. Puoi collegare a colpi di Map il nome della regione a degli oggetti e gli oggetti fanno un po' quello che ti pare.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#6 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
forse allora può esserti utile il celebre Five-Coloring Algorithm: http://en.wikipedia.org/wiki/Five_color_theorem (guarda in fondo).
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Il meccanismo descritto da PGI-Bis è in pratica lo stesso usato nel Picking OpenGL.
Il problema che sorge è in presenza di mappe molto grandi, immagini che occupano molti megabytes o in presenza di molte immagini, in cui avviene/può avvenire un calo di prestazioni. In quel caso. si può ottimizzare il tutto creando delle aree precise (sempre la matrice di cui parlavo prima) che vengono caricate su richiesta (quando clicchi, se l'elemento della matrice "back" non ha ancora il suo pezzetto di immagine associata, la carichi). Il confronto sul colore lo fai quindi solo sulla sezione (in gergo "texel") corrispondente all'area attiva (area = elemento della matrice). Ancora, si può sfruttare ad esempio l'algoritmo postato da 71104 per creare dinamicamente la mappa colorata a partire da uno schema vettoriale (per emulare le map html), in questo mdo l'implementazione diventa generica ed applicabile a tutte le immagini che vuoi. EDIT: il meccanismo che avevo postato all'inizio è semplicissimo da implementare, ma evidentemente non fa al caso tuo
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson Ultima modifica di -fidel- : 16-05-2007 alle 11:51. |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Jul 2005
Messaggi: 584
|
utilizzando il metodo dei colori se ho capito bene verrà visualizzata la cartina originale (con laghi, fiumi, strade, ...) e a questa è sovrapposta un'altra "trasparente" suddivisa per regione = determinato colore, ma come si fa a sovrapporre le due e quella dei colori renderla trasparente
volendo utilizzare invece l'alternativa dei poligoni vettoriali come è, più facile da realizzare oppure no, e come funziona
|
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
In più poi, puoi anche "illuminare" la regione cliccata sulla cartina visualizzata, ma è un'altro paio di maniche. Per i poligoni vettoriali, secondo me per il momento lasciali stare (tra l'altro, con l'algoritmo dei 5 colori, usi appunto 5 colori, ma tu non hai 5 regioni... è più facile avere n colori per n regioni distinte, per semplificare l'associazione colore-regione.
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson |
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Per i poligoni dovresti creare a parte uno strumento che ti consenta di creare e salvare dei poligoni vettoriali associati alle regioni.
Dopodichè carichi la tua cartina e la proietti, carichi i poligoni come oggetti GeneralPath e li metti in una lista. Quando l'utente fa "click", prendi il punto dove l'ha fatto, prendi la lista di GeneralPath che hai memorizzato e, semplicemente, dici: Codice:
dato il Point CLICK = mouseEvent.getPoint();
per ogni GeneralPath GP nella lista L
se GP.contains(CLICK)
la regione è quella associata a GP
altrimenti
continua
Il problema qui è creare i poligoni associati alle regioni. Non basta più Paint. Ci vuole uno strumento vettoriale che possa esportare i poligoni in un formato trasformabile in un GeneralPath. E' un programma di facile realizzazione ma bisogna sempre farlo.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Jul 2005
Messaggi: 584
|
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Jul 2002
Messaggi: 4334
|
Mostri la prima, carichi la seconda in memoria.
Quando si clicca sullo schermo vai a vedere sulla mappa "nascosta" il colore del pixel alla posizione cliccata (a meno di offset).
__________________
|Java Base| |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Tra un attimo incollo il codice... prima mi bevo un caffettino (ho un bufalo alla brace sullo stomaco)
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Allora. Questo è il succo di tutto il programma.
Codice:
package it.hello.imagemap;
import java.awt.event.*;
public interface ClickToItem {
Object getItemForClick(MouseEvent e);
}
Codice:
IN ALTO=255,0,0 IN BASSO=0,0,255 IN MEZZO=0,255,0 Quel formato può essere trasformato in una mappa (Colore, Nome) con una semplice funzione: Codice:
private static Map<Object, Object> readColorMap(String relativeURL)
throws IOException
{
Map<Object, Object> map = new HashMap<Object, Object>();
Scanner scanner = new Scanner(Main.class.getResourceAsStream(
relativeURL));
try {
while(scanner.hasNextLine()) {
String[] tokens = scanner.nextLine().split("=");
String name = tokens[0].trim();
String[] rgbValues = tokens[1].split(",");
Color color = new Color(
Integer.parseInt(rgbValues[0].trim()),
Integer.parseInt(rgbValues[1].trim()),
Integer.parseInt(rgbValues[2].trim()));
map.put(color, name);
}
} finally {
if(scanner != null) scanner.close();
}
return map;
}
La versione di ClickToItem che analizza i pixel di un'immagine colorata per determinare quale "nome" sia associato può essere: Codice:
package it.hello.imagemap;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.util.*;
public class ColorClickToItem implements ClickToItem {
private BufferedImage image;
private Rectangle imageBounds;
private Map<Object, Object> colorMap = new HashMap<Object, Object>();
public ColorClickToItem(BufferedImage image, Map<Object, Object> map) {
this.image = image;
imageBounds = new Rectangle(0, 0, image.getWidth(), image.getHeight());
colorMap.putAll(map);
}
public Object getItemForClick(MouseEvent e) {
JComponent component = (JComponent)e.getComponent();
Point position = e.getPoint();
Insets margin = component.getInsets();
position.translate(-margin.top, -margin.left);
Color pixelColor = getPixelColor(position);
return colorMap.get(pixelColor);
}
private Color getPixelColor(Point p) {
return
imageBounds.contains(p) ?
new Color(image.getRGB(p.x, p.y)) :
null;
}
}
Prendi il punto, trasforma il punto, trova il pixel, trova l'oggetto associato al pixel. Il resto è storia. L'interfaccia per provare è una finestra con dentro un'etichetta. L'etichetta proietta un'immagine. C'è un MouseListener connesso all'etichetta. Quando intercetta un click chiede da un ClickToItem quale sia il "nome" corrispondente. E apre una tristissima finestrella con quel nome Codice:
package it.hello.imagemap;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
public class MainFrame {
private JFrame window = new JFrame("Click to item");
private ClickToItem clickManager;
public MainFrame(BufferedImage image, ClickToItem aClickToItem) {
clickManager = aClickToItem;
JLabel imageLabel = new JLabel(new ImageIcon(image));
imageLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
imageLabel.addMouseListener(mouseManager);
imageLabel.addMouseMotionListener(mouseManager);
JPanel container = new JPanel(new GridBagLayout());
GridBagConstraints lim = new GridBagConstraints();
lim.gridx = lim.gridy = 0;
container.add(imageLabel, lim);
window.add(container);
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public void show() {
window.pack();
window.setSize(
window.getWidth() + window.getWidth() * 5 / 100,
window.getHeight() + window.getHeight() * 5 / 100);
window.setResizable(false);
window.setVisible(true);
}
private void performActionForItem(Object item) {
JOptionPane.showMessageDialog(window, item);
}
private MouseInputAdapter mouseManager = new MouseInputAdapter() {
public void mouseClicked(MouseEvent e) {
if(SwingUtilities.isLeftMouseButton(e)) {
Object item = clickManager.getItemForClick(e);
if(item != null) {
performActionForItem(item);
}
}
}
public void mouseMoved(MouseEvent e) {
if(clickManager.getItemForClick(e) == null) {
e.getComponent().setCursor(Cursor.getDefaultCursor());
} else {
e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
}
};
}
Codice:
package it.hello.imagemap;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.*;
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
final BufferedImage image;
final BufferedImage colorMap;
Map<Object, Object> itemMap;
/* Carica le immagini e la mappa */
try {
image = ImageIO.read(Main.class.getResource("/immagini/immagine1vi6.png"));
colorMap = ImageIO.read(Main.class.getResource("/immagini/immagine1vi6_colori.png"));
itemMap = readColorMap("/immagini/mapitems.txt");
} catch(java.io.IOException ex) {
showError(ex);
return;
}
/* Con la mappa crea un ColorClickToItem */
final ColorClickToItem clicker = new ColorClickToItem(
colorMap,
itemMap);
/* Con l'immagine della cartina e il color click to item crea
l'interfaccia e la proietta sullo schermo */
SwingUtilities.invokeLater(new Runnable() { public void run() {
new MainFrame(image, clicker).show();
}});
}
/* se qualcosa va a catafascio... */
private static void showError(Throwable t) {
JOptionPane.showMessageDialog(null,
"<html>Errore del programma<br>"+t.getMessage());
}
/* Procedurone per la creazione di una mappa Color-String a partire da
un file di testo contenente un numero a piacere di linee, dove ogni linea
contiene un [token] avente la forma:
[text]=[RGB]
[text] qualsiasi sequenza di caratteri ASCII diversi dal carattere = e
interruzioni di linea
[RGB]
[R],[G],[b]
[R] = un numero intero da 0 a 255
[G] = un numero intero da 0 a 255
[b] = un numero intero da 0 a 255 */
private static Map<Object, Object> readColorMap(String relativeURL)
throws IOException
{
Map<Object, Object> map = new HashMap<Object, Object>();
Scanner scanner = new Scanner(Main.class.getResourceAsStream(
relativeURL));
try {
while(scanner.hasNextLine()) {
String[] tokens = scanner.nextLine().split("=");
String name = tokens[0].trim();
String[] rgbValues = tokens[1].split(",");
Color color = new Color(
Integer.parseInt(rgbValues[0].trim()),
Integer.parseInt(rgbValues[1].trim()),
Integer.parseInt(rgbValues[2].trim()));
map.put(color, name);
}
} finally {
if(scanner != null) scanner.close();
}
return map;
}
}
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Jan 2007
Messaggi: 2267
|
Per dovere di cronaca esiste anche il teorema dei quattro colori.
Cioè ti bastano 4 colori diversi per colorare tutta la mappa.
__________________
Concluso con:... |
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Jul 2005
Messaggi: 584
|
grazie mille PGI-Bis sei stato gentilissimo adesso devo studiarmi il codice per capire bene come funziona, scusa se non ti ho risposto prima ma soltanto adesso sono riuscito a connettermi perchè ho avuto problemi con l'adsl
per il file mapitems.txt ho copiato l'esempio IN ALTO=255,0,0 IN BASSO=0,0,255 IN MEZZO=0,255,0 ma quando lancio il programma se clicco nella parte alta esce scritto "IN BASSO" , se clicco nella parte bassa esce scritto "IN ALTO" mentre la parte centrale non è cliccabile!!! quanti colori si possono utilizzare e come calcolare i valori di questi per inserirli nel file .txt ? ancora grazie!!! |
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Tutti i colori che vuoi. Io ho preso l'immagine che hai incollato, l'ho svuotata e l'ho colorata di rosso in alto, di verde al centro e di blu in basso.
Controlla che i valori dei colori che usi corrispondano a quelli nel file (in paint vedi le triplette rgb facendo doppio click sul colore e scegliendo "definisci colori personalizzati") e non usare immagini compresse con perdita di informazioni (png sì, jpg no).
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Jul 2005
Messaggi: 584
|
ho ricolorato l'immagine con i colori che mi hai detto ed adesso funziona perfettamente!!!
grazie!!! |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 20:27.












|










