2011-07-07 158 views
3

我想繪製2 JScrollPanes(左側第一個滾動窗格,右側第二個)之間的線條。這些JScrollPanes包含圖像。我想在這兩個圖像之間畫線(使用一些圖層,使用一些技巧等)。我嘗試過不同的方式,但我失敗了。可能嗎? (如果沒有,我將不得不在一個JScrollPane中製作2張圖片,這樣會不太好)。在1個圖像之間繪製2個圖像JPanel

編輯

我想2個圖像之間畫 - throught部件 - 從圖像中獲得一些積分,並在二者之間畫線。對於質量差的問題,我表示歉意。

+1

我相信你需要做的是在玻璃窗上畫畫。我會盡快編輯我的答案以反映這一點。 – mre

回答

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

OUTPUT

enter image description here

說明

在這個例子中,我每個內點擊兩個任意點,然後畫了一條連線。

+0

如果這真的有效......那麼我今天學到了一些新東西:D,雖然我們應該在我們的優先方法中調用'drawChilderen'或類似的東西。 +1 –

+0

@Martijn,是的,這真的很有用。 :) – mre

+0

謝謝,但這隻適用於'Component',分別連接'Component'。我需要通過'JScrollPane'畫線。我從圖像中獲得一些點,並且我想連接它們。這個例子不適用於此。 – Equo

2

這應該是非常可能的。您需要創建一個可以識別兩個垂直滾動條的自定義組件。它應該將自身作爲AdjustmentListener添加到每個滾動條,以便檢測更改並重新繪製兩者之間的線條。

請參見: addAdjustmentListener method in the API