问题描述
我在JScrollPane中有一个JPanel.在我的程序中,JPanel显示地图图像,并显示车辆的当前位置.我的程序接收车辆的位置和当前方向.我需要在地图上显示出来.
I have a JPanel within a JScrollPane. In my program, the JPanel shows an image of map and it shows the current location of a vehicle. My program receives the location and current direction of the vehicle. I need to show this on the map.
我在显示车辆方向时遇到问题.我想在地图可见区域的左上方显示一个箭头,以显示方向.以下是我尝试过的代码.但是当我向下滚动时会抛出异常.
I'm having a problem showing the direction of the vehicle. I want to show an arrow on the top left of the map's visible area to show the direction. The following is the code that I have tried. But it throws an exception when I scroll down.
Exception in thread "AWT-EventQueue-0" java.awt.image.RasterFormatException: Transformed height (-287) is less than or equal to 0.
at java.awt.image.AffineTransformOp.createCompatibleDestImage(Unknown Source)
at java.awt.image.AffineTransformOp.filter(Unknown Source)
at Test.paintComponent(Test.java:62)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
public class Test extends JPanel implements ActionListener {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(300, 400);
Test view = new Test();
Dimension minimumSize = new Dimension(1000, 1000);
view.setBorder(BorderFactory.createLineBorder(Color.BLUE));
JScrollPane comp = new JScrollPane(view);
comp.setBorder(BorderFactory.createLineBorder(Color.RED));
f.getContentPane().add(comp, BorderLayout.CENTER);
f.setVisible(true);
view.setPreferredSize(minimumSize);
}
private BufferedImage i;
private Random r = new Random();
public Test() {
try {
i = ImageIO
.read(new URL("https://cdn4.iconfinder.com/data/icons/cc_mono_icon_set/blacks/48x48/br_next.png"));
new Timer(1000, this).start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform transform = g2d.getTransform();
transform.rotate(r.nextFloat() * Math.PI * 2, i.getWidth() / 2, i.getHeight() / 2);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
Rectangle cb = g.getClipBounds();
g2d.drawImage(op.filter(i, null), (int) cb.getX(), (int) cb.getY(), null);
}
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
即使用户使用滚动条滚动,如何使箭头始终在左上角可见?
How can I make the arrow always visible on the top left corner even when the user scrolls using the scroll-bars?
推荐答案
JScrollPane
和JViewport
都经过高度优化,在绘制时,裁剪范围仅设置为实际需要更新的区域(引入的区域)
The JScrollPane
and JViewport
are both highly optimised, when painted, the clipping bounds is only set to the area that actually needs to be updated (the area which was introduced)
一个更好的主意可能是创建您自己的JViewport
,您可以在其上绘制视口的内容
A better idea might be to create your own JViewport
onto which you can paint over the viewport's content
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.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Test extends JPanel {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 400);
Test view = new Test();
view.setBorder(BorderFactory.createLineBorder(Color.BLUE));
JScrollPane comp = new JScrollPane();
ViewPortDirection vp = new ViewPortDirection();
comp.setViewport(vp);
comp.setViewportView(view);
comp.setBorder(BorderFactory.createLineBorder(Color.RED));
f.getContentPane().add(comp, BorderLayout.CENTER);
f.setVisible(true);
}
});
}
public static class ViewPortDirection extends JViewport {
private BufferedImage i;
private Random r = new Random();
public ViewPortDirection() {
try {
i = ImageIO.read(new URL("https://cdn4.iconfinder.com/data/icons/cc_mono_icon_set/blacks/48x48/br_next.png"));
new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}).start();
} catch (IOException e) {
throw new RuntimeException(e);
}
addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
repaint(0, 0, i.getWidth(), i.getHeight());
}
});
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform transform = AffineTransform.getRotateInstance(r.nextFloat() * Math.PI * 2, i.getWidth() / 2, i.getHeight() / 2);
int x = 0;
int y = 0;
g2d.setTransform(transform);
g2d.drawImage(i, x, y, this);
g2d.dispose();
}
}
public Test() {
setBackground(Color.BLUE);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(1000, 1000);
}
}
这篇关于在滚动窗格的左上方绘制箭头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!