java 使图像在 JFrame 内容窗格中可滚动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7298817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Making image scrollable in JFrame contentpane
提问by Noble
I am trying to display a large image inside a JFrame's contentpane. I would like to make the image or contentpane scrollable as the image is large. I tried to do it using Jscrollpane and add it into the contentpane but it didn't work. Did some searching for solution but end up failed to find one. Can someone guide me? My code are below
我正在尝试在 JFrame 的内容窗格中显示大图像。我想让图像或内容窗格可滚动,因为图像很大。我尝试使用 Jscrollpane 执行此操作并将其添加到内容窗格中,但没有成功。做了一些搜索解决方案,但最终未能找到一个。有人可以指导我吗?我的代码如下
FinalEnvironment.java
最终环境.java
package environment;
import java.awt.*;
import java.net.URL;
import javax.swing.*;
public class FinalEnvironment{
public FinalEnvironment(){
Image Eastlake;
URL EastlakeURL = null;
EastlakeURL = FinalEnvironment.class.getResource("/image1/eastlake_night.png");
Eastlake = Toolkit.getDefaultToolkit().getImage(EastlakeURL);
JFrame frame = new JFrame("UniCat World");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
JMenuBar yellowMenuBar = new JMenuBar();
Map map = new Map(800, 550, Eastlake);
yellowMenuBar.setOpaque(true);
yellowMenuBar.setBackground(Color.YELLOW);
yellowMenuBar.setPreferredSize(new Dimension(800, 50));
frame.setJMenuBar(yellowMenuBar);
JScrollPane scroller = new JScrollPane(map);
scroller.setAutoscrolls(true);
scroller.setPreferredSize(new Dimension(800, 550));
frame.getContentPane().add(scroller, BorderLayout.CENTER);
frame.setSize(800, 600);
frame.setVisible(true);
}
public static void main(String[] args){
FinalEnvironment fe = new FinalEnvironment();
}
}
Here is my map.java
这是我的 map.java
package environment;
import java.awt.*;
import javax.swing.*;
public class Map extends JPanel{
private int width;
private int height;
private Image img;
public Map(int width, int height, Image img){
this.width = width;
this.height = height;
this.img = img;
}
protected void paintComponent(Graphics g)
{
super.paintComponents(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img,0,0,2624,1696,null);
}
}
Lastly, I would like to place Jbuttons on top of this image. Should I call a Rectangle and place it on top the image in the contentpane which then I use Point to position my buttons or should I straight away use the image or the component itself to do it? I need the button to be able to synchronize with the image when it is scrolled instead of static in the contentpane.
最后,我想将 Jbuttons 放在这张图片的顶部。我应该调用一个 Rectangle 并将其放在内容窗格中的图像顶部,然后我使用 Point 来定位我的按钮,还是应该立即使用图像或组件本身来做到这一点?我需要按钮能够在滚动时与图像同步而不是在内容窗格中进行静态。
Thanks
谢谢
回答by Boro
What I would do here:
我会在这里做什么:
1.Have a panel (canvas) which only responsibility is to paint a given image independent of the real image size in overridden method paintComponent()
1.有一个面板(画布),它的唯一职责是在重写方法中绘制独立于真实图像大小的给定图像 paintComponent()
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
2.Make sure the canvas preferred size equals to image real size.
2.确保画布的首选大小等于图像的实际大小。
3.Have a second panel which will serve as content pane of a frame.
3.有第二个面板,作为框架的内容面板。
4.In it you will set a JScrollPane
as its centre.
4.在其中,您将设置 aJScrollPane
作为其中心。
5.In the scroll pane viewport will be the component from step 1.
5.在滚动窗格视口中将是步骤 1 中的组件。
6.Add your button to canvas panel from step 1. It will be scrolled together with the image.
6.将您的按钮添加到步骤 1 中的画布面板。它将与图像一起滚动。
7.Add the content pane, the panel from step 3, to a frame, and run the application.
7.将内容窗格(步骤 3 中的面板)添加到框架中,然后运行应用程序。
EDIT:Code sample with button added to canvas, which stays always in its place, independent of scroll position or frame size.
编辑:将按钮添加到画布的代码示例,它始终保持在原位,与滚动位置或帧大小无关。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class ScrollImageTest extends JPanel {
private static final long serialVersionUID = 1L;
private BufferedImage image;
private JPanel canvas;
public ScrollImageTest() {
try {
this.image = ImageIO.read(new URL("http://interviewpenguin.com/wp-content/uploads/2011/06/java-programmers-brain.jpg"));
}catch(IOException ex) {
Logger.getLogger(ScrollImageTest.class.getName()).log(Level.SEVERE, null, ex);
}
this.canvas = new JPanel() {
private static final long serialVersionUID = 1L;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
};
canvas.add(new JButton("Currently I do nothing"));
canvas.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
JScrollPane sp = new JScrollPane(canvas);
setLayout(new BorderLayout());
add(sp, BorderLayout.CENTER);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JPanel p = new ScrollImageTest();
JFrame f = new JFrame();
f.setContentPane(p);
f.setSize(400, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}
回答by camickr
Why is everybody reinventing the wheel??? There is no need for a custom panel to paint the image!!!
为什么大家都在重新发明轮子???不需要自定义面板来绘制图像!!!
All you need to do is create a JLabel and add an ImageIcon to the label and you won't have a problem. The label will:
您需要做的就是创建一个 JLabel 并将一个 ImageIcon 添加到标签中,您就不会遇到问题。该标签将:
paint the image at (0, 0) at its original size (which is exactly what the custom code is doing).
determine the preferred size of the image based on the image size. Now scrolling will happen automatically.
以原始大小在 (0, 0) 处绘制图像(这正是自定义代码正在执行的操作)。
根据图像大小确定图像的首选大小。现在滚动将自动发生。
Also there is rarely any reason to use the setPreferredSize() method since all components have a default preferred size. So you should not set the default size of the menu bar. The only time I set a preferred size would be on the JScrollPane. This will allow the frame to be packed at a reasonable size and then scrollbars will appear automatically based on the size of the image in the label.
此外,很少有任何理由使用 setPreferredSize() 方法,因为所有组件都有默认的首选大小。所以你不应该设置菜单栏的默认大小。我唯一一次设置首选大小是在 JScrollPane 上。这将允许以合理的大小打包框架,然后滚动条将根据标签中图像的大小自动出现。
回答by Hovercraft Full Of Eels
What if you use your dimensions to set the Map's preferred size. For instance, give Map this method:
如果您使用尺寸来设置地图的首选尺寸会怎样。例如,给 Map 这个方法:
// method in the Map class
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
This way the Map JPanel will take up the necessary room to show the entire image. Also, why does your drawImage method in the paintComponent method have the large magicnumbers? Why not use the width and height there as well? Edit 1:or don't even specify the image size as Boro suggests in his answer (1+ to him).
这样 Map JPanel 将占用必要的空间来显示整个图像。另外,为什么你的paintComponent方法中的drawImage方法有很大的幻数?为什么不使用那里的宽度和高度呢? 编辑 1:或者甚至不要像 Boro 在他的回答中建议的那样指定图像大小(对他来说是 1+)。