Jframe - 绘制矩形不起作用
Jframe - Drawing Rectangles not working
我有这段代码,用于在预加载的图像上绘制一个矩形,但它不起作用。
当我将绘图 class 添加到框架时,它会覆盖图像,这意味着我看不到预加载的图像,但它仍然允许我绘制矩形。
此外,我没有将 jframe 放在屏幕中间,而是放在右上角,我必须将其最大化才能看到框架。
代码:
public class defineArea {
public static void main(String[] args) throws IOException {
displayImage();
}
private static void displayImage() throws IOException {
BufferedImage image = ImageIO.read(new File("C:\Users\Rusty\Desktop\temp\Test_PDF-1.png"));
ImageIcon icon = new ImageIcon(image);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lbl = new JLabel();
lbl.setIcon(icon);
JScrollPane jsp = new JScrollPane(lbl);
frame.add(jsp);
frame.add(new paintRectangles());
frame.pack();
frame.setVisible(true);
}
public static class paintRectangles extends JComponent {
ArrayList<Shape> shapes = new ArrayList<Shape>();
Point startDrag, endDrag;
public paintRectangles() throws IOException {
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = { Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK };
int colorIndex = 0;
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if (startDrag != null && endDrag != null) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
System.out.println(r.getBounds2D());
}
}
}
private static Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
有人能帮忙吗?我基本上是在尝试从绘制的矩形中获取二维矩形坐标(根据系统输出 getbounds2d)。
如果删除 frame.add(new paintRectangles());,您可以看到框架的外观(但无法绘制矩形)
很多问题跳出来了。
首先,您显然不了解 BorderLayout 的工作原理以及如果您尝试将两个组件添加到同一位置它会做什么。
其次,重写绘画不是执行自定义绘画的推荐方法,您应该使用 paintComponent
并且,除非您清楚地了解绘画的工作原理,否则请在您之前调用 super.paintComponent
做任何定制绘画。
第三,您似乎试图在滚动窗格顶部覆盖一个组件,在当前配置中,这将阻止滚动窗格对鼠标事件做出反应。这也意味着如果滚动窗格的内容移动,您在顶部绘制的内容将不会随之滚动
我的“一般”建议是 - 阅读布局管理器,更好地了解它们的工作原理。阅读绘画系统在 Swing 中的工作原理,更好地了解如何使用它以达到您想要的结果。从一个可以自己绘制图像的组件开始,然后您可以向其中添加自定义绘制要求,这将大大减少您当前遇到的问题以及您将遇到的新问题
先看看:
解决您当前问题的 "simple" 方法是将您的 "paint" 面板添加到 JLabel
。默认情况下,JLabel
没有布局管理器,因此您需要提供一个,例如:
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
BufferedImage image = ImageIO.read(new File("C:\Users\Rusty\Desktop\temp\Test_PDF-1.png"));
ImageIcon icon = new ImageIcon(image);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lbl = new JLabel();
lbl.setIcon(icon);
lbl.setLayout(new BorderLayout());
lbl.add(new PaintOverlayPane());
JScrollPane jsp = new JScrollPane(lbl);
frame.add(jsp);
frame.pack();
frame.setVisible(true);
}
});
}
public class PaintOverlayPane extends JPanel {
ArrayList<Shape> shapes = new ArrayList<Shape>();
Point startDrag, endDrag;
public PaintOverlayPane() {
setOpaque(false);
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = {Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK};
int colorIndex = 0;
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if (startDrag != null && endDrag != null) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
System.out.println(r.getBounds2D());
}
}
}
private static Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
这个问题的缺点是您无法控制图像的位置,也无法控制覆盖面板的大小,因此标签的大小可能会发生变化,所有您的绘画将不再与图标匹配。
更好的解决方案是在同一个面板中绘制图像。这样你就可以完全控制图像的位置和形状的位置,并且可以控制它们如何偏移,如果你愿意的话
您可以将 paintRectangles
(顺便说一句应该是 PaintRectangles)添加到 JLayeredPane
。
该解决方案并不理想,但有效。
如果没有别的,值得试驾以了解此选项:
public class DefineArea {
public static void main(String[] args) throws IOException {
displayImage();
}
private static void displayImage() throws IOException {
// URL url = new URL("http://www.digitalphotoartistry.com/rose1.jpg");
// BufferedImage image = ImageIO.read(url);
// ImageIcon icon= new ImageIcon(image);
URL url = DefineArea.class.getResource("image.jpg");
BufferedImage image = ImageIO.read(url);
ImageIcon icon = new ImageIcon(image);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lbl = new JLabel();
lbl.setIcon(icon);
JScrollPane jsp = new JScrollPane(lbl);
frame.add(jsp);
//add glass pane to layered pane
JComponent glass = new paintRectangles();
JLayeredPane lp = frame.getLayeredPane();
int w = icon.getIconWidth(); int h = icon.getIconHeight();
// Size is needed here, as there is no layout in lp
//to make it useful you need to dynamically adjust glass size
glass.setSize(w,h);
lp.add(glass);
frame.pack();
frame.setVisible(true);
}
public static class paintRectangles extends JComponent {
ArrayList<Shape> shapes = new ArrayList<>();
Point startDrag, endDrag;
public paintRectangles() throws IOException {
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = { Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK };
int colorIndex = 0;
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if ((startDrag != null) && (endDrag != null)) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
System.out.println(r.getBounds2D());
}
}
}
private static Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2),
Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
有关详细信息,请参阅 How to Use Layered Panes
我有这段代码,用于在预加载的图像上绘制一个矩形,但它不起作用。
当我将绘图 class 添加到框架时,它会覆盖图像,这意味着我看不到预加载的图像,但它仍然允许我绘制矩形。
此外,我没有将 jframe 放在屏幕中间,而是放在右上角,我必须将其最大化才能看到框架。
代码:
public class defineArea {
public static void main(String[] args) throws IOException {
displayImage();
}
private static void displayImage() throws IOException {
BufferedImage image = ImageIO.read(new File("C:\Users\Rusty\Desktop\temp\Test_PDF-1.png"));
ImageIcon icon = new ImageIcon(image);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lbl = new JLabel();
lbl.setIcon(icon);
JScrollPane jsp = new JScrollPane(lbl);
frame.add(jsp);
frame.add(new paintRectangles());
frame.pack();
frame.setVisible(true);
}
public static class paintRectangles extends JComponent {
ArrayList<Shape> shapes = new ArrayList<Shape>();
Point startDrag, endDrag;
public paintRectangles() throws IOException {
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = { Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK };
int colorIndex = 0;
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if (startDrag != null && endDrag != null) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
System.out.println(r.getBounds2D());
}
}
}
private static Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
有人能帮忙吗?我基本上是在尝试从绘制的矩形中获取二维矩形坐标(根据系统输出 getbounds2d)。
如果删除 frame.add(new paintRectangles());,您可以看到框架的外观(但无法绘制矩形)
很多问题跳出来了。
首先,您显然不了解 BorderLayout 的工作原理以及如果您尝试将两个组件添加到同一位置它会做什么。
其次,重写绘画不是执行自定义绘画的推荐方法,您应该使用 paintComponent
并且,除非您清楚地了解绘画的工作原理,否则请在您之前调用 super.paintComponent
做任何定制绘画。
第三,您似乎试图在滚动窗格顶部覆盖一个组件,在当前配置中,这将阻止滚动窗格对鼠标事件做出反应。这也意味着如果滚动窗格的内容移动,您在顶部绘制的内容将不会随之滚动
我的“一般”建议是 - 阅读布局管理器,更好地了解它们的工作原理。阅读绘画系统在 Swing 中的工作原理,更好地了解如何使用它以达到您想要的结果。从一个可以自己绘制图像的组件开始,然后您可以向其中添加自定义绘制要求,这将大大减少您当前遇到的问题以及您将遇到的新问题
先看看:
解决您当前问题的 "simple" 方法是将您的 "paint" 面板添加到 JLabel
。默认情况下,JLabel
没有布局管理器,因此您需要提供一个,例如:
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
BufferedImage image = ImageIO.read(new File("C:\Users\Rusty\Desktop\temp\Test_PDF-1.png"));
ImageIcon icon = new ImageIcon(image);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lbl = new JLabel();
lbl.setIcon(icon);
lbl.setLayout(new BorderLayout());
lbl.add(new PaintOverlayPane());
JScrollPane jsp = new JScrollPane(lbl);
frame.add(jsp);
frame.pack();
frame.setVisible(true);
}
});
}
public class PaintOverlayPane extends JPanel {
ArrayList<Shape> shapes = new ArrayList<Shape>();
Point startDrag, endDrag;
public PaintOverlayPane() {
setOpaque(false);
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = {Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK};
int colorIndex = 0;
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if (startDrag != null && endDrag != null) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
System.out.println(r.getBounds2D());
}
}
}
private static Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
这个问题的缺点是您无法控制图像的位置,也无法控制覆盖面板的大小,因此标签的大小可能会发生变化,所有您的绘画将不再与图标匹配。
更好的解决方案是在同一个面板中绘制图像。这样你就可以完全控制图像的位置和形状的位置,并且可以控制它们如何偏移,如果你愿意的话
您可以将 paintRectangles
(顺便说一句应该是 PaintRectangles)添加到 JLayeredPane
。
该解决方案并不理想,但有效。
如果没有别的,值得试驾以了解此选项:
public class DefineArea {
public static void main(String[] args) throws IOException {
displayImage();
}
private static void displayImage() throws IOException {
// URL url = new URL("http://www.digitalphotoartistry.com/rose1.jpg");
// BufferedImage image = ImageIO.read(url);
// ImageIcon icon= new ImageIcon(image);
URL url = DefineArea.class.getResource("image.jpg");
BufferedImage image = ImageIO.read(url);
ImageIcon icon = new ImageIcon(image);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lbl = new JLabel();
lbl.setIcon(icon);
JScrollPane jsp = new JScrollPane(lbl);
frame.add(jsp);
//add glass pane to layered pane
JComponent glass = new paintRectangles();
JLayeredPane lp = frame.getLayeredPane();
int w = icon.getIconWidth(); int h = icon.getIconHeight();
// Size is needed here, as there is no layout in lp
//to make it useful you need to dynamically adjust glass size
glass.setSize(w,h);
lp.add(glass);
frame.pack();
frame.setVisible(true);
}
public static class paintRectangles extends JComponent {
ArrayList<Shape> shapes = new ArrayList<>();
Point startDrag, endDrag;
public paintRectangles() throws IOException {
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = { Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK };
int colorIndex = 0;
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if ((startDrag != null) && (endDrag != null)) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
System.out.println(r.getBounds2D());
}
}
}
private static Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2),
Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
有关详细信息,请参阅 How to Use Layered Panes