我使用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);
}
});
}
}
感谢您的回答。
答案 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;
}
}
}