围绕在屏幕上的鼠标位置区域缩放框 [英] Zoom box for area around mouse location on screen

查看:331
本文介绍了围绕在屏幕上的鼠标位置区域缩放框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法在Java中创建一个动态缩放框将包括电子。 G。 20x20pix区域光标周围(但即使当光标将超越应用程序的帧),并且将显示在例如一个小的JPanel

我要问一个颜色选择方案的背景。最后一个功能需要实施就是这样缩放框。


解决方案

我敢肯定有一些,这可以实现不同的方式。

此基本上使用单独的部件,其作为所述缩放框。您提供它想要的放大的组成部分。它增加了一个鼠标侦听器,以便它可以监视鼠标移动事件,进入和退出事件。

这些用于确定当弹出的窗口应示出,其中,应显示的弹出窗口和应的绘制的区域。

此使用组件被放大油漆方法的区域画到它到后台缓冲区,然后缩放和画的缩放框......简单的

我没有与缩放因子起到左右,所以有可能还是会有一些怪癖,但你应该得到的基本思想......

虽然我已经presented一个图像作为背景,这应该任何部件上工作

 进口java.awt.BorderLayout中;
进口java.awt.Color中;
进口java.awt.Dimension中;
进口java.awt.EventQueue中;
进口java.awt.Graphics;
进口java.awt.Graphics2D中;
进口java.awt.Point中;
进口java.awt.event.MouseAdapter;
进口java.awt.event.MouseEvent中;
进口java.awt.geom.AffineTransform中;
进口java.awt.image.BufferedImage中;
进口的java.io.File;
进口java.io.IOException异常;
进口javax.imageio.ImageIO中;
进口javax.swing.JComponent中;
进口javax.swing.JFrame中;
进口javax.swing.JPanel中;
进口javax.swing.JWindow中;
进口javax.swing.UIManager中;
进口javax.swing.UnsupportedLookAndFeelException;公共类ZoomBoxWindow {  公共静态无效的主要(字串[] args){
    新ZoomBoxWindow();
  }  公共ZoomBoxWindow(){
    EventQueue.invokeLater(新的Runnable(){
      @覆盖
      公共无效的run(){
        尝试{
          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
          ex.printStackTrace();
        }        TestPane窗格=新TestPane();
        ZoomPane zoomPane =新ZoomPane(面板);        JFrame的帧=新的JFrame(测试);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(面板);
        frame.pack();
        frame.setLocationRelativeTo(NULL);
        frame.setVisible(真);
      }
    });
  }  公共静态类ZoomPane继承JPanel {    受保护的静态最终诠释ZOOM_AREA = 40;    私人JComponent的父母;
    私人的JWindow弹出;    私人的BufferedImage缓冲;    私人浮法个zoomLevel = 2F;    公共ZoomPane(JComponent的父){
      this.parent =父母;
      弹出=新的JWindow();
      popup.setLayout(新的BorderLayout());
      popup.add(本);
      popup.pack();
      MouseAdapter MA =新MouseAdapter(){
        @覆盖
        公共无效的mouseMoved(的MouseEvent E){
          点P = e.getPoint();
          点POS = e.getLocationOnScreen();
          updateBuffer(P);
          popup.setLocation(pos.x + 16,pos.y + 16);
          重绘();
        }        @覆盖
        公共无效的mouseEntered(的MouseEvent E){
          popup.setVisible(真);
        }        @覆盖
        公共无效的mouseExited(的MouseEvent E){
          popup.setVisible(假);
        }      };      parent.addMouseListener(MA);
      parent.addMouseMotionListener(MA);
    }    保护无效updateBuffer(点p){
      INT宽度= Math.round(ZOOM_AREA);
      INT高度= Math.round(ZOOM_AREA);
      缓冲液=新的BufferedImage(宽度,高度,BufferedImage.TYPE_INT_ARGB);
      Graphics2D的G2D = buffer.createGraphics();
      在的AffineTransform =新AffineTransform();      INT XPOS =(ZOOM_AREA / 2) - p.x;
      INT yPos =(ZOOM_AREA / 2) - p.y;      如果(XPOS大于0){
        XPOS = 0;
      }
      如果(yPos大于0){
        yPos = 0;
      }      如果((XPOS * 1)+ ZOOM_AREA> parent.getWidth()){
        XPOS =(parent.getWidth() - ZOOM_AREA)* -1;
      }
      如果((yPos * 1)+ ZOOM_AREA> parent.getHeight()){
        yPos =(parent.getHeight() - ZOOM_AREA)* -1;
      }      at.translate(XPOS,yPos);
      g2d.setTransform(AT);
      parent.paint(G2D);
      g2d.dispose();
    }    @覆盖
    公共尺寸的get preferredSize(){
      返回新的Dimension(Math.round(ZOOM_AREA *个zoomLevel),Math.round(ZOOM_AREA *个zoomLevel));
    }    @覆盖
    保护无效paintComponent(图形G){
      super.paintComponent方法(G);
      Graphics2D的G2D =(Graphics2D的)g.create();
      如果(缓冲!= NULL){
        的AffineTransform在= g2d.getTransform();
        g2d.setTransform(AffineTransform.getScaleInstance(个zoomLevel,个zoomLevel));
        g2d.drawImage(缓冲液,0,0,这一点);
        g2d.setTransform(AT);
      }
      g2d.setColor(Color.RED);
      g2d.drawRect(0,0,的getWidth() - 1,的getHeight() - 1);
      g2d.dispose();
    }  }  公共类TestPane继承JPanel {    私人的BufferedImage IMG;    公共TestPane(){
      尝试{
        IMG = ImageIO.read(新文件(/路径/到/你/图像));
      }赶上(IOException异常前){
        ex.printStackTrace();
      }
    }    @覆盖
    公共尺寸的get preferredSize(){
      返回IMG == NULL?新尺寸(200,200):新的Dimension(img.getWidth(),img.getHeight());
    }    @覆盖
    保护无效paintComponent(图形G){
      super.paintComponent方法(G);
      如果(IMG!= NULL){
        Graphics2D的G2D =(Graphics2D的)g.create();
        INT X =(的getWidth() - img.getWidth())/ 2;
        INT Y =(的getHeight() - img.getHeight())/ 2;
        g2d.drawImage(IMG,X,Y,这一点);
        g2d.dispose();
      }
    }  }}

更新,其中屏幕的版本

这个版本将允许您显示缩放窗口屏幕上的任何地方。

这在您需要隐藏缩放窗口你捕获屏幕前的事实,一个小问题,然后重新表现出来。

我可能会改变的过程,这样,当 updateBuffer 方法检测鼠标的位置没有改变,它更新了缓冲区,并显示缩放窗口。当鼠标位置的变化,它会再次隐藏窗口...那是我;)

 进口java.awt.AWTException;
进口java.awt.BorderLayout中;
进口java.awt.Color中;
进口java.awt.Dimension中;
进口java.awt.EventQueue中;
进口java.awt.Graphics;
进口java.awt.Graphics2D中;
进口java.awt.MouseInfo;
进口java.awt.Point中;
进口java.awt.PointerInfo;
进口java.awt.Rectangle中;
进口java.awt.Robot中;
进口java.awt.event.ActionEvent中;
进口java.awt.event.ActionListener;
进口java.awt.geom.AffineTransform中;
进口java.awt.image.BufferedImage中;
进口javax.swing.Action中;
进口javax.swing.JPanel中;
进口javax.swing.JWindow中;
进口javax.swing.Timer中;
进口javax.swing.UIManager中;
进口javax.swing.UnsupportedLookAndFeelException;
引入静态zoomboxwindow.ZoomBoxWindow.ZoomPane.ZOOM_AREA;公共类GlobalZoomBox {  公共静态无效的主要(字串[] args){
    新GlobalZoomBox();
  }  公共GlobalZoomBox(){
    EventQueue.invokeLater(新的Runnable(){
      @覆盖
      公共无效的run(){
        尝试{
          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
          ex.printStackTrace();
        }
        伸缩镜头伸缩镜头=新的伸缩镜头();
        zoomer.setZoomWinodwVisible(真);
      }
    });
  }  公共类祖玛继承JPanel {    受保护的静态最终诠释ZOOM_AREA = 40;    私人的JWindow弹出;    私人的BufferedImage缓冲;
    私人机器人机器人;    私人浮法个zoomLevel = 2F;
    私人点lastPoint;
    私人最终计时器定时器;    公共缩放器(){
      弹出=新的JWindow();
      popup.setLayout(新的BorderLayout());
      popup.add(本);
      popup.pack();
      尝试{
        BOT =新机器人();
      }赶上(前的AWTException){
        ex.printStackTrace();
      }
      定时器=新定时器(125,新的ActionListener(){
        @覆盖
        公共无效的actionPerformed(ActionEvent的五){
          updateBuffer();
        }
      });
      timer.setCoalesce(真);
      timer.setInitialDelay(0);
    }    公共无效setZoomWinodwVisible(布尔值){      如果(价值和放大器;&安培;!popup.isVisible()){        timer.start();
        popup.setVisible(真);      }其他{        timer.stop();
        popup.setVisible(假);      }    }    @覆盖
    公共尺寸的get preferredSize(){
      返回新的Dimension(Math.round(ZOOM_AREA *个zoomLevel),Math.round(ZOOM_AREA *个zoomLevel));
    }    保护无效updateBuffer(){
      如果(BOT!= NULL){
        PointerInfo信息= MouseInfo.getPointerInfo();
        点P = info.getLocation();
        如果(lastPoint ==空||!lastPoint.equals(P)){
          INT X = p.x - (ZOOM_AREA / 2);
          INT Y = p.y - (ZOOM_AREA / 2);
          popup.setLocation(p.x + 16,p.y + 16);
          popup.setVisible(假);
          缓冲= bot.createScreenCapture(新的Rectangle(X,Y,ZOOM_AREA,ZOOM_AREA));
          popup.setVisible(真);
          lastPoint = P;
          重绘();
        }
      }
    }    @覆盖
    保护无效paintComponent(图形G){
      super.paintComponent方法(G);
      Graphics2D的G2D =(Graphics2D的)g.create();
      如果(缓冲!= NULL){
        的AffineTransform在= g2d.getTransform();
        g2d.setTransform(AffineTransform.getScaleInstance(个zoomLevel,个zoomLevel));
        g2d.drawImage(缓冲液,0,0,这一点);
        g2d.setTransform(AT);
      }
      g2d.setColor(Color.RED);
      g2d.drawRect(0,0,的getWidth() - 1,的getHeight() - 1);
      g2d.dispose();
    }  }}

更新了工具提示的风格弹出

在第二个例子中存在的主要问题是,你需要隐藏弹出为了抢一个屏幕拍摄的事实。这样做是为了prevent从开始捕获以及弹出。这使得在弹出的闪每次移动鼠标时。

您可能会解决这个确保弹出获得定位出方的捕捉范围内,但随着你增加捕捉区域,在弹出将进一步远离移动光标。

这当然会,是固定的位置显示(即你有固定在面板的JFrame 而不是一个浮动框)

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

 进口java.awt.AWTException;
进口java.awt.BorderLayout中;
进口java.awt.Color中;
进口java.awt.Dimension中;
进口java.awt.EventQueue中;
进口java.awt.Graphics;
进口java.awt.Graphics2D中;
进口java.awt.MouseInfo;
进口java.awt.Point中;
进口java.awt.PointerInfo;
进口java.awt.Rectangle中;
进口java.awt.Robot中;
进口java.awt.event.ActionEvent中;
进口java.awt.event.ActionListener;
进口java.awt.geom.AffineTransform中;
进口java.awt.image.BufferedImage中;
进口javax.swing.Action中;
进口javax.swing.JPanel中;
进口javax.swing.JWindow中;
进口javax.swing.Timer中;
进口javax.swing.UIManager中;
进口javax.swing.UnsupportedLookAndFeelException;
引入静态zoomboxwindow.ZoomBoxWindow.ZoomPane.ZOOM_AREA;公共类GlobalZoomBox {  公共静态无效的主要(字串[] args){
    新GlobalZoomBox();
  }  公共GlobalZoomBox(){
    EventQueue.invokeLater(新的Runnable(){
      @覆盖
      公共无效的run(){
        尝试{
          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
          ex.printStackTrace();
        }
        伸缩镜头伸缩镜头=新的伸缩镜头();
        zoomer.setZoomWinodwVisible(真);
      }
    });
  }  公共类祖玛继承JPanel {    受保护的静态最终诠释ZOOM_AREA = 80;    私人的JWindow弹出;    私人的BufferedImage缓冲;
    私人机器人机器人;    私人浮法个zoomLevel = 2F;
    私人点lastPoint;
    私人最终计时器定时器;
    私人最终计时器popupTimer;    公共缩放器(){
      弹出=新的JWindow();
      popup.setLayout(新的BorderLayout());
      popup.add(本);
      popup.pack();
      尝试{
        BOT =新机器人();
      }赶上(前的AWTException){
        ex.printStackTrace();
      }
      定时器=新定时器(125,新的ActionListener(){
        @覆盖
        公共无效的actionPerformed(ActionEvent的五){
          updateBuffer();
        }
      });
      timer.setCoalesce(真);
      timer.setInitialDelay(0);      popupTimer =新的Timer(250,新的ActionListener(){
        @覆盖
        公共无效的actionPerformed(ActionEvent的五){
          如果(lastPoint!= NULL){
            的System.out.println(lastPoint =+ lastPoint);
            popup.setVisible(假);
            点P = lastPoint;
            INT X = p.x - (ZOOM_AREA / 2);
            INT Y = p.y - (ZOOM_AREA / 2);
            popup.setLocation(p.x + 16,p.y + 16);
            缓冲= bot.createScreenCapture(新的Rectangle(X,Y,ZOOM_AREA,ZOOM_AREA));
            重绘();
            popup.setVisible(真);
          }
        }
      });
      popupTimer.setRepeats(假);
    }    公共无效setZoomWinodwVisible(布尔值){      如果(价值和放大器;&安培;!popup.isVisible()){        timer.start();
        popup.setVisible(真);      }其他{        timer.stop();
        popup.setVisible(假);      }    }    @覆盖
    公共尺寸的get preferredSize(){
      返回新的Dimension(Math.round(ZOOM_AREA *个zoomLevel),Math.round(ZOOM_AREA *个zoomLevel));
    }    保护无效updateBuffer(){
      如果(BOT!= NULL){
        PointerInfo信息= MouseInfo.getPointerInfo();
        点P = info.getLocation();
        如果(lastPoint ==空||!lastPoint.equals(P)){
          lastPoint = P;
          popupTimer.stop();
          popup.setVisible(假);
        }其他{
          如果(!popup.isVisible()){
            popupTimer.start();
          }
        }
      }
    }    @覆盖
    保护无效paintComponent(图形G){
      super.paintComponent方法(G);
      Graphics2D的G2D =(Graphics2D的)g.create();
      如果(缓冲!= NULL){
        的AffineTransform在= g2d.getTransform();
        g2d.setTransform(AffineTransform.getScaleInstance(个zoomLevel,个zoomLevel));
        g2d.drawImage(缓冲液,0,0,这一点);
        g2d.setTransform(AT);
      }
      g2d.setColor(Color.RED);
      g2d.drawRect(0,0,的getWidth() - 1,的getHeight() - 1);
      g2d.dispose();
    }  }}

Is there any way to create a dynamic Zoom Box in Java which will include e. g. 20x20pix area around the cursor (but even when cursor will move beyond the Frame of app) and which will be shown for example in a small JPanel?

I'm asking in context of a Color Chooser program. The last functionality need to be implemented is just that Zoom Box.

解决方案

I'm sure there are a number of different ways that this could be achieved.

This basically uses a separate component, which acts as the "zoom box". You supply it a component that you want to "zoom" on. It adds a mouse listener so it can monitor mouse motion events and enter and exit events.

These are used to determine when the "popup" window should be shown, where the popup window should be shown and the area that should be "painted".

This uses the "component to be zoomed" paint method to paint a region to of it to a backing buffer, which is then scaled and painted to the "zoom box"...simple

I've not played around with the zoom factor, so there may still be some quirks, but you should get the basic idea...

While I've presented a image to act as the background, this should work on any component

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) - p.x;
      int yPos = (ZOOM_AREA / 2) - p.y;

      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();
      }
    }

  }

}

Updated with "screen" version

This version will allow you to display a "zoom window" any where on the screen.

This has a minor issue in the fact that you need to hide the zoom window before you capture the screen, then re-show it.

I might be tempted to change the process so that when the updateBuffer method detected that the mouse position hadn't changed, it updated the buffer and showed the zoom window. When the mouse position changes, it would hide the window again...but that's me ;)

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 = p.x - (ZOOM_AREA / 2);
          int y = p.y - (ZOOM_AREA / 2);
          popup.setLocation(p.x + 16, p.y + 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();
    }

  }

}

Updated with "tooltip" style popup

The main problems with the second example is the fact that you need to hide the popup in order to grab a screen shoot. This is done to prevent the popup from begin captured as well. This makes the popup "flash" every time the mouse is moved.

You "could" get around this ensuring the popup is positioned out side the range of the capture, but as you increase the capture area, the popup will move further away from the cursor.

This would, of course, be a great solution for fixed position display (ie, you had a panel fixed on a JFrame instead of a floating box)

This is an additional update that uses a second timer to display the zoom box after the user has stopped moving the mouse.

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 = p.x - (ZOOM_AREA / 2);
            int y = p.y - (ZOOM_AREA / 2);
            popup.setLocation(p.x + 16, p.y + 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();
    }

  }

}

这篇关于围绕在屏幕上的鼠标位置区域缩放框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆