Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1

    Disengare cerchio su JPanel in tempo reale

    ciao!
    ho questo JPanel su cui disegnare:
    codice:
    private class ImagePanel extends JPanel implements MouseListener, MouseMotionListener {
    
            private FileChooserPanel jfc = new FileChooserPanel();
            private BufferedImage buff;
            private Rectangle currentRect;
            private String fileDelete;
            private int xx = 0;
            private int yy = 0;
            private int w = 0;
            private int h = 0;
            boolean done = false;
            String forma;
    
            public ImagePanel(String path, String forma) {
                setLayout(new BorderLayout());
                setPreferredSize(new Dimension(width, height));
                fileDelete = path;
                this.forma = forma;
                try {
                    buff = ImageIO.read(new File(path));
                    button.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            capture(e);
                            dispose();
                        }
                    });
                    addMouseListener(this);
                    addMouseMotionListener(this);
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(null, ex.getMessage());
                }
            }
    
            @Override
            public void mousePressed(MouseEvent e) {
                xx = e.getX();
                yy = e.getY();
                currentRect = new Rectangle(xx, yy, 0, 0);
            }
    
            @Override
            public void mouseDragged(MouseEvent e) {
                currentRect.setSize(e.getX() - currentRect.x, e.getY() - currentRect.y);
                repaint();
            }
    
            @Override
            public void mouseReleased(MouseEvent e) {
                w = e.getX() - currentRect.x;
                h = e.getY() - currentRect.y;
                currentRect.setSize(w, h);
                done = true;
                repaint();
            }
    
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                 g.drawImage(buff, 0, 0, this);
                 g.setColor(Color.RED);
                g.drawOval(xx, yy, w, h);
            }
    
            @Override
            public void mouseClicked(MouseEvent e) {
            }
    
            @Override
            public void mouseEntered(MouseEvent e) {
            }
    
            @Override
            public void mouseExited(MouseEvent e) {
            }
    
            @Override
            public void mouseMoved(MouseEvent e) {
            }
        }
    il tutto funziona più o meno, ma ho due domande:
    -prima di tutto viene disegnato un ovale e non un cerchio: come posso fare per ottenere un cerchio?
    -inoltre la linea si vede solo quando il mouse viene rilasciato: è possibile far vedere le linee in tempo reale??

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    -prima di tutto viene disegnato un ovale e non un cerchio: come posso fare per ottenere un cerchio?
    Adesso ottieni un ovale (in generale) perché larghezza/altezza sono sostanzialmente controllati solo ed esclusivamente dall'utente.
    Se vuoi sempre un cerchio puoi usare la lunghezza su un asse anche per l'altro asse oppure fare una logica più complessa del tipo "quale è il cerchio che sta perfettamente inscritto/centrato in un rettangolo" ma richiede qualche calcolo in più.
    Più che altro cambia poi quello che l'utente deve aspettarsi.

    Quote Originariamente inviata da fermat Visualizza il messaggio
    -inoltre la linea si vede solo quando il mouse viene rilasciato: è possibile far vedere le linee in tempo reale??
    Sì ovviamente è possibile. Nota che attualmente w e h (quelli che usi nel drawOval) li assegni solo nel mouseReleased. Basta che il size attuale, quello che l'utente sta cambiando, si rifletta subito, e non solo più al mouseReleased, nel painting.

    Banalmente:
    g.drawOval(xx, yy, currentRect.width, currentRect.height);


    Una nota finale: facendo come ho appena detto, usi currentRect nel paintComponent. Ma la variabile currentRect è inizialmente a null e al primo paintComponent ci sarà un NullPointerException. Quindi o inizializzi currentRect o salti il drawOval se è null.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    ciao andbin.

    allora, per il primo problema ho risolto banalmente così:
    codice:
    g.drawOval(xx, yy, w, w);
    in effetti non ci avevo pensato.

    per il secondo problema.
    currentRect è un oggetto Rectangle.
    ho modificato il metodo così:
    codice:
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.drawImage(buff, 0, 0, this);
                g.setColor(Color.RED);
                switch (forma) {
                    case "rectangle":
                        if (done) {
                            g.drawRect(xx, yy, currentRect.width, currentRect.height);
                        }
                        break;
                    case "circle":
                        if (done) {
                            g.drawOval(xx, yy, currentRect.width, currentRect.width);
                        }
                        break;
                    default:
                        break;
                }
            }
    non ottengo errori in quanto ci pensa la variabile done.
    solo che con la forma rettangolo nessun problema, mentra con il cerchio si, in quanto ottengo cmq un rettangolo.
    penso che dipenda dal fatto che currentRect è un oggetto Rectangle.
    c'è un qualche oggetto che rappresenti un ovale??

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    allora, per il primo problema ho risolto banalmente così:
    codice:
    g.drawOval(xx, yy, w, w);
    Infatti. Avresti potuto mettere h, h oppure per entrambi i valori "il minore tra w e h". In tutti questi casi faresti sempre un cerchio. Cambia solo dal punto di vista di come/quanto l'utente deve spostarsi in base a cosa si aspetta di ottenere.

    Quote Originariamente inviata da fermat Visualizza il messaggio
    penso che dipenda dal fatto che currentRect è un oggetto Rectangle.
    c'è un qualche oggetto che rappresenti un ovale??
    Non è un problema di Rectangle, non lo stai usando come "shape" da disegnare direttamente ma solo come "contenitore" di locazione+dimensione. Materialmente usi drawOval e questo fa quello che dice il nome: disegna un "ovale".
    Se dici che disegna un rettangolo, probabilmente non sta passando da lì e la radice del problema è altrove.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    scusa, mi sono espresso male.
    il programma in sostanza salva la porzione disegnata in una immagine.
    sul jpanel compare un ovale, ma l'immagine salvata è rettangolare.
    sul jpanel c'è di default una immagine dell'intero schermo.
    ho usato un BufferedImage.
    quando clicco sul bottone:
    codice:
            public void capture(ActionEvent e) {
                try {
                    BufferedImage subBuff = buff.getSubimage(xx, yy, w, h);
                    jfc.salva(subBuff);
                    DeleteTemp.delete(fileDelete);
                } catch (AWTException | IOException ex) {
                    JOptionPane.showMessageDialog(null, ex.getMessage());
                }
            }
    probabilmente è qua l'errore.
    le coordinate le imposto qua:
    codice:
            @Override
            public void mouseReleased(MouseEvent e) {
                w = e.getX() - currentRect.x;
                h = e.getY() - currentRect.y;
                currentRect.setSize(w, h);
                done = true;
                repaint();
            }

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    ma l'immagine salvata è rettangolare.
    Ovvio .... qualunque formato "raster" (bitmap), insomma non "vettoriale" ... è rettangolare!!

    Se vuoi che nel file salvato ci sia l'immagine solo nell'ovale e nel resto ci sia o un colore fisso (es. nero) oppure completa "trasparenza" ..... beh, si può fare ma è un altro paio di maniche ...
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    ok grazie per la spiegazione!!

    mi puoi dare una dritta su quest'altro paio di maniche please???

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    mi puoi dare una dritta su quest'altro paio di maniche please???
    Può darsi che ci siano diversi modi, quello che mi viene in mente (e che userei io senza andarmi a spulciare tutta la documentazione per vedere se ci sono altri modi) è:

    - crei un nuovo BufferedImage della larghezza/altezza dell'ovale. Il BufferedImage puoi crearlo con o senza "alpha channel" (vedi Javadoc, in particolare il imageType per creare l'immagine).
    - prendi il Graphics2D ( createGraphics() ) del BufferedImage e puoi riempire tutto il rettangolo con un colore fisso con/senza semi-trasparenza.
    - crei un Ellipse2D.Float che modella l'ovale. L'origine deve essere 0,0 (perché è l'origine nella immagine da salvare).
    - sul Graphics2D imposti l'area di "clip" ( clip(Shape s) ). Nota, Ellipse2D.Float è quello shape!
    - disegni sul Graphics2D la tua immagine originale, in pratica da [x , y; w x h] di src a [0 , 0; w x h] nel BufferedImage. Il drawImage da usare è uno di quelli che hanno src e dst completi.
    - fai dispose del Graphics2D e hai l'immagine da salvare.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    intanto grazie per le dritte.

    allora, fino a un certo punto ok.
    poi mi sono perso.
    codice:
            public void capture(ActionEvent e) {
                BufferedImage subBuff = new BufferedImage(w, w, BufferedImage.TYPE_INT_RGB);
                Graphics2D g2d = subBuff.createGraphics();
                g2d.setColor(Color.white);
                Shape shape = new Ellipse2D.Float();
                g2d.setClip(shape);
                g2d.drawImage(buff, xx, yy, w, w, 0, 0, w, w, ImageObserver);
            }
    principalmente sul metodo drawImage.
    nella javadoc ho visto che ne esistono molte versioni diverse.
    io pensavo a questo, che mi sembrava completo come dicevi.
    solo che richiede un oggetto ImageObserver.....

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    allora, fino a un certo punto ok.
    poi mi sono perso.
    Ci sono almeno 4 cose da sistemare:

    1) setColor per il white setta solo lo stato del colore ... non riempie la immagine, devi fare un fillRect tu per questo..
    2) Il Ellipse2D.Float lo devi creare con origine 0,0 ma con la dimensione del tuo ovale (cerchio nel tuo caso), altrimenti è inutile.
    3) Il ImageObserver serve quando una immagine è caricata in modo asincrono oppure quando è una immagine animata (es .gif) e un componente ha bisogno di "osservare" i continui aggiornamenti. Se la tua immagine originale è un BufferedImage, non ci sono "aggiornamenti" in tal senso, quindi puoi passare null.
    4) Ad "occhio" hai scambiato l'origine sorgente/destinazione nel drawImage. Il 2°/3° parametro sono l'origine nella immagine di destinazione (subBuff) quindi lì deve essere 0,0.

    E ricorda il dispose del Graphics2D alla fine.
    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.