Java 如何在带有空布局和子面板的JPanel中实现缩放
我用一个JScrollPane构建了一个程序。这个滚动窗格包括另一个具有空布局的JPanel,这个面板包括一些其他JPanel[我将它们命名为子面板](带有一些绘制的东西和JLabel) 这些子面板用setBounds(int,int,int,int,int)方法定位在面板中(我不想改变这一点) 在寻找一个很好的缩放解决方案后,我找到了两个选择 -放大“绘制/绘制组件”方法的内部(因为绘制的内容已更改,但x、y轴的比例未更改,且这些子面板的宽度和高度未更改,所以效果不佳->我的鼠标侦听器无法工作(在错误的位置)) -使用JScrollPane的视口进行缩放(根本不起作用(我在google等上找到的结果) 因此,我正在寻找一个很好的解决方案来放大和缩小我的JPanel 这里有一些代码来想象我的意思Java 如何在带有空布局和子面板的JPanel中实现缩放,java,jpanel,zooming,jscrollpane,null-layout-manager,Java,Jpanel,Zooming,Jscrollpane,Null Layout Manager,我用一个JScrollPane构建了一个程序。这个滚动窗格包括另一个具有空布局的JPanel,这个面板包括一些其他JPanel[我将它们命名为子面板](带有一些绘制的东西和JLabel) 这些子面板用setBounds(int,int,int,int,int)方法定位在面板中(我不想改变这一点) 在寻找一个很好的缩放解决方案后,我找到了两个选择 -放大“绘制/绘制组件”方法的内部(因为绘制的内容已更改,但x、y轴的比例未更改,且这些子面板的宽度和高度未更改,所以效果不佳->我的鼠标侦听器无法工作
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class MyAppFrame extends JFrame {
private JScrollPane scroll;
private JPanel nullLayoutPanel;
private JPanel subPanel;
private double zoomFactor;
private double lastScale;
private static Point pressed;
public MyAppFrame(){
setSize(200, 200);
setLocation(50, 50);
zoomFactor = 1.0;
lastScale = 1.0;
nullLayoutPanel = new JPanel(){
//when you try it with the paint method you'll see my problem
//move the rect by dragging it around then
//scroll out or in and try to move the rect
//you'll see that the position of the logical rect doesn't fit with the painted one
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
//g2d.translate(nullLayoutPanel.getWidth()/2, nullLayoutPanel.getHeight()/2);
g2d.scale(zoomFactor, zoomFactor);
//g2d.translate(-nullLayoutPanel.getWidth()/2, -nullLayoutPanel.getHeight()/2);
//super.paint(g2d);
g2d.dispose();
}
@Override
public Dimension getPreferredSize(){
return new Dimension((int)(nullLayoutPanel.getWidth()*zoomFactor), (int)(nullLayoutPanel.getHeight()*zoomFactor));
}
};
nullLayoutPanel.setPreferredSize(new Dimension(400,400));
nullLayoutPanel.setLayout(null);
nullLayoutPanel.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL){
if((.1 * e.getWheelRotation()) > 0 && zoomFactor < 2.0){
zoomFactor += (.1 * e.getWheelRotation());
} else if((.1 * e.getWheelRotation()) < 0 && zoomFactor > 0.1){
zoomFactor += (.1 * e.getWheelRotation());
}
zoomFactor = Math.round(zoomFactor*10.0)/10.0;
zoom(e.getPoint());
}
}
});
scroll = new JScrollPane(nullLayoutPanel);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
getContentPane().add(scroll);
subPanel = new JPanel(){
@Override
public void paint(Graphics g){
g.setColor(Color.BLUE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}
};
subPanel.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
pressed = e.getPoint();
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
});
subPanel.addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseDragged(MouseEvent e) {
Point pPoint;
pPoint = subPanel.getLocation();
int x = (int)(pPoint.x - pressed.getX()+e.getX());
int y = (int)(pPoint.y - pressed.getY()+e.getY());
if(x>0&&y>0)
subPanel.setLocation(x,y);
repaint();
}
});
subPanel.setBounds(10, 10, 10, 10);
nullLayoutPanel.add(subPanel);
setVisible(true);
}
public void alignViewPort(Point mousePosition) {
// if the scale didn't change there is nothing we should do
if (zoomFactor != lastScale) {
// compute the factor by that the image zoom has changed
double scaleChange = zoomFactor / lastScale;
// compute the scaled mouse position
Point scaledMousePosition = new Point(
(int)Math.round(mousePosition.x * scaleChange),
(int)Math.round(mousePosition.y * scaleChange)
);
// retrieve the current viewport position
Point viewportPosition = scroll.getViewport().getViewPosition();
// compute the new viewport position
Point newViewportPosition = new Point(
viewportPosition.x + scaledMousePosition.x - mousePosition.x,
viewportPosition.y + scaledMousePosition.y - mousePosition.y
);
// update the viewport position
// IMPORTANT: This call doesn't always update the viewport position. If the call is made twice
// it works correctly. However the screen still "flickers".
scroll.getViewport().setViewPosition(newViewportPosition);
// debug
if (!newViewportPosition.equals(scroll.getViewport().getViewPosition())) {
System.out.println("Error: " + newViewportPosition + " != " + scroll.getViewport().getViewPosition());
}
// remember the last scale
lastScale = zoomFactor;
}
}
public void zoom(Point p){
alignViewPort(p);
nullLayoutPanel.revalidate();
scroll.repaint();
}
/**
* @param args
*/
public static void main(String[] args) {
new MyAppFrame();
}
}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Point;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseListener;
导入java.awt.event.MouseMotionListener;
导入java.awt.event.mouseweelEvent;
导入java.awt.event.MouseWheelListener;
导入java.awt.geom.AffineTransform;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
公共类MyAppFrame扩展了JFrame{
私有JScrollPane滚动条;
私人JPanel nullLayoutPanel;
私人JPanel子面板;
私人双重动物因子;
私人双表;
私有静态点按下;
公共MyAppFrame(){
设置大小(200200);
设定位置(50,50);
zoomFactor=1.0;
lastScale=1.0;
nullLayoutPanel=newjpanel(){
//当你用画法尝试时,你会发现我的问题
//然后通过拖动矩形来移动矩形
//向外或向内滚动并尝试移动矩形
//您将看到逻辑rect的位置与绘制的位置不匹配
@凌驾
公共组件(图形g){
超级组件(g);
Graphics2D g2d=(Graphics2D)g.create();
//translate(nullLayoutPanel.getWidth()/2,nullLayoutPanel.getHeight()/2);
g2d.比例(缩放因子,缩放因子);
//translate(-nullLayoutPanel.getWidth()/2,-nullLayoutPanel.getHeight()/2);
//超级油漆(g2d);
g2d.dispose();
}
@凌驾
公共维度getPreferredSize(){
返回新维度((int)(nullLayoutPanel.getWidth()*zoomFactor),(int)(nullLayoutPanel.getHeight()*zoomFactor));
}
};
nullLayoutPanel.setPreferredSize(新维度(400400));
nullLayoutPanel.setLayout(null);
nullLayoutPanel.addMouseWheelListener(新的MouseWheelListener(){
@凌驾
已移动公共无效鼠标滚轮(鼠标滚轮事件e){
如果(例如getScrollType()==MouseWheelEvent.WHEEL\u单元\u滚动){
如果(.1*e.getWheelRotation())>0&&zoomFactor<2.0){
zoomFactor+=(.1*e.getWheelRotation());
}如果(.1*e.getWheelRotation())<0&&zoomFactor>0.1,则为else{
zoomFactor+=(.1*e.getWheelRotation());
}
zoomFactor=Math.round(zoomFactor*10.0)/10.0;
缩放(如getPoint());
}
}
});
滚动=新的JScrollPane(nullLayoutPanel);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HorizontalScrollBar\uAlways);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL\u SCROLLBAR\u ALWAYS);
getContentPane().add(滚动);
子面板=新的JPanel(){
@凌驾
公共空间涂料(图g){
g、 setColor(Color.BLUE);
g、 fillRect(0,0,this.getWidth(),this.getHeight());
}
};
子面板addMouseListener(新MouseListener(){
@凌驾
公共无效MouseEvent(MouseEvent e){
//TODO自动生成的方法存根
}
@凌驾
公共无效鼠标按下(MouseEvent e){
按下=e.getPoint();
}
@凌驾
公共无效mouseExited(MouseEvent e){
//TODO自动生成的方法存根
}
@凌驾
公共无效鼠标事件(鼠标事件e){
//TODO自动生成的方法存根
}
@凌驾
公共无效mouseClicked(MouseEvent e){
//TODO自动生成的方法存根
}
});
子面板addMouseMotionListener(新的MouseMotionListener(){
@凌驾
public void mouseMoved(MouseEvent e){
//TODO自动生成的方法存根
}
@凌驾
公共无效鼠标标记(鼠标事件e){
点对点;
pPoint=subPanel.getLocation();
intx=(int)(pPoint.x-pressed.getX()+e.getX());
int y=(int)(pPoint.y-pressed.getY()+e.getY());
如果(x>0&&y>0)
子面板设置位置(x,y);
重新油漆();
}
});
第10、10、10、10、10子面板;
nullLayoutPanel.add(子面板);
setVisible(真);
}
公共空心对齐视口(点鼠标位置){
//如果比例没有改变,我们就什么都不应该做
如果(缩放因子!=lastScale){
//计算图像缩放已更改的系数
双尺度变换=缩放因子/最后尺度;
//计算缩放的鼠标位置
点scaledMousePosition=新点(
(int)数学圆(mousePosition.x*scaleChange),
(int)数学圆(mousePosition.y*scaleChange)
);
//检索当前视口位置
Point viewportPosition=滚动.getViewport().getViewPosition();
//计算新视口位置
Point newViewportPosition=新点(
viewportPosition.x+scaledMousePosition.x-mousePosition.x,
争夺