当取消选中JCheckBox时,使ZoomBox周围的光标消失

时间:2017-06-26 09:12:03

标签: java swing zoom jcheckbox

我使用Zoom box for area around mouse location on screen的第一个答案在鼠标位置周围创建一个缩放框窗口,可以在鼠标移动时缩放图像。

现在,我想知道在选中 JCheckBox 时如何激活缩放框视图,如果未选中则停用它。

我修改了由@ MadProgrammer 编写的类 ZoomBoxWindow ZoomPane ,添加了用于激活和停用ZoomBoxView的代码行,但是这个似乎不起作用。你能告诉我我做错了吗?

以下是代码:

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;
import javax.swing.JCheckBox;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent; 
import java.awt.event.KeyEvent;

public class ZoomPane extends JPanel {

protected static final int ZOOM_AREA = 40;

private JComponent parent;
private JWindow popup;
private Boolean zoomBoxActivated = false;

private BufferedImage buffer;

private float zoomLevel = 2f;

public ZoomPane(JComponent parent, Boolean zba) {
  this.parent = parent;
  this.zoomBoxActivated=zba;
  popup = new JWindow();
  popup.setLayout(new BorderLayout());
  popup.add(this);
  popup.pack();
  popup.setAlwaysOnTop(true);
  MouseAdapter ma = new MouseAdapter() {
    @Override
    public void mouseMoved(MouseEvent e) {
      Point p = e.getPoint();
      Point pos = e.getLocationOnScreen();
      updateBuffer(p);
      popup.setLocation(pos.x - 20, pos.y + 20);
      repaint();
    }

    @Override
    public void mouseEntered(MouseEvent e) {

  if(zoomBoxActivated){
     popup.setVisible(true);
  }
  else {
     popup.setVisible(false);
      }
    }

    @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("satellite-image-of-spain.jpg"));
  } 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();
  }
}
}

public class ZoomBoxWindow {

 ZoomPane zoomPane;

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 = new ZoomPane(pane, false);

JPanel buttonPanel = new JPanel(new BorderLayout());

JCheckBox zoomBoxChkBox = new JCheckBox("Zoom Box");
zoomBoxChkBox.setMnemonic(KeyEvent.VK_Z);
zoomBoxChkBox.setSelected(false);
zoomBoxChkBox.addItemListener(new ItemListener() {

@Override
public void itemStateChanged(ItemEvent e) {
    // TODO Auto-generated method stub
    if ( e.getStateChange() == ItemEvent.SELECTED) {
         zoomPane = new ZoomPane(pane,true);
    }
    else {

         zoomPane = new ZoomPane(pane,false);
    }
}

});
buttonPanel.add(zoomBoxChkBox);

    JFrame frame = new JFrame("Testing");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(pane,BorderLayout.CENTER);
frame.add(buttonPanel, BorderLayout.PAGE_START);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
});
}
}

感谢您的回答。

2 个答案:

答案 0 :(得分:1)

将新的ZoomPane分配到zoomPane字段对实际显示的ZoomPane无效。

您想要的是告诉现有ZoomPane切换其缩放政策。

您可以通过将以下方法添加到ZoomPane

来实现
void switchZoomBoxActivated() {

    zoomBoxActivated = !zoomBoxActivated;
}

然后在ItemListener中,只需按照这样的方式调用它:

@Override
public void itemStateChanged(final ItemEvent e) {

   zoomPane.switchZoomBoxActivated();
}

答案 1 :(得分:1)

所以,

zoomBoxChkBox.addItemListener(new ItemListener() {
    @Override
    public void itemStateChanged(ItemEvent e) {
        // TODO Auto-generated method stub
        if (e.getStateChange() == ItemEvent.SELECTED) {
            zoomPane = new ZoomPane(pane, true);
        } else {

            zoomPane = new ZoomPane(pane, false);
        }
    }
});

不是真的在做任何事情,你只是创建一个ZoomPane的新实例。除了向MouseListener组件添加一堆parent之外,这可能会导致问题无法结束。

相反,我要向ZoomPane

添加新方法
public class ZoomPane extends JPanel {

    private boolean isAutoDisplayEnabled = false;
    //...


    public void setShowZoomPopup(boolean show) {
        popup.setVisible(show);
        isAutoDisplayEnabled = show;
    }

现在允许您从外部控制弹出窗口的可见性状态。

现在,isAutoDisplayEnabled标志仅用于确定触发mouseEntered事件时是否应显示弹出窗口,例如......

MouseAdapter ma = new MouseAdapter() {
    //...
    @Override
    public void mouseEntered(MouseEvent e) {
        if (isAutoDisplayEnabled) {
        popup.setVisible(true);
        }
    }

现在您的ItemListener可以控制弹出窗口的状态

zoomBoxChkBox.addItemListener(new ItemListener() {
    @Override
    public void itemStateChanged(ItemEvent e) {
        // TODO Auto-generated method stub
        if (e.getStateChange() == ItemEvent.SELECTED) {
            zoomPane.setShowZoomPopup(true);
        } else {
            zoomPane.setShowZoomPopup(false);
        }
    }
});

你还可以添加一个检查,看看鼠标当前是否在图像窗格的范围内,所以你不必不必要地显示它,但是我会把它留给你试试弄清楚;)

  

弹出窗口在移动时会闪烁

这是因为每次显示弹出窗口时,它都会触发mouseExit事件,触发弹出窗口隐藏,然后触发mouseEnter事件,依此类推......

这对同一个想法略有不同,但是,它不是单独的窗口,而是将缩放绘制为图像窗格本身的一部分。

这确实意味着,如果缩放超出了面板的范围,它将被截断,但我花了一些时间,以便您可以调整面板大小比图像大,缩放效果仍然工作

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
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();

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(pane);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage img;
        private Point zoomPoint;
        private boolean zoomEnabled = true;
        private int zoomArea = 80;
        private float zoom = 2.0f;

        public TestPane() {
            try {
                img = ImageIO.read(new File("/Volumes/Big Fat Extension/Dropbox/MegaTokyo/_cg_1009___Afraid___by_Serena_Clearwater.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            addMouseMotionListener(new MouseAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    zoomPoint = e.getPoint();
                    repaint();
                }
            });

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseEntered(MouseEvent e) {
                    repaint();
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    zoomPoint = null;
                    repaint();
                }

            });
        }

        public float getZoom() {
            return zoom;
        }

        public void setZoom(float zoom) {
            this.zoom = zoom;
            repaint();
        }

        public int getZoomArea() {
            return zoomArea;
        }

        public void setZoomArea(int zoomArea) {
            this.zoomArea = zoomArea;
            repaint();
        }

        public boolean isZoomEnabled() {
            return zoomEnabled;
        }

        public void setZoomEnabled(boolean zoomEnabled) {
            this.zoomEnabled = zoomEnabled;
            repaint();
        }

        @Override
        public Dimension getPreferredSize() {
            return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
        }

        protected Point getOffset() {
            if (img == null) {
                return new Point(0, 0);
            }
            int x = (getWidth() - img.getWidth()) / 2;
            int y = (getHeight() - img.getHeight()) / 2;
            return new Point(x, y);
        }

        protected Rectangle getImageBounds() {
            Rectangle bounds = new Rectangle(0, 0, 0, 0);
            if (img != null) {
                bounds.setLocation(getOffset());
                bounds.setSize(img.getWidth(), img.getHeight());
            }
            return bounds;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                Point offset = getOffset();
                g2d.drawImage(img, offset.x, offset.y, this);
                if (zoomPoint != null) {
                    BufferedImage zoomBuffer = updateBuffer(zoomPoint);
                    if (zoomBuffer != null) {
                        Rectangle bounds = getZoomBounds();
                        g2d.drawImage(zoomBuffer, bounds.x, bounds.y, this);
                        g2d.setColor(Color.RED);
                        g2d.draw(bounds);
                    }
                }
                g2d.dispose();
            }
        }

        protected Rectangle getZoomBounds() {
            Rectangle bounds = null;
            if (zoomPoint != null && img != null) {
                int zoomArea = getZoomArea();
                int xPos = zoomPoint.x - (zoomArea / 2);
                int yPos = zoomPoint.y - (zoomArea / 2);

                Rectangle zoomBounds = new Rectangle(xPos, yPos, zoomArea, zoomArea);
                Rectangle imageBounds = getImageBounds();

                bounds = imageBounds.intersection(zoomBounds);
                System.out.println(bounds);
            }
            return bounds;
        }

        protected BufferedImage updateBuffer(Point p) {
            if (zoomPoint == null) {
                return null;
            }
            Rectangle bounds = getZoomBounds();
            Point offset = getOffset();
            bounds.translate(-offset.x, -offset.y);
            if (bounds.x < 0 || bounds.y < 0 || bounds.width <= 0 || bounds.height <= 0) {
                return null;
            }
            BufferedImage zoomBuffer = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = zoomBuffer.createGraphics();

            BufferedImage sample = img.getSubimage(bounds.x, bounds.y, bounds.width, bounds.height);
            double zoom = getZoom();
            Image scaled = sample.getScaledInstance((int) (bounds.width * zoom), (int) (bounds.height * zoom), Image.SCALE_SMOOTH);

            g2d.drawImage(scaled, 0, 0, this);
            g2d.dispose();
            return zoomBuffer;
        }

    }

}