在1个JPanel中绘制2个图像

时间:2011-07-07 11:29:52

标签: java swing jscrollpane draw

我想绘制2 JScrollPanes之间的线条(左侧第一个滚动窗格,右侧第二个)。这些JScrollPanes包含图片。我想在这两个图像之间画线(使用一些图层,使用一些技巧等)。我尝试了不同的方式,但我失败了。可能吗? (如果没有,我将不得不在一个JScrollPane制作2张图片,这样就不太好了。

修改

我想绘制两幅图像 - 通过组件 - 从图像中获取一些点并在它们之间绘制线条。我为制定不好的问题道歉。

3 个答案:

答案 0 :(得分:7)

为了实现这一目标,我相信您需要使用Glass PaneGlass Pane位于JRootPane中的所有内容之上,并填充整个视图。这个特殊的位置允许两个不同的功能:

  • 拦截鼠标和键盘事件
  • 绘制整个用户界面

我相信你的问题是由第二种能力解决的。以下是一个示例实现,您可以稍后根据自己的需要进行定制。请注意,我已经遗漏了很多关于您需要自己研究的Glass Pane的详细信息。

<强> CODE

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class GlassPaneDemo {
        private static BufferedImage bi;

        public static void main(String[] args){
            try {
                loadImages();

                SwingUtilities.invokeLater(new Runnable(){
                    @Override
                    public void run() {
                        createAndShowGUI();             
                    }
                });
            } catch (IOException e) {
                // handle exception
            }
        }

        private static void loadImages() throws IOException{
            bi = ImageIO.read(new File("src/resources/person.png"));
        }

        private static void createAndShowGUI(){
            final JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setResizable(false);
            frame.setGlassPane(new CustomGlassPane());
            frame.getContentPane().add(getButtonPanel());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.getGlassPane().setVisible(true);
            frame.setVisible(true);
        }

        private static final JPanel getButtonPanel(){
            @SuppressWarnings("serial")
            final JPanel panel = new JPanel(){
                @Override
                protected void paintComponent(Graphics g){
                    Graphics gCopy = g.create();

                    gCopy.setColor(Color.BLUE.darker());
                    gCopy.fillRect(0, 0, getWidth(), getHeight());

                    gCopy.dispose();
                }
            };

            final JLabel labelOne = new JLabel();
            labelOne.setIcon(new ImageIcon(bi));
            final JLabel labelTwo = new JLabel();
            labelTwo.setIcon(new ImageIcon(bi));
            panel.add(labelOne);
            panel.add(labelTwo);

            return panel;
        }

        @SuppressWarnings("serial")
        private static class CustomGlassPane extends JComponent{
            private Point p1;
            private Point p2;
            private boolean lineDrawn;

            public CustomGlassPane(){
                addMouseListener(new MouseAdapter(){
                    @Override
                    public void mouseClicked(MouseEvent e){
                        if(p1 == null || lineDrawn){
                            if(lineDrawn){
                                p1 = null;
                                p2 = null;
                                lineDrawn = false;
                            }
                            p1 = e.getPoint();
                        }else{
                            p2 = e.getPoint();
                            repaint(); // not optimal
                            lineDrawn = true;
                        }
                    }
                });

                // Block all other input events
                addMouseMotionListener(new MouseMotionAdapter(){});
                addKeyListener(new KeyAdapter(){});
                addComponentListener(new ComponentAdapter(){
                    @Override
                    public void componentShown(ComponentEvent e){
                        requestFocusInWindow();
                    }
                });
                setFocusTraversalKeysEnabled(false);
            }

            @Override
            protected void paintComponent(Graphics g){
                if(p1 != null && p2 != null){
                    Graphics2D g2 = (Graphics2D) g.create();

                    g2.setRenderingHint(
                            RenderingHints.KEY_ANTIALIASING, 
                            RenderingHints.VALUE_ANTIALIAS_ON);
                    g2.setColor(Color.RED);
                    g2.drawLine((int)p1.getX(), (int)p1.getY(), (int)p2.getX(), (int)p2.getY());

                    g2.dispose();
                }
            }
        }
  }

<强>输出

enter image description here

<强>说明

在这个例子中,我点击了每个JLabel中的两个任意点,然后绘制了一条连接线。

答案 1 :(得分:2)

这应该是非常可能的。您需要创建一个知道两个垂直ScrollBars的自定义组件。它应该将自己添加为每个滚动条的AdjustmentListener,以便检测更改并重新绘制两者之间的线条。

请参阅: addAdjustmentListener method in the API

答案 2 :(得分:2)

你可以用它 http://java-sl.com/connector.html 作为此类代码的一个例子。