【问题标题】:Make ZoomBox around cursor disappear when JCheckBox unchecked取消选中 JCheckBox 时使光标周围的 ZoomBox 消失
【发布时间】:2017-11-29 02:17:24
【问题描述】:

我使用Zoom box for area around mouse location on screen 的第一个答案在鼠标位置周围创建了一个缩放框窗口,它会随着鼠标移动而放大图像。

现在,我想知道如何在选中 JCheckBox 时激活此 Zoom Box View,如果未选中则停用它。

我修改了 @MadProgrammer 编写的类 ZoomBoxWindowZoomPane,添加了用于激活和停用 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);
  }
});
}
}

感谢您的回答。

【问题讨论】:

    标签: java swing zooming jcheckbox


    【解决方案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 的新实例。除了将一堆MouseListeners 添加到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;
            }
    
        }
    
    }
    

    【讨论】:

    • 谢谢,这行得通。我还有一个小问题:有没有办法使用相同的代码使 Zoom Pane 窗口以鼠标位置为中心,这意味着窗口的中心将成为光标?
    • 基本解决方案是从鼠标点减去弹出窗口宽度/高度的一半
    • 完成后,弹出窗口在移动时闪烁
    • 由于mouseEnter/Exit 事件而闪烁,因为当弹出窗口可见时,它会生成exit 事件:P
    • @Marija 我用稍微不同的方法更新了答案
    【解决方案2】:

    将新的ZoomPane 分配给zoomPane 字段不会对实际显示的ZoomPane 执行任何操作。

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

    您可以通过将以下方法添加到 ZoomPane 来做到这一点:

    void switchZoomBoxActivated() {
    
        zoomBoxActivated = !zoomBoxActivated;
    }
    

    那么在ItemListener,就这样称呼吧:

    @Override
    public void itemStateChanged(final ItemEvent e) {
    
       zoomPane.switchZoomBoxActivated();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-12
      • 2012-08-16
      • 1970-01-01
      • 2019-03-21
      • 1970-01-01
      相关资源
      最近更新 更多