我借用下面的课程为项目制作选择区域工具。但是当我尝试在内容未在左上方对齐时进行选择时,它会出现问题,它会使我的鼠标坐标与ScrollPane相关,但会覆盖图像 - 请参阅此SS以便更好地理解:
SSCCE :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
/** Getting a Rectangle of interest on the screen.
Requires the MotivatedEndUser API - sold separately. */
public class ScreenCaptureRectangle {
Rectangle captureRect;
ScreenCaptureRectangle(final BufferedImage screen) {
final BufferedImage screenCopy = new BufferedImage(screen.getWidth(), screen.getHeight(), screen.getType());
final JLabel screenLabel = new JLabel(new ImageIcon(screenCopy));
JScrollPane screenScroll = new JScrollPane(screenLabel);
screenScroll.setPreferredSize(new Dimension((int)(screen.getWidth()*2), (int)(screen.getHeight()*2)));
JPanel panel = new JPanel(new BorderLayout());
panel.add(screenScroll, BorderLayout.CENTER);
final JLabel selectionLabel = new JLabel("Drag a rectangle in the screen shot!");
panel.add(selectionLabel, BorderLayout.SOUTH);
repaint(screen, screenCopy);
screenLabel.repaint();
screenLabel.addMouseMotionListener(new MouseMotionAdapter() {
Point start = new Point();
@Override
public void mouseMoved(MouseEvent me) {
start = me.getPoint();
repaint(screen, screenCopy);
selectionLabel.setText("Start Point: " + start);
screenLabel.repaint();
}
@Override
public void mouseDragged(MouseEvent me) {
Point end = me.getPoint();
captureRect = new Rectangle(start, new Dimension(end.x-start.x, end.y-start.y));
repaint(screen, screenCopy);
screenLabel.repaint();
selectionLabel.setText("Rectangle: " + captureRect);
}
});
JOptionPane.showMessageDialog(null, panel);
System.out.println("Rectangle of interest: " + captureRect);
}
public void repaint(BufferedImage orig, BufferedImage copy) {
Graphics2D g = copy.createGraphics();
g.drawImage(orig,0,0, null);
if (captureRect!=null) {
g.setColor(Color.RED);
g.draw(captureRect);
g.setColor(new Color(255,255,255,150));
g.fill(captureRect);
}
g.dispose();
}
public static void main(String[] args) throws Exception {
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
final BufferedImage screen = robot.createScreenCapture(new Rectangle(300,0,300,300));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ScreenCaptureRectangle(screen);
}
});
}
}
答案 0 :(得分:3)
我认为您有问题,因为您试图将图像置于面板中心。
最简单的解决方案是确保从面板的顶部/左侧绘制图像:
final JLabel screenLabel = new JLabel(new ImageIcon(screenCopy));
screenLabel.setHorizontalAlignment(JLabel.LEFT);
screenLabel.setVerticalAlignment(JLabel.TOP);
答案 1 :(得分:2)
基本上,正在发生的事情是,你是直接绘制到图像表面(由JLabel持有),所以当你在屏幕上以2x2x36x36拖动时,然后在矩形上绘制RELATIVE到图像本身
因此即使图像在JLabel
的上下文中居中,您仍然会渲染到图像的本地上下文(0x0),因此两者之间会断开连接。
根据您想要实现的目标,您可以改变绘画的工作方式并采取更直接的控制,例如......
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawimgExample {
public static void main(String[] args) {
try {
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
final BufferedImage screen = robot.createScreenCapture(new Rectangle(300, 0, 300, 300));
new DrawimgExample(screen);
} catch (AWTException exp) {
exp.printStackTrace();
}
}
public DrawimgExample(final BufferedImage screen) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new DrawingPane(screen));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawingPane extends JPanel {
private BufferedImage img;
private Rectangle drawRect;
public DrawingPane(BufferedImage img) {
this.img = img;
MouseAdapter mouseHandler = new MouseAdapter() {
private Point startPoint;
@Override
public void mousePressed(MouseEvent e) {
startPoint = e.getPoint();
}
@Override
public void mouseDragged(MouseEvent e) {
Point endPoint = e.getPoint();
int startX = Math.min(startPoint.x, endPoint.x);
int startY = Math.min(startPoint.y, endPoint.y);
int width = Math.max(startPoint.x, endPoint.x) - startX;
int height = Math.max(startPoint.y, endPoint.y) - startY;
drawRect = new Rectangle(
startX,
startY,
width,
height
);
repaint();
}
};
addMouseListener(mouseHandler);
addMouseMotionListener(mouseHandler);
}
@Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
if (drawRect != null) {
g2d.setColor(Color.RED);
g2d.draw(drawRect);
g2d.setColor(new Color(255, 255, 255, 150));
g2d.fill(drawRect);
}
g2d.dispose();
}
}
}
尽管如此,在可能的情况下,您应该避免直接绘制图像,因为JLabel
已经做得很好,但有时候,如果它不能满足您的需求,您可能需要更直接地控制