在 JPanel 中在图像上绘制形状
我需要在 JPanel 的 JLabel 中显示的图像上绘制形状(圆形或自由线).
I need to draw shapes (circle or free line) over an image that is shown in a JLabel of a JPanel.
我的代码基于问题 如何在拖动光标时绘制没有间隙的细线? 和 单击 2 次鼠标画一个圆.
I based my code on the questions How to draw thin line with no gap while dragging the cursor? and Draw a circle using 2 mouse clicks.
代码如下.问题是,当我开始绘制图像时,图像会消失,只有在我停止后才会重新出现.如果我评论 super.paintComponent(g); 行,那不会发生,但是当我画圆时,它会保持先前位置的路径.
The code is bellow. The problem is that when I start drawing the image disappears and only reappears after I stop. If I comment the line super.paintComponent(g); that doesnt happen but when I draw the circle it maintains a path of the previous positions.
public static void main(String args[]) {
try {
URL url = new URL("http://www.senhoritatours.com/wp-content/uploads/2014/05/Porto-.jpg");
backgroundImage = ImageIO.read(url);
} catch (Exception e) {
e.printStackTrace();
}
loadAnnotation();
loadBackground();
JFrame f;
f = new JFrame();
f.setLayout(new BorderLayout());
f.add(mp);
f.pack();
f.setVisible(true);
}
/* 第 0 层:* 加载背景图片 */
/* Layer 0: * Load background picture */
public static void loadBackground() {
JLabel lbImg = new JLabel();
lbImg.setBounds(0, 0, new ImageIcon(backgroundImage).getIconWidth(), new ImageIcon(backgroundImage).getIconHeight());
lbImg.setIcon(new ImageIcon(backgroundImage));
mp = new JPanel(new BorderLayout());
btnCircle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if(btnCircle.isEnabled())
{
btnCircle.setEnabled(false);
btnLine.setEnabled(true);
}
}
});
btnLine.setEnabled(true);
btnCircle.setEnabled(false);
btnLine.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if(btnLine.isEnabled())
{
btnLine.setEnabled(false);
btnCircle.setEnabled(true);
}
}
});
mp.add(btnCircle);
mp.add(btnLine);
mp.add(lbImg);
mp.add(p);
}
/* 第 1 层:* 注释:在背景图片上绘制任何东西!*/
/* Layer 1: * Annotation: Draw on top of background picture anything! */
public static void loadAnnotation() {
p = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.RED);
if (_bufImage == null) {
int w = this.getWidth();
int h = this.getHeight();
_bufImage = new BufferedImage(1024,600, BufferedImage.TRANSLUCENT);
Graphics2D gc = _bufImage.createGraphics();
}
g2.drawImage(_bufImage, null, 0, 0);
if (_state == State.DRAGGING) {
if (!btnLine.isEnabled())
{
g.drawLine(_start.x, _start.y, _end.x , _end.y);
}
}
if (!btnCircle.isEnabled())
{
g.drawOval(x, y, width, height);
}
}
public Dimension getPreferredSize() {
return new Dimension(1024, 600);
}
};
p.setLayout(new OverlayLayout(p));
p.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent me) {
}
@Override
public void mousePressed(MouseEvent me) {
last = me.getPoint();
dragging = isInsideEllipse(last);
if (!dragging) {
x = last.x;
y = last.y;
width = 0;
height = 0;
}
p.repaint();
}
@Override
public void mouseReleased(MouseEvent me) {
//_state = State.IDLE;
last = null;
dragging = false;
_state = State.IDLE;
p.repaint();
}
@Override
public void mouseEntered(MouseEvent me) {
}
@Override
public void mouseExited(MouseEvent me) {
}
});
p.addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent me) {
if(!btnLine.isEnabled())
{
_state = State.DRAGGING;
_end = me.getPoint();
if (_state == State.DRAGGING) {
Graphics2D g2 = _bufImage.createGraphics();
g2.setColor(Color.red);
g2.setStroke(new BasicStroke(2));
g2.drawLine(_start.x, _start.y, _end.x, _end.y);
p.repaint();
//
}
_start = _end;
}
else
{
int dx = me.getX() - last.x;
int dy = me.getY() - last.y;
if (dragging) {
x += dx;
y += dy;
} else {
width += dx;
height += dy;
}
last = me.getPoint();
p.repaint();
}
}
@Override
public void mouseMoved(MouseEvent me) {
//System.out.println("move");
_start = me.getPoint();
}
});
}
推荐答案
要么
- 通过
Graphics#drawImage(...)
以与您进行绘图相同的 paintComponent 方法显示图像.您可以在super.paintComponent(g)
调用之后立即调用它. - 或者在显示图像的 JLabel 的
paintComponent(...)
方法中进行绘图.
- Display the image in the same paintComponent method that you're doing your drawing in, via
Graphics#drawImage(...)
. You would call this immediately after thesuper.paintComponent(g)
call. - Or do your drawing in the
paintComponent(...)
method of your JLabel, the one displaying the image.
<小时>
例如:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class DrawingPanel extends JPanel {
private final static String PATH = "https://upload.wikimedia.org/wikipedia/commons/"
+ "thumb/7/7c/Thomas_Hicks_-_Leopold_Grozelier_-_Presidential_Candidate_"
+ "Abraham_Lincoln_1860_-_cropped_to_lithographic_plate.jpg/"
+ "463px-Thomas_Hicks_-_Leopold_Grozelier_-_Presidential_Candidate_"
+ "Abraham_Lincoln_1860_-_cropped_to_lithographic_plate.jpg";
private static final Color DRAWING_COLOR = new Color(255, 100, 200);
private static final Color FINAL_DRAWING_COLOR = Color.red;
private BufferedImage backgroundImg;
private Point startPt = null;
private Point endPt = null;
private Point currentPt = null;
private int prefW;
private int prefH;
public DrawingPanel() throws IOException {
URL imgUrl = new URL(PATH);
BufferedImage bImg = ImageIO.read(imgUrl);
prefW = bImg.getWidth();
prefH = bImg.getHeight();
backgroundImg = new BufferedImage(prefW, prefH,
BufferedImage.TYPE_INT_ARGB);
Graphics g = backgroundImg.getGraphics();
g.drawImage(bImg, 0, 0, this);
g.dispose();
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseMotionListener(myMouseAdapter);
addMouseListener(myMouseAdapter);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, this);
}
if (startPt != null && currentPt != null) {
g.setColor(DRAWING_COLOR);
int x = Math.min(startPt.x, currentPt.x);
int y = Math.min(startPt.y, currentPt.y);
int width = Math.abs(startPt.x - currentPt.x);
int height = Math.abs(startPt.y - currentPt.y);
g.drawRect(x, y, width, height);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(prefW, prefH);
}
public void drawToBackground() {
Graphics g = backgroundImg.getGraphics();
g.setColor(FINAL_DRAWING_COLOR);
int x = Math.min(startPt.x, endPt.x);
int y = Math.min(startPt.y, endPt.y);
int width = Math.abs(startPt.x - endPt.x);
int height = Math.abs(startPt.y - endPt.y);
g.drawRect(x, y, width, height);
g.dispose();
startPt = null;
repaint();
}
private class MyMouseAdapter extends MouseAdapter {
@Override
public void mouseDragged(MouseEvent mEvt) {
currentPt = mEvt.getPoint();
DrawingPanel.this.repaint();
}
@Override
public void mouseReleased(MouseEvent mEvt) {
endPt = mEvt.getPoint();
currentPt = null;
drawToBackground();
}
@Override
public void mousePressed(MouseEvent mEvt) {
startPt = mEvt.getPoint();
}
}
private static void createAndShowGui() {
DrawingPanel mainPanel = null;
try {
mainPanel = new DrawingPanel();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("Drawing Panel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
相关文章