抱歉,下面是一段很长的示例代码,但问题是:
我有一个正在积极绘制的背景(我可能会很聪明,绘制一次并缩放它,但这也显示了问题)。
您可以使用鼠标滚轮放大和缩小图像。
这个想法是在鼠标指针下进行缩放的“谷歌地图”缩放。我注意到的是,直到图像足够大以使用两个滚动条时,它似乎才真正起作用。在那之前,您会得到图像变大,但锁定在原点。
“正确”的行为应该是移动 View 位置,即使滚动条尚未被超大图像使用。
我不确定如何解决这个问题(或者这是否正确且符合预期),而不在图像后面绘制更大的背景,使其不仅仅是填充视口(viewport)。
由于(我认为)同样的问题,它在一个或另一个滚动条接合后“跳跃”。
想法?
package com.hostigr.raw.io.client.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
public class TestFrame extends JFrame {
public static void main(String[] arg) {
new TestFrame();
}
public TestFrame() {
initComponents();
setVisible(true);
}
private void initComponents() {
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 600);
setPreferredSize(new Dimension(600, 600));
add(new TopPanel());
}
private class TopPanel extends JPanel {
JScrollPane scrollPane;
public TopPanel() {
setPreferredSize(new Dimension(500,500));
scrollPane = new JScrollPane(new InteriorPanel());
scrollPane.setPreferredSize(new Dimension(500,500));
scrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(10,490));
scrollPane.getHorizontalScrollBar().setPreferredSize(new Dimension(490,10));
scrollPane.setWheelScrollingEnabled(false);
scrollPane.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scrollPane);
}
}
private class InteriorPanel extends JPanel {
private double scale = 10.0;
private final double scaleModifier = 0.1;
private final int width = 10;
private Point loc = new Point(0,0);
private final int SIZE = 10;
public InteriorPanel() {
super(true);
setPreferredSize(new Dimension((int)(scale * width * SIZE),
(int)(scale * width * SIZE)));
this.addMouseWheelListener(new MapMouseWheelListener());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2D.scale(scale,scale);
for (int row = 0; row <= SIZE; row++) {
for (int col = 0; col < SIZE; col++) {
if ((col + row) % 2 == 0) {
g2D.setColor(Color.white);
} else {
g2D.setColor(Color.black);
}
g2D.fillRect(col * width, row * width, width, width);
}
}
}
private void incrementScale(int notches) {
double modifier = 0;
double prevScale = scale;
if (notches != 0) {
modifier = 1.0 + -notches / Math.abs(notches) * scaleModifier;
}
scale = scale * Math.pow(modifier, Math.abs(notches));
/*if (scale * width < 1) {
scale = 1.0/width;
} else if (scale * width * 3 > parentHeight || scale * width * 3 > parentWidth) {
if (parentHeight > parentWidth) {
scale = parentWidth / 3.0 / width;
} else {
scale = parentHeight / 3.0 / width;
}
} else if (scale * width * SIZE < parentWidth) {
scale = parentWidth / (double)SIZE / width;
} else if (scale * width * SIZE < parentHeight) {
scale = parentHeight / (double)SIZE / width;
}*/
this.repaint();
setPreferredSize(new Dimension((int)(scale * width * SIZE),
(int)(scale * width * SIZE)));
JViewport viewport = ((JViewport)(getParent().getParent().getComponent(0)));
Point orig = viewport.getViewPosition();
viewport.setViewPosition(new Point(
orig.x - (int)Math.round(loc.x*(1 - scale/prevScale)),
orig.y - (int)Math.round(loc.y*(1 - scale/prevScale))));
System.out.println(orig + "\n " + loc + "\n " + (1 - scale / prevScale));
revalidate();
}
private class MapMouseWheelListener implements MouseWheelListener {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
loc = e.getPoint();
incrementScale(e.getWheelRotation());
}
}
}
}
最佳答案
看起来像 JViewPort#scrollRectToVisible(Rectangle r)
对我来说有效
viewport.scrollRectToVisible(new Rectangle(new Point(
orig.x - (int) Math.round(loc.x * (1 - scale / prevScale)),
orig.y - (int) Math.round(loc.y * (1 - scale / prevScale)))));
编辑并使用正确的 Swing 重绘规则,那么您的 codeBlock 必须以 revalidate() 结尾; + 重绘();
setPreferredSize(new Dimension((int) (scale * width * SIZE),
(int) (scale * width * SIZE)));
JViewport viewport = ((JViewport) (getParent().getParent().getComponent(0)));
Point orig = viewport.getViewPosition();
/*viewport.setViewPosition(new Point(
orig.x - (int) Math.round(loc.x * (1 - scale / prevScale)),
orig.y - (int) Math.round(loc.y * (1 - scale / prevScale))));*/
viewport.scrollRectToVisible(new Rectangle(new Point(
orig.x - (int) Math.round(loc.x * (1 - scale / prevScale)),
orig.y - (int) Math.round(loc.y * (1 - scale / prevScale)))));
System.out.println(orig + "\n " + loc + "\n " + (1 - scale / prevScale));
revalidate();
repaint();
关于java - JScrollPane "jumping"当滚动条开始使用时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6819243/