我正在尝试在一个有限的、更大的红色矩形内操纵一些蓝色矩形。
我将其与放大和缩小功能一起使用
问题是我想在红色矩形不完全可见时显示滚动条 并在整个红色矩形可见时动态删除滚动条。
我怎样才能实现这个目标?这就是我到目前为止所得到的...
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
public class Demo {
public static void main(String[] args) {
JFrame frame = new JFrame("Zoomable Canvas");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
ZoomPanel zoomPanel = new ZoomPanel();
frame.add(zoomPanel);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
}
class ZoomPanel extends JPanel {
private static final long serialVersionUID = 1L;
private double zoomFactor = 1.0;
private static final double ZOOM_MULTIPLIER = 1.1;
private static final double MIN_ZOOM = 0.1; // Minimum zoom level
private static final double MAX_ZOOM = 4.0; // Maximum zoom level
private Point zoomCenter;
private AffineTransform currentTransform;
private Point lastMousePosition;
private Rectangle2D.Double square;
private Point dragOffset;
private Rectangle2D.Double redRectangle;
public ZoomPanel() {
currentTransform = new AffineTransform();
square = new Rectangle2D.Double(100, 100, 200, 200);
redRectangle = new Rectangle2D.Double(0, 0, 1000, 1000);
addMouseWheelListener(new MouseAdapter() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
double adjustedZoomFactor = e.getWheelRotation() < 0 ? ZOOM_MULTIPLIER : 1 / ZOOM_MULTIPLIER;
double newZoomFactor = zoomFactor * adjustedZoomFactor;
// Check if the new zoom factor is within the valid range
if (newZoomFactor >= MIN_ZOOM && newZoomFactor <= MAX_ZOOM) {
zoomFactor = newZoomFactor;
zoomCenter = e.getPoint();
AffineTransform at = new AffineTransform();
at.translate(zoomCenter.getX(), zoomCenter.getY());
at.scale(adjustedZoomFactor, adjustedZoomFactor);
at.translate(-zoomCenter.getX(), -zoomCenter.getY());
currentTransform.preConcatenate(at);
repaint();
}
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
Point transformedPoint = transformPoint(e.getPoint(), currentTransform);
if (square.contains(transformedPoint)) {
lastMousePosition = e.getPoint();
dragOffset = new Point(transformedPoint.x - (int) square.getX(), transformedPoint.y - (int) square.getY());
} else {
lastMousePosition = null;
}
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (lastMousePosition != null) {
Point transformedPoint = transformPoint(e.getPoint(), currentTransform);
int newX = transformedPoint.x - dragOffset.x;
int newY = transformedPoint.y - dragOffset.y;
// Check if the new position is within the red rectangle
if (redRectangle.contains(newX, newY, square.getWidth(), square.getHeight())) {
square.setRect(newX, newY, square.getWidth(), square.getHeight());
lastMousePosition = e.getPoint();
repaint();
}
}
}
});
}
private Point transformPoint(Point point, AffineTransform transform) {
try {
AffineTransform inverse = transform.createInverse();
Point transformedPoint = new Point();
inverse.transform(point, transformedPoint);
return transformedPoint;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Apply zoom factor
if (zoomCenter != null) {
g2d.transform(currentTransform);
}
// Draw red rectangle
g2d.setColor(Color.red);
g2d.fill(redRectangle);
// Draw blue square
g2d.setColor(Color.BLUE);
g2d.fill(square);
}
}
我的代码有问题......
package zoom;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
public class Demo {
public static void main(String[] args) {
JFrame frame = new JFrame("Zoomable Canvas");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
ZoomPanel zoomPanel = new ZoomPanel();
JScrollPane scrollPane = new JScrollPane(zoomPanel);
frame.add(scrollPane);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
}
class ZoomPanel extends JPanel {
private static final long serialVersionUID = 1L;
private double zoomFactor = 1.0;
private static final double ZOOM_MULTIPLIER = 1.1;
private static final double MIN_ZOOM = 0.1; // Minimum zoom level
private static final double MAX_ZOOM = 4.0; // Maximum zoom level
private Point zoomCenter;
private AffineTransform currentTransform;
private Point lastMousePosition;
private Rectangle2D.Double square;
private Point dragOffset;
private Rectangle2D.Double redRectangle;
public ZoomPanel() {
currentTransform = new AffineTransform();
square = new Rectangle2D.Double(100, 100, 200, 200);
redRectangle = new Rectangle2D.Double(0, 0, 1000, 1000);
addMouseWheelListener(new MouseAdapter() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
double adjustedZoomFactor = e.getWheelRotation() < 0 ? ZOOM_MULTIPLIER : 1 / ZOOM_MULTIPLIER;
double newZoomFactor = zoomFactor * adjustedZoomFactor;
// Check if the new zoom factor is within the valid range
if (newZoomFactor >= MIN_ZOOM && newZoomFactor <= MAX_ZOOM) {
zoomFactor = newZoomFactor;
zoomCenter = e.getPoint();
AffineTransform at = new AffineTransform();
at.translate(zoomCenter.getX(), zoomCenter.getY());
at.scale(adjustedZoomFactor, adjustedZoomFactor);
at.translate(-zoomCenter.getX(), -zoomCenter.getY());
currentTransform.preConcatenate(at);
updatePreferredSize(); // Add this line
repaint();
}
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
Point transformedPoint = transformPoint(e.getPoint(), currentTransform);
if (square.contains(transformedPoint)) {
lastMousePosition = e.getPoint();
dragOffset = new Point(transformedPoint.x - (int) square.getX(), transformedPoint.y - (int) square.getY());
} else {
lastMousePosition = null;
}
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (lastMousePosition != null) {
Point transformedPoint = transformPoint(e.getPoint(), currentTransform);
int newX = transformedPoint.x - dragOffset.x;
int newY = transformedPoint.y - dragOffset.y;
// Check if the new position is within the red rectangle
if (redRectangle.contains(newX, newY, square.getWidth(), square.getHeight())) {
square.setRect(newX, newY, square.getWidth(), square.getHeight());
lastMousePosition = e.getPoint();
repaint();
}
}
}
});
}
private Point transformPoint(Point point, AffineTransform transform) {
try {
AffineTransform inverse = transform.createInverse();
Point transformedPoint = new Point();
inverse.transform(point, transformedPoint);
return transformedPoint;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Apply zoom factor
if (zoomCenter != null) {
g2d.transform(currentTransform);
}
// Draw red rectangle
g2d.setColor(Color.red);
g2d.fill(redRectangle);
// Draw blue square
g2d.setColor(Color.BLUE);
g2d.fill(square);
}
private void updateScrollbars() {
Container parent = getParent();
if (parent instanceof JViewport) {
JViewport viewport = (JViewport) parent;
Rectangle viewRect = viewport.getViewRect();
boolean horizontalScrollbarVisible = viewRect.width < redRectangle.width * zoomFactor;
boolean verticalScrollbarVisible = viewRect.height < redRectangle.height * zoomFactor;
JScrollPane scrollPane = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
if (scrollPane != null) {
scrollPane.setHorizontalScrollBarPolicy(horizontalScrollbarVisible ? JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED : JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setVerticalScrollBarPolicy(verticalScrollbarVisible ? JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED : JScrollPane.VERTICAL_SCROLLBAR_NEVER);
}
}
}
private void updatePreferredSize() {
int width = (int) (redRectangle.width * zoomFactor);
int height = (int) (redRectangle.height * zoomFactor);
setPreferredSize(new Dimension(width, height));
revalidate();
}
}
我尝试了camickr的建议,但没有使用scrollbarpolicy并覆盖有效的getPreferredSize——有点......当我调整大小时,我会得到时髦的滚动条闪烁,无论我尝试什么,我都无法在最大化后捕获恢复事件......所以覆盖代码没有任何效果
package zoom;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class SwingApp {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("Swing App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(640, 480);
frame.setResizable(true);
JScrollPane scrollPane = new JScrollPane();
Editor editor = new Editor(scrollPane);
/*
frame.addWindowStateListener(new WindowStateListener() {
@Override
public void windowStateChanged(WindowEvent e) {
if ((e.getNewState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH
|| e.getNewState() == Frame.NORMAL) {
editor.updateWorkspace();
editor.updatePreferredSize();
frame.repaint();
}
}
});
*/
frame.addComponentListener(new ComponentListener() {
@Override public void componentResized(ComponentEvent arg0) {
editor.updateWorkspace();
editor.updatePreferredSize();
editor.repaint();
}
@Override public void componentHidden(ComponentEvent arg0) {}
@Override public void componentMoved(ComponentEvent arg0) {}
@Override public void componentShown(ComponentEvent arg0) {}
});
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
static class Editor extends JPanel {
private static final long serialVersionUID = 1L;
private static final int WORKSPACE_WIDTH = 300;
private static final int WORKSPACE_HEIGHT = 300;
private Dimension preferredSize;
private Rectangle workspace;
private Rectangle box;
private JScrollPane scrollPane;
private Editor(JScrollPane s) {
scrollPane = s;
preferredSize = new Dimension(WORKSPACE_WIDTH, WORKSPACE_HEIGHT);
workspace = new Rectangle(0, 0, WORKSPACE_WIDTH, WORKSPACE_HEIGHT);
box = new Rectangle(workspace.x + 100, workspace.y + 100, 100, 100);
scrollPane.setViewportView(this);
// updateWorkspace();
// updatePreferredSize();
// revalidate();
}
public void updateWorkspace() {
int xPos = (getWidth() - workspace.width) / 2;
int yPos = (getHeight() - workspace.height) / 2;
workspace = new Rectangle(xPos, yPos, workspace.width, workspace.height);
box = new Rectangle(workspace.x + 100, workspace.y + 100, box.width, box.height);
}
@Override
public Dimension getPreferredSize() {
return preferredSize;
}
private void updatePreferredSize() {
Rectangle v = scrollPane.getViewport().getVisibleRect();
if(v != null) {
int left = Math.min(v.x, workspace.x);
int right = Math.max(v.x + v.width, workspace.x + workspace.width);
int top = Math.min(v.y, workspace.y);
int bottom = Math.max(v.y + v.height, workspace.y + workspace.height);
preferredSize = new Dimension(right-left, bottom-top);
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(workspace.x, workspace.y, workspace.width, workspace.height);
g.setColor(Color.BLUE);
g.fillRect(box.x, box.y, box.width, box.height);
}
}
}
您尝试过scrollPane滚动条策略吗?
https://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html#setup