在 1 个 JPanel 中的 2 个图像之间绘图

发布于 2024-11-19 01:13:01 字数 295 浏览 3 评论 0原文

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

编辑

我想在两个图像之间绘制 - 通过组件 - 从图像中获取一些点并在它们之间绘制线条。对于问题表述不当,我深表歉意。

I want to draw the lines between 2 JScrollPanes (first scroll pane on the left side, second on the right). These JScrollPanes contain images. I want to draw lines between these 2 images (use some layers, use some trick etc.). I tried do it different ways, but i failed. Is it possible? (if not, i will have to make 2 images in one JScrollPane and it won't be nice).

EDIT

I want to draw between 2 images - throught components - get some points from images and draw lines between them. I apologize for poorly formulated question.

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

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

发布评论

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

评论(3

情深已缘浅 2024-11-26 01:13:01

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

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

我相信第二个功能可以解决您的问题。以下是一个示例实现,您可以稍后对其进行定制以满足您自己的需求。请注意,我遗漏了许多有关 Glass Pane 的细节,您需要自己研究。

代码

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

输出

在此处输入图像描述

说明

中,我单击每个 JLabel 内的任意两个点,然后绘制一条连接线。

In order to accomplish this, I believe you'll need to make use of the Glass Pane. The Glass Pane sits on top of everything in the JRootPane and fills the entire view. This particular position allows two distinct capabilities:

  • Intercepting mouse and keyboard events
  • Drawing over the entire user interface

I believe your question is addressed by the second capability. The following is an example implementation, which you can later tailor to meet your own needs. Note that I've left out a lot of detail with regard to Glass Pane that you'll need to research on your own.

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

OUTPUT

enter image description here

EXPLANATION

In this example, I clicked two arbitrary points within each JLabel, and then drew a connecting line.

梦断已成空 2024-11-26 01:13:01

这应该是很有可能的。您将需要创建一个可识别两个垂直滚动条的自定义组件。它应该将自身作为 AdjustmentListener 添加到每个滚动条,以便检测更改并重新绘制两者之间的线条。

看:
addAdjustmentListener API 中的方法

This should be very possible. You will need to create a custom component that is aware of both vertical ScrollBars. It should add itself as an AdjustmentListener to each scroll bar in order to detect changes and repaint the lines between the two.

See:
addAdjustmentListener method in the API

半衬遮猫 2024-11-26 01:13:01

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

You can use this
http://java-sl.com/connector.html
as an example of such code.

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