屏幕上鼠标位置周围区域的缩放框

有什么办法可以创build一个Javadynamic缩放框,其中包括例如20x20pix区域的光标(但即使光标将超出应用程序的框架),将例如在一个小的JPanel中显示?

我正在问一个颜色select器程序的上下文。 需要实现的最后一个function就是Zoom Box。

我确信有很多不同的方法可以实现。

这基本上使用一个单独的组件,作为“缩放框”。 你提供一个你想“放大”的组件。 它增加了一个鼠标监听器,所以它可以监视鼠标移动事件,并进入和退出事件。

这些用于确定何时应该显示“popup”窗口,应该在哪里显示popup窗口以及应该被“绘制”的区域。

这使用“要缩放的组件”的paint方法来绘制一个区域到一个后台缓冲区,然后缩放和绘制到“缩放框”…简单

我还没有玩过缩放因子,所以可能还是会有一些怪癖,但是你应该明白一些基本的想法。

虽然我已经提供了一个图像作为背景,但这应该适用于任何组件

在这里输入图像描述

 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.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JWindow; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class ZoomBoxWindow { public static void main(String[] args) { new ZoomBoxWindow(); } public ZoomBoxWindow() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } TestPane pane = new TestPane(); ZoomPane zoomPane = new ZoomPane(pane); JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(pane); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public static class ZoomPane extends JPanel { protected static final int ZOOM_AREA = 40; private JComponent parent; private JWindow popup; private BufferedImage buffer; private float zoomLevel = 2f; public ZoomPane(JComponent parent) { this.parent = parent; popup = new JWindow(); popup.setLayout(new BorderLayout()); popup.add(this); popup.pack(); MouseAdapter ma = new MouseAdapter() { @Override public void mouseMoved(MouseEvent e) { Point p = e.getPoint(); Point pos = e.getLocationOnScreen(); updateBuffer(p); popup.setLocation(pos.x + 16, pos.y + 16); repaint(); } @Override public void mouseEntered(MouseEvent e) { popup.setVisible(true); } @Override public void mouseExited(MouseEvent e) { popup.setVisible(false); } }; parent.addMouseListener(ma); parent.addMouseMotionListener(ma); } protected void updateBuffer(Point p) { int width = Math.round(ZOOM_AREA); int height = Math.round(ZOOM_AREA); buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = buffer.createGraphics(); AffineTransform at = new AffineTransform(); int xPos = (ZOOM_AREA / 2) - px; int yPos = (ZOOM_AREA / 2) - py; if (xPos > 0) { xPos = 0; } if (yPos > 0) { yPos = 0; } if ((xPos * -1) + ZOOM_AREA > parent.getWidth()) { xPos = (parent.getWidth() - ZOOM_AREA) * -1; } if ((yPos * -1) + ZOOM_AREA > parent.getHeight()) { yPos = (parent.getHeight()- ZOOM_AREA) * -1; } at.translate(xPos, yPos); g2d.setTransform(at); parent.paint(g2d); g2d.dispose(); } @Override public Dimension getPreferredSize() { return new Dimension(Math.round(ZOOM_AREA * zoomLevel), Math.round(ZOOM_AREA * zoomLevel)); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); if (buffer != null) { AffineTransform at = g2d.getTransform(); g2d.setTransform(AffineTransform.getScaleInstance(zoomLevel, zoomLevel)); g2d.drawImage(buffer, 0, 0, this); g2d.setTransform(at); } g2d.setColor(Color.RED); g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1); g2d.dispose(); } } public class TestPane extends JPanel { private BufferedImage img; public TestPane() { try { img = ImageIO.read(new File("/path/to/your/image")); } catch (IOException ex) { ex.printStackTrace(); } } @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); if (img != null) { Graphics2D g2d = (Graphics2D) g.create(); int x = (getWidth() - img.getWidth()) / 2; int y = (getHeight() - img.getHeight()) / 2; g2d.drawImage(img, x, y, this); g2d.dispose(); } } } } 

更新为“屏幕”版本

此版本将允许您在屏幕上的任何位置显示“缩放窗口”。

这有一个小问题,在捕捉屏幕之前需要隐藏缩放窗口,然后重新显示它。

我可能会试图改变这个过程,以便当updateBuffer方法检测到鼠标位置没有改变时,它更新缓冲区并显示缩放窗口。 当鼠标位置改变时,它会再次隐藏窗口…但这就是我;)

在这里输入图像描述

 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.MouseInfo; import java.awt.Point; import java.awt.PointerInfo; import java.awt.Rectangle; import java.awt.Robot; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import javax.swing.Action; import javax.swing.JPanel; import javax.swing.JWindow; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import static zoomboxwindow.ZoomBoxWindow.ZoomPane.ZOOM_AREA; public class GlobalZoomBox { public static void main(String[] args) { new GlobalZoomBox(); } public GlobalZoomBox() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } Zoomer zoomer = new Zoomer(); zoomer.setZoomWinodwVisible(true); } }); } public class Zoomer extends JPanel { protected static final int ZOOM_AREA = 40; private JWindow popup; private BufferedImage buffer; private Robot bot; private float zoomLevel = 2f; private Point lastPoint; private final Timer timer; public Zoomer() { popup = new JWindow(); popup.setLayout(new BorderLayout()); popup.add(this); popup.pack(); try { bot = new Robot(); } catch (AWTException ex) { ex.printStackTrace(); } timer = new Timer(125, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { updateBuffer(); } }); timer.setCoalesce(true); timer.setInitialDelay(0); } public void setZoomWinodwVisible(boolean value) { if (value && !popup.isVisible()) { timer.start(); popup.setVisible(true); } else { timer.stop(); popup.setVisible(false); } } @Override public Dimension getPreferredSize() { return new Dimension(Math.round(ZOOM_AREA * zoomLevel), Math.round(ZOOM_AREA * zoomLevel)); } protected void updateBuffer() { if (bot != null) { PointerInfo info = MouseInfo.getPointerInfo(); Point p = info.getLocation(); if (lastPoint == null || !lastPoint.equals(p)) { int x = px - (ZOOM_AREA / 2); int y = py - (ZOOM_AREA / 2); popup.setLocation(px + 16, py + 16); popup.setVisible(false); buffer = bot.createScreenCapture(new Rectangle(x, y, ZOOM_AREA, ZOOM_AREA)); popup.setVisible(true); lastPoint = p; repaint(); } } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); if (buffer != null) { AffineTransform at = g2d.getTransform(); g2d.setTransform(AffineTransform.getScaleInstance(zoomLevel, zoomLevel)); g2d.drawImage(buffer, 0, 0, this); g2d.setTransform(at); } g2d.setColor(Color.RED); g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1); g2d.dispose(); } } } 

更新为“工具提示”样式popup

第二个例子的主要问题是,您需要隐藏popup窗口才能抓取屏幕截图。 这样做是为了防止popup开始捕获。 这使得每次移动鼠标时popup“闪光灯”。

您可以“绕过”,以确保popup窗口位于捕捉范围的外侧,但是当您增加捕捉区域时,popup窗口将远离光标。

这当然是固定位置显示的一个很好的解决scheme(也就是说,你有一个固定在JFrame而不是浮动框上的面板)

这是一个额外的更新,使用第二个计时器来显示用户停止移动鼠标后的缩放框。

在这里输入图像描述

 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.MouseInfo; import java.awt.Point; import java.awt.PointerInfo; import java.awt.Rectangle; import java.awt.Robot; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import javax.swing.Action; import javax.swing.JPanel; import javax.swing.JWindow; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import static zoomboxwindow.ZoomBoxWindow.ZoomPane.ZOOM_AREA; public class GlobalZoomBox { public static void main(String[] args) { new GlobalZoomBox(); } public GlobalZoomBox() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } Zoomer zoomer = new Zoomer(); zoomer.setZoomWinodwVisible(true); } }); } public class Zoomer extends JPanel { protected static final int ZOOM_AREA = 80; private JWindow popup; private BufferedImage buffer; private Robot bot; private float zoomLevel = 2f; private Point lastPoint; private final Timer timer; private final Timer popupTimer; public Zoomer() { popup = new JWindow(); popup.setLayout(new BorderLayout()); popup.add(this); popup.pack(); try { bot = new Robot(); } catch (AWTException ex) { ex.printStackTrace(); } timer = new Timer(125, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { updateBuffer(); } }); timer.setCoalesce(true); timer.setInitialDelay(0); popupTimer = new Timer(250, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (lastPoint != null) { System.out.println("lastPoint = " + lastPoint); popup.setVisible(false); Point p = lastPoint; int x = px - (ZOOM_AREA / 2); int y = py - (ZOOM_AREA / 2); popup.setLocation(px + 16, py + 16); buffer = bot.createScreenCapture(new Rectangle(x, y, ZOOM_AREA, ZOOM_AREA)); repaint(); popup.setVisible(true); } } }); popupTimer.setRepeats(false); } public void setZoomWinodwVisible(boolean value) { if (value && !popup.isVisible()) { timer.start(); popup.setVisible(true); } else { timer.stop(); popup.setVisible(false); } } @Override public Dimension getPreferredSize() { return new Dimension(Math.round(ZOOM_AREA * zoomLevel), Math.round(ZOOM_AREA * zoomLevel)); } protected void updateBuffer() { if (bot != null) { PointerInfo info = MouseInfo.getPointerInfo(); Point p = info.getLocation(); if (lastPoint == null || !lastPoint.equals(p)) { lastPoint = p; popupTimer.stop(); popup.setVisible(false); } else { if (!popup.isVisible()) { popupTimer.start(); } } } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); if (buffer != null) { AffineTransform at = g2d.getTransform(); g2d.setTransform(AffineTransform.getScaleInstance(zoomLevel, zoomLevel)); g2d.drawImage(buffer, 0, 0, this); g2d.setTransform(at); } g2d.setColor(Color.RED); g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1); g2d.dispose(); } } } 

放大鼠标

 import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import javax.swing.*; class ZoomOnMouse { public static void main(String[] args) throws AWTException { final Robot robot = new Robot(); Runnable r = new Runnable() { @Override public void run() { final int size = 256; final BufferedImage bi = new BufferedImage( size, size, BufferedImage.TYPE_INT_RGB); final JLabel gui = new JLabel(new ImageIcon(bi)); ActionListener zoomListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { PointerInfo pi = MouseInfo.getPointerInfo(); Point p = pi.getLocation(); BufferedImage temp = robot.createScreenCapture( new Rectangle(px-(size/4), py-(size/4), (size/2), (size/2))); Graphics g = bi.getGraphics(); g.drawImage(temp, 0, 0, size, size, null); g.dispose(); gui.repaint(); } }; Timer t = new Timer(40, zoomListener); t.start(); JOptionPane.showMessageDialog(null, gui); t.stop(); } }; // Swing GUIs should be created and updated on the EDT // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html SwingUtilities.invokeLater(r); } }