Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    come disegnare linee su un'immagine caricata?

    Salve a tutti,
    sto cercando di creare un programma che carichi un'immagine su un jpanel (all'interno di un jframe) e permetta di disegnarvi sopra delle linee o dei cerchietti (per evidenziare parti dell'immagine caricata).
    Sono riuscito a creare la prima parte del programma, ovvero riesco ad ottenere una finestra in cui disegno con il muose delle linee tondeggianti all'interno della componente.
    Il problema è caricare un'immagine e potervi disegnare sopra: ho creato du pannelli, uno su cui si disegna e l'altro che contiene l'immagine, provando a sovrapporli all'interno del jframe, ma non ho ottenuto nulla di utile, essendo che soltanto uno dei due pannelli risulta visibile (quello aggiunto per ultimo). Anche rendendo il secondo pannello aggiunto trasparente non cambia nulla, l'immagine sottostante non è visibile e inoltre il programma di disegno smette di funzionare. Come posso fare? Qulacuno può aiutarmi?
    Lorenz

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Non è chiaro se le varie figure che vuoi disegnare devono essere nella immagine per essere "permanenti" (ad esempio se poi vuoi salvare su file la immagine con ciò che hai disegnato), oppure se le figure devono stare "sopra" la immagine ma senza alterare la immagine.

    Se devi scrivere nella immagine ... beh, prendi il suo Graphics e ... ci disegni sopra. Dipende poi da chi disegna la immagine ma se hai fatto un tuo componente nel cui paintComponent() disegni la immagine, devi disegnarla dopo ogni modifica alla immagine.

    Se invece le figure devono stare "sopra" alla immagine ma non modificandola, allora ci sono diversi approcci:

    a) Le figure le disegni su una seconda immagine inizialmente tutta "trasparente". Sul tuo componente quindi disegni immagine reale e poi sopra la immagine trasparente+figure.

    b) Tutte le figure che disegni man mano le tieni in una apposita struttura dati nel tuo componente. Ad ogni richiesta di paintComponent() disegni la immagine e poi tutte le figure.
    Per questo approccio vedi tra i miei Java Examples (vedi firma), trovi esempi a riguardo.


    P.S. non tentare strade strane con sovrapposizione di più pannelli. Evitati complicazioni.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Considera che attraverso il metodo paint() e il metodo mousedragged() sono riuscito a far disegnare una serie di cerchietti sul pannello, come un evidenziatore, immagina un semplice strumento di disegno in stile paintbrush.
    HO provato a far disegnare dallo stesso metodo paint() anche l'immagine che deve essere evidenziata (l'immagine sulla quale vengono disegnati i cerchietti), all'interno delo metodo quindi avevo un g.drawImage() e un g.fillOval(). L'immagine appare sul pannello, riesco a disegnare col mouse, ma non sull'immagine caricata, credo perchè essendo che ad ogni spostamento del mouse il metodo mouseDragged() richiama il metodo paint() attraverso repaint per disegnare la serie di cerchietti, esso fa ridisegnare anche l'immagine di sfondo, che venendo ridisegnata copre i cerchietti che invece dovrebbero stare sopra di essa. INsomma, se l'immagine in questione è al centro del pannello, col mouse posso disegnarle tutto attorno, ma non sopra. Per essere più chiaro posto il codice del programma. In questa versione, per semplificare le cose dato che non hai a disposizione l'immagine che uso io, al posto dell'immagine su cui disegnare o messo un rettangolino nero. E' la stessa cosa no? IN ogni caso fai girare il programma e guarda cose si verifica.

    import javax.imageio.ImageIO;
    import javax.swing.*;
    import java.awt.*;
    import java.awt.Color.*;
    import java.awt.event.*;
    import java.applet.*;
    import java.io.File;
    import java.io.IOException;

    public class Painter extends JPanel {
    private int startXPoint = 0; // coordinata x di partenza
    private int endXPoint = 0; // coordinata x di arrivo
    private int startYPoint = 0; // coordinata y di partenza
    private int endYPoint = 0; // coordinata y di arrivo
    private boolean paint = true;
    private static Image image;




    // ascoltatore del moto del mouse
    class mMotionListener implements MouseMotionListener {
    public void mouseDragged(MouseEvent e) {
    // aggiorna le coordinate
    startXPoint = endXPoint;
    startYPoint = endYPoint;
    endXPoint = e.getX();
    endYPoint = e.getY();
    Painter.this.repaint();

    System.out.println(startXPoint+" "+startYPoint+" "+ endXPoint +" "+endYPoint);
    // disegna

    }
    public void mouseMoved(MouseEvent e) {
    // aggiorna le coordinate

    endXPoint = e.getX();
    endYPoint = e.getY();
    }
    }
    //ascoltatore dei pulsanti del mouse
    class mListener implements MouseListener {
    // i seguenti metodi sono richiesti dalla
    // interfaccia MouseListener anche se non
    // vengono utilizzati
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}

    // pulsante premuto
    public void mousePressed(MouseEvent e) {
    // attiva la modalita' di disegno
    paint = true;
    }
    // pulsante rilasciato
    public void mouseReleased(MouseEvent e) {
    // disattiva la modalita' di disegno
    paint = false;
    }
    }


    // Costruttore della classe principale
    public Painter() {
    super();

    MouseListener ml = new mListener();
    addMouseListener(ml);

    MouseMotionListener mml = new mMotionListener();
    addMouseMotionListener(mml);





    }

    public void paintComponent(Graphics g){
    //super.paintComponent(g);
    g.setColor(Color.black);
    g.fillRect(120,120,120,120);
    //g.drawImage(image, 0, 0, null);
    if(paint) {
    g.setColor(Color.MAGENTA) ;
    g.fillOval(startXPoint,startYPoint,10,10);
    }
    }

    /* public void paint(Graphics g) {
    // se e' attiva la modalita' di disegno, traccia una riga
    if(paint) {
    g.setColor(Color.MAGENTA) ;
    g.fillOval(startXPoint,startYPoint,10,10);
    }

    } */ //questa parte del codice non c'entra
    public static void main(String argv[]) {
    try {
    image = ImageIO.read(new File ("/Users/Flocklaw/Desktop/IMG_6335.JPG"));
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    Painter p = new Painter();



    JFrame f = new JFrame("Painter");
    f.getContentPane().add(p);
    f.setSize(400,300);
    f.setVisible(true);


    }
    }


    Per quanto riguarda il consigli che mi hai dato, come faccio a creare un'immagine trasparente? Potresti fornire maggiori dettagli o indicarmi quale degli java examples che fornisci nella pagina web mi converrebbe consultare?

    Grazie dell'aiuto.
    Lorenz

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da flocklaw
    Considera che attraverso il metodo paint()
    Nei componenti Swing è paintComponent() .... dimentica paint().

    Originariamente inviato da flocklaw
    e il metodo mousedragged() sono riuscito a far disegnare una serie di cerchietti sul pannello
    Ma l'approccio è totalmente sbagliato!! Perché quando il cursore si muove tu memorizzi la posizione e chiedi il repaint. E nel paintComponent() disegni solo il pallino a quel punto. L'unica cosa che ti "salva" è che aggiungi sempre senza prima aver azzerato il resto (hai commentato il super.paintComponent(g).

    Ma se provi a ridimensionare la finestra o a minimizzarla e poi ripristinarla .... sparisce tutto!!! Perché non è così che va fatto!!

    Se vuoi che sia davvero permanente: a) disegni le aggiunte man mano su una immagine (e questo è "permanente") che poi disegni sul componente oppure b) mantieni una struttura dati in cui memorizzi ogni figura e nel paintComponent() li disegni tutti.

    paintComponent() non vuol dire "disegna un pezzetto in più'' ... vuol dire "senti componente, disegna l'intero tuo stato".

    Originariamente inviato da flocklaw
    Per quanto riguarda il consigli che mi hai dato, come faccio a creare un'immagine trasparente?
    Un BufferedImage con tipo TYPE_INT_ARGB, se non sbaglio.
    Oppure, meglio, ti fai dare una immagine "compatibile" con il display da createCompatibleImage() di java.awt.GraphicsConfiguration.

    Originariamente inviato da flocklaw
    Potresti fornire maggiori dettagli o indicarmi quale degli java examples che fornisci nella pagina web mi converrebbe consultare?
    Quelli nella sezione AWT/Swing - Graphics.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Per ottenere l'immagine compatibile può andare un metodo del genere?

    public void image (GraphicsConfiguration cfg){

    BufferedImage buffer = new BufferedImage(10, 10, 10);
    buffer=cfg.createCompatibleImage(300, 500);

    }

    e una volta che ho ottenuto l'immagine compatibile come faccio a far sì che paint disegni sopra a quell'immagine e non direttamente sul pannello?
    Lorenz

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da flocklaw
    Per ottenere l'immagine compatibile può andare un metodo del genere?

    public void image (GraphicsConfiguration cfg){

    BufferedImage buffer = new BufferedImage(10, 10, 10);
    buffer=cfg.createCompatibleImage(300, 500);

    }
    No, non proprio. Intanto devi ottenere un GraphicsConfiguration. Poi comunque hai istanziato un BufferedImage che non ti serve .... perché nella riga dopo assegni a 'buffer' un altro BufferedImage ritornato da createCompatibleImage.
    Anche ammesso che il new BufferedImage(...) che hai messo fosse davvero utile, nel terzo parametro non dovresti passare una costante numerica 10 o simile ... devi mettere una delle costanti definite in BufferedImage. Ma non un valore numerico diretto!!! Chiaro?

    E infine, il createCompatibleImage che hai usato ti fornisce una immagine "opaca" ... non trasparente. Se intendevi usare la tecnica che ho detto della immagine "trasparente" su cui disegni le figure e che sta "sopra" la vera immagine, non va bene. Devi usare l'altro createCompatibleImage().

    In definitiva, no non va bene.

    Originariamente inviato da flocklaw
    e una volta che ho ottenuto l'immagine compatibile come faccio a far sì che paint disegni sopra a quell'immagine e non direttamente sul pannello?
    No, non è il paintComponent() che deve disegnare su questa immagine "trasparente"!!!

    Hai 2 immagini: A è quella "vera", B è quella "trasparente" su cui disegni le figure. Quando a seguito di qualche evento (quello/i che hai scelto ... non lo so) devi disegnare una figura, prendi il Graphics/Graphics2D della immagine B e ... disegni la figura. Quindi chiedi il repaint() del tuo componente e nel paintComponent() disegni prima A e poi "sopra" B.
    Tutto qui.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Grazie mille.
    Sono riuscito a fare girare il programma correttamente.
    Ora:
    ho creato due finestre sulle quali disegnare sulla stessa immagine. Lo scopo finale del programma è verificare se le porzioni di area evidenziate all'interno delle due finestre sono le stesse (lo scopo è verificare se due ipotetici giocatori evidenziano le stesse parti di un'immagine, non so se mi spiego).
    Ho provato a fare confrontere il programma le coordinate dei punti centrali degli ovali disegnati sulle immagini, ma il metodo si è rivelato alquanto impreciso. Necessito di confrontare l'intera area occupata da ogni piccolo ovale disegnato, per ottenere un migliore confronto.
    Come posso, una volta che disegno un singolo ovale, ottenere l'insieme dei punti (espressi i tramite coordinate xy) occupati da quell'ovale?

    Non so se mi sono spiegato, se è necessario posso postare il codice.
    Lorenz

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da flocklaw
    Necessito di confrontare l'intera area occupata da ogni piccolo ovale disegnato, per ottenere un migliore confronto.
    Come posso, una volta che disegno un singolo ovale, ottenere l'insieme dei punti (espressi i tramite coordinate xy) occupati da quell'ovale?
    Di per sé no, non puoi (se anche si potesse ... non lo so in questo momento ... sarebbe comunque non banale e di certo non comodo da gestire!). E bisognerebbe anche vedere se hai disegnato le figure con o senza anti-aliasing.

    Se vuoi semplicemente verificare se 2 cerchi (parlo proprio di cerchio, non di un ellisse generico) si "intersecano", la regola se non sbaglio dovrebbe recitare così: due cerchi si intersecano se la distanza tra i loro centri è minore della somma dei due raggi.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    Ho provato a usare questa tecnica, ma genera svariati problemi:
    disegno una serie di piccoli quadratini della dimensione di 10 pixel x 10. Ogni volta che disegno un quadrato, ottengo le coordinate del punto di partenza e calcolo tutti i punti che vengono occupati dal quadrato disegnato. Ognuna di queste coordinate viene memorizzata in un vettore, che progressivamente viene allungato tramite l'aggiunta di tutte le coordinate dei punti occupati dall'area del quadrato successivo. Dopodichè ho implementato un piccolo ciclo che fa sì che, se due quadrati vengono sovrapposti, nel vettore vengono memorizzati i nuovi punti che non sono in comune hai due quadrati.
    Fin qui tutto bene, finchè mi sono accorto, che disegnando molti quadrati il programma rallenta e dopo poco non disegna più, credo a causa del ciclo che mi aiuta a controllare se una coordinata è presente all'interno dell'array. Se infatti non mi curo di non aggiungere al vettore le coordinate già presenti fila tutto liscio.
    Se non sussistesse questo problema, la maggiorparte del lavoro sarebbe fatta, dato che dal momento che conosco tutte le coordinate dei punti evidenziati sulle due immagini, posso fare un confronto tra i due array di coordinate e stabilire quanti punti vi sono in comune, definendo una percentuale di punti evidenziati in comune.

    Sai darmi qualche consiglio?
    Lorenz

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da flocklaw
    Ogni volta che disegno un quadrato, ottengo le coordinate del punto di partenza e calcolo tutti i punti che vengono occupati dal quadrato disegnato. Ognuna di queste coordinate viene memorizzata in un vettore
    Sei libero di credermi oppure no .... ma dal mio punto di vista stai solo facendo un inutile grosso lavoro ....

    Originariamente inviato da flocklaw
    Sai darmi qualche consiglio?
    Sì, quello di ragionare con la "matematica".
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.