在可滚动的JPanel上绘制形状

时间:2018-12-10 19:47:21

标签: java swing

我试图在相当大的图像上绘制矩形,以获取图像内对象的像素坐标。我能够显示图像并使其可滚动,或者显示图像并能够在其顶部绘制矩形。...但不能同时显示两者。

很明显,我是在试图在其上绘制矩形的画布上绘制图像,但我一生都无法弄清楚如何使其全部并存。

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;

import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DrawRect extends JPanel {

    int x, y, x2, y2;
    private static final long serialVersionUID = 1L;
    private BufferedImage image;
    private JPanel canvas;

    public static void main(String[] args) {
        JPanel p = new DrawRect();
        JFrame f = new JFrame();
        f.setContentPane(p);
        f.setSize(400, 300);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

    DrawRect() {
        x = y = x2 = y2 = 0; //
        MyMouseListener listener = new MyMouseListener();
        addMouseListener(listener);
        addMouseMotionListener(listener);

        try {
            this.image = ImageIO.read(new URL("https://previews.123rf.com/images/victoroancea/victoroancea1201/victoroancea120100059/12055848-tv-color-test-pattern-test-card-for-pal-and-ntsc.jpg"));
        }catch(IOException ex) {
            Logger.getLogger(DrawRect.class.getName()).log(Level.SEVERE, null, ex);
        }

        this.canvas = new JPanel() {
            private static final long serialVersionUID = 1L;
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.drawImage(image, 0, 0, null);
            }
        };
        canvas.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
        JScrollPane sp = new JScrollPane(canvas);
        setLayout(new BorderLayout());
        add(sp, BorderLayout.CENTER);
    }

    public void setStartPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void setEndPoint(int x, int y) {
        x2 = (x);
        y2 = (y);
    }

    public void drawRect(Graphics g, int x, int y, int x2, int y2) {
        int px = Math.min(x,x2);
        int py = Math.min(y,y2);
        int pw=Math.abs(x-x2);
        int ph=Math.abs(y-y2);
        g.drawRect(px, py, pw, ph);
    }

    class MyMouseListener extends MouseAdapter {

        public void mousePressed(MouseEvent e) {
            setStartPoint(e.getX(), e.getY());
        }

        public void mouseDragged(MouseEvent e) {
            setEndPoint(e.getX(), e.getY());
            repaint();
        }

        public void mouseReleased(MouseEvent e) {
            setEndPoint(e.getX(), e.getY());
            repaint();
        }
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.RED);
        drawRect(g, x, y, x2, y2);
    }
}

1 个答案:

答案 0 :(得分:1)

您绘制图像的JPanel必须与绘制矩形并添加了MouseAdapter的JPanel相同。例如:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class DrawRect2 extends JPanel {
    public static final String IMG_PATH = "https://previews.123rf.com/images/victoroancea"
            + "/victoroancea1201/victoroancea120100059"
            + "/12055848-tv-color-test-pattern-test-card-for-pal-and-ntsc.jpg";
    private static final int PREF_W = 600;
    private static final int PREF_H = PREF_W;
    private DrawingPanel drawingPanel;

    public DrawRect2(Image img) {
        drawingPanel = new DrawingPanel(img);
        JScrollPane scrollPane = new JScrollPane(drawingPanel);
        MyMouse myMouse = new MyMouse();
        drawingPanel.addMouseListener(myMouse);
        drawingPanel.addMouseMotionListener(myMouse);

        setLayout(new BorderLayout());
        add(scrollPane);
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private static void createAndShowGui() {
        Image img = null;
        try {
            URL url = new URL(IMG_PATH);
            img = ImageIO.read(url);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }
        DrawRect2 mainPanel = new DrawRect2(img);

        JFrame frame = new JFrame("DrawRect2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

}

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class DrawingPanel extends JPanel {
    private Image img;
    private Rectangle rectangle;

    public DrawingPanel(Image img) {
        this.img = img;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (img != null) {
            g.drawImage(img, 0, 0, this);
        }
        if (rectangle != null) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setXORMode(Color.WHITE);
            g2.draw(rectangle);
            g2.dispose(); // since we created this object
        }
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension superSize = super.getPreferredSize();
        if (img == null) {
            return super.getPreferredSize();
        } else {
            int w = img.getWidth(this);
            int h = img.getHeight(this);
            return new Dimension(w, h);
        }
    }

    public void setRectangle(Rectangle rectangle) {
        this.rectangle = rectangle;
    }
}

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class MyMouse extends MouseAdapter {
    private Point p1;

    @Override
    public void mousePressed(MouseEvent e) {
        p1 = e.getPoint();
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (p1 != null) {
            createRect(e);
        }
    }

    private void createRect(MouseEvent e) {
        Point p2 = e.getPoint();
        int x = Math.min(p1.x, p2.x);
        int y = Math.min(p1.y, p2.y);
        int width = Math.abs(p1.x - p2.x);
        int height = Math.abs(p1.y - p2.y);

        Rectangle r = new Rectangle(x, y, width, height);
        ((DrawingPanel) e.getSource()).setRectangle(r);
        ((DrawingPanel) e.getSource()).repaint();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (p1 != null) {
            createRect(e);
        }
        p1 = null;
    }
}

因此,在此paintComponent方法中,我使用Graphics2D XOR模式绘制图像和矩形,无论背景颜色如何,都可以帮助显示线条:

@SuppressWarnings("serial")
public class DrawingPanel extends JPanel {
    private Image img;
    private Rectangle rectangle;

    public DrawingPanel(Image img) {
        this.img = img;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (img != null) {
            g.drawImage(img, 0, 0, this);
        }
        if (rectangle != null) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setXORMode(Color.WHITE);
            g2.draw(rectangle);
            g2.dispose(); // since we created this object
        }
    }

我也有这种方法:

public void setRectangle(Rectangle rectangle) {
    this.rectangle = rectangle;
}

允许MouseListener / Adapter将Rectangle传递到此JPanel中。

    Rectangle r = new Rectangle(x, y, width, height);
    ((DrawingPanel) e.getSource()).setRectangle(r);
    ((DrawingPanel) e.getSource()).repaint();