Java JScrollPane- 多个组件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5840075/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 13:03:43  来源:igfitidea点击:

Java JScrollPane- Multiple components

javaswingjscrollpane

提问by Mike

I'm trying to add 2 images inside the JScrollPane. the first image is a background and the second one overlap the first one. The problem shows only the second image when i run my program!

我正在尝试在 JScrollPane 中添加 2 个图像。第一个图像是背景,第二个图像与第一个图像重叠。当我运行我的程序时,问题只显示第二个图像!

please help

请帮忙

ImageIcon ii = new ImageIcon("mini_map.png");
JLabel label1=new JLabel(ii);

Icon icon = new ImageIcon("Mg.gif");
JLabel label2 = new JLabel(icon);

JScrollPane jsp=new JScrollPane();

jsp.getViewport().add(label1);
jsp.getViewport().add(label2 );

回答by kleopatra

JViewport is a single-child container, you can't add two components.

JViewport 是单子容器,不能添加两个组件。

To achieve an overlap (that is stack components in z-direction) in anycontainer, you'r mostly on your own, the built-in support is poor. Either have to manage them in LayeredPane (as mentioned already) or try OverlapLayout

要在任何容器中实现重叠(即 z 方向上的堆栈组件),您主要靠自己,内置支持很差。要么必须在 LayeredPane 中管理它们(如前所述)或尝试 OverlapLayout

回答by Howard

If you want to have components on top of each other use a layered pane.

如果您想让组件彼此重叠,请使用分层窗格

回答by MByD

Put both labels in the same panel and add it to the JScrollPane:

将两个标签放在同一个面板中并将其添加到 JScrollPane:

ImageIcon ii = new ImageIcon("mini_map.png");
JLabel label1=new JLabel(ii);

Icon icon = new ImageIcon("Mg.gif");
JLabel label2 = new JLabel(icon);

JPanel pContainer = new JPanel();
pContainer.add(label1);
pContainer.add(label2);
JScrollPane jsp=new JScrollPane(pContainer);

回答by Boro

This is how I would do it for your particular problem.

这就是我将如何解决您的特定问题。

Since you say you have one image which serves the role of a background, thus I would override paintComponent() like in BackgroundPanel below. This way you have a panel which serves as a background only. To it you can add any type of component, in your case a JLabel with an ImageIcon.

既然你说你有一个图像作为背景,因此我会像下面的 BackgroundPanel 一样覆盖paintComponent()。这样,您就有了一个仅用作背景的面板。您可以向它添加任何类型的组件,在您的情况下是带有 ImageIcon 的 JLabel。

This way you have an effect of one being over another and you are still able to use layout manager to control where your components are.

通过这种方式,您可以产生一个超越另一个的效果,并且您仍然可以使用布局管理器来控制组件的位置。

If your problem is more complex or you want to generally set Components one over another then do as all are saying here ---> use JLayeredPane. Note that if you use JLayeredPane sadly layout managers will not help you since it doesn't respects them. You will have to proceed similarly to a situation when you use a null manager, i.e. setBounds() for components.

如果您的问题更复杂,或者您想将组件设置在另一个之上,那么请按照此处所说的去做 ---> 使用 JLayeredPane。请注意,如果您使用 JLayeredPane,遗憾的是布局管理器不会帮助您,因为它不尊重它们。当您使用空管理器时,您将不得不以类似的情况进行处理,即组件的 setBounds()。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class PaintInScroll
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    Image backgroundImage = new ImageIcon(new URL(
                            "http://www.jvsearch.com/adidocs7_images/JAVAORANGE.JPG")).getImage();
                    BackgroundPanel bP = new BackgroundPanel(backgroundImage);
                    bP.setLayout(new BorderLayout());
                    bP.setPreferredSize(new Dimension(500, 500));
                    JLabel label = new JLabel(new ImageIcon(new URL(
                            "https://blogs.oracle.com/theplanetarium/resource/thumb-java-duke-guitar.png")));
                    bP.add(label, BorderLayout.CENTER);
                    JScrollPane scrollPane = new JScrollPane(bP);
                    scrollPane.setPreferredSize(new Dimension(300, 400));
                    JPanel contentPane = new JPanel();
                    contentPane.add(scrollPane);
                    JFrame f = new JFrame();
                    f.setContentPane(contentPane);
                    f.setSize(800, 600);
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    f.setVisible(true);
                }catch(MalformedURLException ex)
                {
                    Logger.getLogger(PaintInScroll.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }
}

class BackgroundPanel extends JPanel
{
    private Image image;

    public BackgroundPanel(Image image)
    {
        this.image = image;
    }
    private static final long serialVersionUID = 1L;

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), null);
    }
}

NOTE:Images are URLs thus i-net connection is required to run the example.

注意:图像是 URL,因此运行示例需要 i-net 连接。

EDIT1:Example showing how to use JLayeredPane with use of layout managers for each layer.

EDIT1:示例展示了如何使用 JLayeredPane 并为每一层使用布局管理器。

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class PaintInScrollRespectingLayoutManagers extends JPanel
{
    private static final long serialVersionUID = 1L;
    private JLayeredPane layeredPane;
    private JLabel imageContainer = new JLabel();
    private JButton infoB = new JButton("i");
    private JScrollPane scrollPane;

    public PaintInScrollRespectingLayoutManagers(ImageIcon image)
    {
        super();
        this.imageContainer.setIcon(image);
        scrollPane = new JScrollPane(imageContainer);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setPreferredSize(new Dimension(125, 90));
        JPanel iSPP = new JPanel();//image scroll pane panel
        iSPP.setOpaque(false);
        iSPP.add(scrollPane);
        JPanel iBP = new JPanel();//info button panel
        iBP.setOpaque(false);
        iBP.add(infoB);
        this.layeredPane = new JLayeredPane();
        layeredPane.add(iSPP, new Integer(50));
        layeredPane.add(iBP, new Integer(100));
        this.setLayout(new BorderLayout());
        this.add(layeredPane, BorderLayout.CENTER);
        this.add(new JButton("A button"), BorderLayout.SOUTH);
        layeredPane.addComponentListener(layeredPaneCL);
        setPreferredSize(new Dimension(300, 300));
    }
    private ComponentListener layeredPaneCL = new ComponentAdapter()
    {
        @Override
        public void componentResized(ComponentEvent e)
        {
            super.componentResized(e);
            System.out.println("componentResized");
            for(Component c : layeredPane.getComponents())
                c.setSize(layeredPane.getSize());
        }
    };

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    JFrame frame = new JFrame();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new PaintInScrollRespectingLayoutManagers(new ImageIcon(new URL(
                            "http://www.prodeveloper.org/wp-content/uploads/2008/10/stackoverflow-logo-250.png"))));
                    frame.pack();
                    frame.setVisible(true);
                }catch(MalformedURLException ex)
                {
                    Logger.getLogger(PaintInScrollRespectingLayoutManagers.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }
}

NOTE 2:The only reason that the scroll panes have setPrefferedSize is so you can see the scrollbars. Otherwise do not use it let the layout take care of controlling scroll pane.

注意 2:滚动窗格具有 setPrefferedSize 的唯一原因是您可以看到滚动条。否则不要使用它让布局负责控制滚动窗格。