使图像在JFrame contentpane中可滚动

Nob*_*ble 12 java swing image jscrollpane

我试图在JFrame的contentpane中显示一个大图像.我想使图像或内容窗格可滚动,因为图像很大.我尝试使用Jscrollpane并将其添加到contentpane但它不起作用.有人寻找解决方案,但最终找不到解决方案.有人可以指导我吗?我的代码如下

FinalEnvironment.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();
}
}
Run Code Online (Sandbox Code Playgroud)

这是我的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);
    }

}
Run Code Online (Sandbox Code Playgroud)

最后,我想将Jbuttons放在此图像的顶部.我应该调用一个矩形并将其放在contentpane中的图像上,然后我使用Point来定位我的按钮,还是我应该立即使用图像或组件本身来完成它?我需要按钮能够在内容窗格中滚动而不是静态时与图像同步.

谢谢

Bor*_*oro 14

我会在这做什么:

1.有一个面板(画布),其唯一的责任是在重写方法中独立于实际图像大小绘制给定图像 paintComponent()

    super.paintComponent(g);
    g.drawImage(image, 0, 0, null);
Run Code Online (Sandbox Code Playgroud)

2.确保画布首选大小等于图像实际大小.

3.有第二个面板,用作框架的内容窗格.

4.在其中你将设置一个JScrollPane中心.

5.在滚动窗格中,视口将是步骤1中的组件.

6.将步骤1中的按钮添加到画布面板.它将与图像一起滚动.

7.将内容窗格(步骤3中的面板)添加到框架,然后运行该应用程序.

编辑: 带有添加到画布的按钮的代码示例,它始终保持在原位,与滚动位置或帧大小无关.

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);
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Noble:如果您的计划遇到新问题并需要我们的帮助,那么您最好的办法是在SO上提出一个新问题.如果需要,您可以链接到此问题,但为新问题创建新问题将增加获得及时帮助的机会. (2认同)

Hov*_*els 5

如果您使用尺寸来设置地图的首选尺寸,该怎么办?例如,给Map这个方法:

// method in the Map class
@Override
public Dimension getPreferredSize() {
  return new Dimension(width, height);
}
Run Code Online (Sandbox Code Playgroud)

这样,Map JPanel将占用显示整个图像的必要空间.另外,为什么paintComponent方法中的drawImage方法具有大的数?为什么不在那里使用宽度和高度? 编辑1:或者甚至不指定Boro在他的答案中建议的图像大小(1+给他).


cam*_*ckr 5

为什么每个人都在重新发明轮子??? 不需要自定义面板来绘制图像!

您需要做的就是创建一个JLabel并将ImageIcon添加到标签中,您将不会遇到任何问题.标签将:

  1. 将图像绘制在(0,0)处的原始大小(这正是自定义代码正在执行的操作).

  2. 根据图像大小确定图像的首选大小.现在滚动会自动发生.

此外,很少有任何理由使用setPreferredSize()方法,因为所有组件都具有默认的首选大小.因此,您不应该设置菜单栏的默认大小.我设置首选大小的唯一时间是JScrollPane.这将允许以合理的大小打包框架,然后根据标签中图像的大小自动显示滚动条.