使图像在 JFrame 内容窗格中可滚动

发布于 2024-12-03 06:21:04 字数 2051 浏览 2 评论 0原文

我正在尝试在 JFrame 的内容窗格中显示大图像。我想让图像或内容窗格可滚动,因为图像很大。我尝试使用 Jscrollpane 来完成此操作并将其添加到内容窗格中,但它不起作用。曾有人寻找解决方案,但最终未能找到。有人可以指导我吗?我的代码位于

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();
}
}

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

}

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

谢谢

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

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();
}
}

Here is my 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.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

优雅的叶子 2024-12-10 06:21:04

我在这里会做什么:

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

    super.paintComponent(g);
    g.drawImage(image, 0, 0, null);

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);
            }
        });
    }
}

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()

    super.paintComponent(g);
    g.drawImage(image, 0, 0, null);

2.Make sure the canvas preferred size equals to image real size.

3.Have a second panel which will serve as content pane of a frame.

4.In it you will set a JScrollPane as its centre.

5.In the scroll pane viewport will be the component from step 1.

6.Add your button to canvas panel from step 1. It will be scrolled together with the image.

7.Add the content pane, the panel from step 3, to a frame, and run the application.

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);
            }
        });
    }
}
再见回来 2024-12-10 06:21:04

如果您使用尺寸来设置地图的首选尺寸会怎样?例如,为 Map 提供此方法:

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

这样 Map JPanel 将占用必要的空间来显示整个图像。另外,为什么你的paintComponent方法中的drawImage方法有很大的magic数字?为什么不也使用那里的宽度和高度呢? 编辑1:或者甚至不按照Boro在他的回答中建议的那样指定图像大小(对他来说1+)。

What if you use your dimensions to set the Map's preferred size. For instance, give Map this method:

// 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 magic numbers? 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).

呆° 2024-12-10 06:21:04

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

您需要做的就是创建一个 JLabel 并向该标签添加一个 ImageIcon,这样就不会有问题。标签将:

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

  2. 根据图像尺寸确定图像的首选尺寸。现在滚动将自动发生。

此外,几乎没有任何理由使用 setPreferredSize() 方法,因为所有组件都有默认的首选大小。所以你不应该设置菜单栏的默认大小。我唯一一次设置首选大小是在 JScrollPane 上。这将使框架以合理的尺寸打包,然后滚动条将根据标签中图像的尺寸自动出现。

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:

  1. paint the image at (0, 0) at its original size (which is exactly what the custom code is doing).

  2. determine the preferred size of the image based on the image size. Now scrolling will happen automatically.

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.

叫嚣ゝ 2024-12-10 06:21:04

除了其他有用的答案之外,您可能还喜欢研究这个 使用鼠标手势滚动任意内容的示例

In addition to other helpful answers, you might like studying this example that uses mouse gestures to scroll arbitrary content.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文