# Rechtecke auf Bild zeichnen



## Martwig (10. Apr 2010)

Hallo zusammen,
ich bitte zu verzeihen, dass es sich bei meinem ersten Post gleich um eine Frage handelt ;-).
Und zwar brauch ich Hilfe bei meinem aktuellen Problem. 

Ich möchte gern Rechtecke auf ein Bild zeichnen. Allerdings habe ich keine Idee, wie ich das Zeichnen "ruckelfrei" hinbekomme. Das Rechteck verschwindet durch das "repaint" nach kurzer Zeit wieder, wenn ich mit dem Mauszeiger auf einer Stelle bleibe. Außerdem würde ich gern ein Rechteck, wenn es einmal gezeichnet wurde, nicht wieder löschen. Es sollen also mehrere Rechtecke gezeichnet werden können.


```
public void mouseReleased(MouseEvent e) {
        Graphics gPaint = image.getGraphics();
        gPaint.drawRect(Rect.x, Rect.y, e.getX()-Rect.x, e.getY()-Rect.y);
    }

    public void mouseDragged(MouseEvent e) {
        Rect.width = e.getX()-Rect.x;
        Rect.height = e.getY()-Rect.y;
        thisPanel.repaint();
    }

public class myImagePanel extends JPanel {
        @Override
    protected void paintComponent (Graphics g) {
        super.paintComponent(g);
        if ((Rect!= null) && (image != null)) {
            Graphics gPaint = image.getGraphics();
            gPaint.drawRect(Rect.x, Rect.y, Rect.width, Rect.height);
        }
    }
```

Würde mich freuen wenn jemand einen Tipp hat!
Mario


----------



## Landei (10. Apr 2010)

Wenn ich das richtig sehe, malst du nur auf das Graphics-Objekt vom Bild, nicht auf das übergebene Graphics g. Wahrscheinlich hilft schon ein g.drawImage(0, 0, image, null) oder so am Ende


----------



## Martwig (10. Apr 2010)

Danke für die Antwort. Was soll das "gPaint.drawImage(image,0, 0, null);" denn machen? Verstehe ich nicht so richtig. Wichtig wäre vll. auch noch zu erwähnen, dass es sich bei dem Bild um ein _DisplayJAI_ handelt.


----------



## Martwig (11. Apr 2010)

Ich habe noch etwas rumgesucht und folgende Anleitung gefunden: Handbuch der Java-Programmierung, 5. Auflage

Das habe ich erst mal so übernommen. Nun ist mein Problem, dass ich die Rechtecke *auf* ein Bild zeichnen will, er sie aber darunter zeichnet. Ich würde mich freuen, wenn noch jemand eine Idee hat. Hier der Code:


```
public void mousePressed(MouseEvent e) {
        paintRect= new Rectangle();
        paintRect.x=e.getX();
        paintRect.y=e.getY();
    }

    public void mouseReleased(MouseEvent e) {
       if (paintRect.width > 0 || paintRect.height > 0) {
         drawlist.addElement(paintRect); //private Vector drawlist
       }
       repaint();
     }

//...
    public void mouseDragged(MouseEvent e) {

       int x = e.getX();
       int y = e.getY();
       if (x > paintRect.x && y > paintRect.y) {
         paintRect.width = x - paintRect.x;
         paintRect.height = y - paintRect.y;
       }
       repaint();
     }



public class MyImagePanel extends JPanel {        
        @Override
     protected void paintComponent (Graphics g) {
         super.paintComponent(g);
         Rectangle r;
         Enumeration e;
         thisPanel.add(srcScrollPaneImage); //eine ScrollPane, die ein Bild "srcdj" enthält

         Graphics gTemp = srcdj.getGraphics(); //weil ich ja auf das Bild zeichnen will
         for (e = drawlist.elements(); e.hasMoreElements(); ) {
             r = (Rectangle)e.nextElement();
             gTemp.drawRect(r.x, r.y, r.width, r.height);
         }
         if (paintRect.x > 0 || paintRect.y > 0) {
            gTemp.drawRect(paintRect.x, paintRect.y, paintRect.width, paintRect.height);
        }
    }
}
```
Danke! Mario


----------



## André Uhres (12. Apr 2010)

Wie der Name sagt, soll "paintComponent" die Komponente zeichnen und nicht noch eine Komponente hinzuzufügen.
Man könnte vielleicht zum Bildpanel eine Rechteckkomponente hinzufügen, die sich in Grösse und Position anpassen lässt.


----------



## Martwig (12. Apr 2010)

Hallo,
ich werde das mal versuchen. Mit dem Schreiben in die paintComponent()-Methode wollte ich vermeiden, dass die Rechtecke bei einem repaint gelöscht werden. Gibt es nicht so was wie eine durchsichtige Zeichenfläche, die ich auf mein Bild legen kann? 

Danke,
Mario


----------



## Martwig (14. Apr 2010)

Ich habe mich etwas in JavaBeans eingelesen, komme aber trotzdem überhaupt nicht weiter. Ich brauche mehrere Rechtecke auf dem Bild. Geht das mit den Komponenten? Und wo soll ich die Rechtecke denn zeichnen, wenn nicht in der paint-Methode? Schließlich sollen sie ja nicht verschwinden, wenn das Fenster neu gezeichnet wird.
Ich würde mich freuen, wenn noch jemand einen Tipp für mich hätte.
Danke!


----------



## André Uhres (15. Apr 2010)

```
/*
 * ImageMarker.java
 *
 * Benutzt die Klasse JComponentBounds:
 * http://wiki.byte-welt.net/wiki/JComponentBounds
 *
 * Hier wird ein "mainpanel" mit OverlayLayout benutzt. Darin sind ein "imagePanel"
 * und ein überlagertes "markerPanel". Die Methode "addMarker(markerPanel)" fügt
 * neue Marker hinzu.
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.*;

public class ImageMarker extends JFrame {

    private final static String FILENAME = "Picture1.jpg";
    private JPanel mainpanel;
    private Rectangle marker;
    private JLabel lbMarkerBounds;
    private JButton btAdd;
    private final JPanel markerPanel;

    public ImageMarker() {
        super("ImageMarker");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(800, 600);
        setLocationRelativeTo(null);
        mainpanel = new JPanel() {

            @Override
            public boolean isOptimizedDrawingEnabled() {
                return false;
            }
        };
        mainpanel.setLayout(new OverlayLayout(mainpanel));
        markerPanel = new JPanel(null);
        markerPanel.setOpaque(false);

        Picture imagePanel = new Picture(FILENAME);

        mainpanel.add(markerPanel);//zuerst den Marker Panel (vorne)
        mainpanel.add(imagePanel);//dann die Bildkomponente (hinten)

        add(new JScrollPane(mainpanel));
        lbMarkerBounds = new JLabel();
        add(lbMarkerBounds, BorderLayout.NORTH);
        btAdd = new JButton("Add Marker");
        btAdd.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent e) {
                addMarker(markerPanel);
            }
        });
        add(btAdd, BorderLayout.SOUTH);
    }

    private void addMarker(final JPanel markerPanel) {
        final JLabel markerLabel = new JLabel();
        markerLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        markerLabel.setOpaque(true);
        markerLabel.setBackground(new Color(50, 50, 50, 50));
        markerLabel.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
        marker = new Rectangle(0, 0, 100, 100);
        int m = JComponentBounds.MARGIN;
        final JComponentBounds markerBounds = new JComponentBounds(markerLabel,
                marker.x - m, marker.y - m, true);
        markerBounds.setSize(marker.width + m * 2, marker.height + m * 2);
        markerPanel.add(markerBounds);
        markerBounds.addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(final ComponentEvent e) {
                displayBounds();
            }

            @Override
            public void componentMoved(final ComponentEvent e) {
                displayBounds();
            }

            private void displayBounds() {
                marker = markerBounds.getComponentRect();
                lbMarkerBounds.setText(marker.toString());
            }
        });
        markerPanel.revalidate();
    }

    public static void main(final String[] args) {
        Runnable gui = new Runnable() {

            public void run() {
                new ImageMarker().setVisible(true);
            }
        };
        //GUI must start on EventDispatchThread:
        SwingUtilities.invokeLater(gui);
    }
}

class Picture extends JComponent {

    private BufferedImage image;
    private String filename;

    public Picture(String filename) {
        this.filename = filename;
    }

    @Override
    public void paintComponent(final Graphics g) {
        super.paintComponent(g);
        if (image == null) {
            try {
                image = ImageIO.read(getClass().getResource(filename));
                setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
                revalidate();
            } catch (Exception ex) {
                System.out.println("Bild nicht gefunden: " + filename);
                image = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
            }
        }
        Rectangle r = g.getClipBounds();
        g.drawImage(image, r.x, r.y, r.width + r.x, r.height + r.y,
                r.x, r.y, r.width + r.x, r.height + r.y, null);
    }

    public void setFilename(final String filename) {
        this.filename = filename;
        image = null;
        repaint();
    }
}
```


----------



## Martwig (15. Apr 2010)

Vielen, vielen... Dank! Ein Rundum-Sorglos-Packet habe ich jetzt echt nicht erwartet. Ich saß wirklich einige Tage an diesem Problem! :toll:


----------



## André Uhres (15. Apr 2010)

Martwig hat gesagt.:


> Ein Rundum-Sorglos-Paket habe ich jetzt echt nicht erwartet.


Es bleibt ja sicher noch viel zu tun: die Rechtecke sind ja wohl kaum Selbstzweck.


----------

