2012-09-12 12 views
6

線を描いてパネルを接続したいだけです。スイングで2つのパネルの間に線を描画するには

私は2つのパネルを持っており、両方のパネルにはJtableが含まれています.1つのパネルのjtableの各セルを別のjPanelの別のJtableに接続したいと思います。ここで

enter image description here

私はピンク色の円で強調しているようなラインを描きたいです。

、これは私がjtables

DefaultTableModel fcdbDataModel = new DefaultTableModel(fcdbIdTxnArray, 
    fcdbIdTxnColumnArray); 
fcdbIdTxnJTable = new FieldMapperJTable(fcdbDataModel); 

を作成するために使用していますコードスニペットで、ここでFieldMapperJTableは私のカスタマイズされたJTableのクラスです。

+0

他の方法を使用するには、どんなタイプのヘルプやアイデアもありがたいです。 –

+1

@Stanislavあなたの投稿のためにありがとうございます。これは私のために働いた。 "http://java-sl.com/connector.html" –

+0

なぜStaniの答えを削除したのだろうと思っています。投稿が本当に素敵で知識が得意だったのは間違いなく助かりました – kleopatra

答えて

8

JFrame/JDialog GlassPaneをペイントフィールドとして使用して簡単に行うことができます。カスタムコンポーネントをフレームのガラスペインとして設定し、リンクを直接ペイントしてください。

フレーム/ダイアログのレイヤードペインでも同じことができます。ここで

は、窓ガラス部品に、このような「リンク」を描画する方法の小さな作業例です:

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.HashMap; 
import java.util.Map; 

/** 
* @see http://stackoverflow.com/a/12389479/909085 
*/ 

public class ComponentLinkerTest extends JComponent 
{ 
    private Map<JComponent, JComponent> linked; 

    public ComponentLinkerTest() 
    { 
     super(); 
     linked = new HashMap<JComponent, JComponent>(); 
    } 

    public void link (JComponent c1, JComponent c2) 
    { 
     linked.put (c1, c2); 
     repaint(); 
    } 

    protected void paintComponent (Graphics g) 
    { 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

     g2d.setPaint (Color.BLACK); 
     for (JComponent c1 : linked.keySet()) 
     { 
      Point p1 = getRectCenter (getBoundsInWindow (c1)); 
      Point p2 = getRectCenter (getBoundsInWindow (linked.get (c1))); 
      g2d.drawLine (p1.x, p1.y, p2.x, p2.y); 
     } 
    } 

    private Point getRectCenter (Rectangle rect) 
    { 
     return new Point (rect.x + rect.width/2, rect.y + rect.height/2); 
    } 

    private Rectangle getBoundsInWindow (Component component) 
    { 
     return getRelativeBounds (component, getRootPaneAncestor (component)); 
    } 

    private Rectangle getRelativeBounds (Component component, Component relativeTo) 
    { 
     return new Rectangle (getRelativeLocation (component, relativeTo), 
       component.getSize()); 
    } 

    private Point getRelativeLocation (Component component, Component relativeTo) 
    { 
     Point los = component.getLocationOnScreen(); 
     Point rt = relativeTo.getLocationOnScreen(); 
     return new Point (los.x - rt.x, los.y - rt.y); 
    } 

    private JRootPane getRootPaneAncestor (Component c) 
    { 
     for (Container p = c.getParent(); p != null; p = p.getParent()) 
     { 
      if (p instanceof JRootPane) 
      { 
       return (JRootPane) p; 
      } 
     } 
     return null; 
    } 

    public boolean contains (int x, int y) 
    { 
     return false; 
    } 

    private static ComponentLinkerTest linker; 

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

     JFrame frame = new JFrame(); 

     linker = new ComponentLinkerTest(); 
     frame.setGlassPane (linker); 
     linker.setVisible (true); 

     JPanel content = new JPanel(); 
     content.setLayout (new GridLayout (10, 5, 5, 5)); 
     content.setBorder (BorderFactory.createEmptyBorder (5, 5, 5, 5)); 
     frame.add (content); 

     for (int i = 0; i < 50; i++) 
     { 
      final JButton button = new JButton ("Button" + i); 
      button.addActionListener (new ActionListener() 
      { 
       public void actionPerformed (ActionEvent e) 
       { 
        link (button); 
       } 
      }); 
      content.add (button); 
     } 

     frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo (null); 
     frame.setVisible (true); 
    } 

    private static JButton last = null; 

    private static void link (JButton button) 
    { 
     if (last == null) 
     { 
      last = button; 
     } 
     else 
     { 
      linker.link (last, button); 
      last = null; 
     } 
    } 

    private static void setupLookAndFeel() 
    { 
     try 
     { 
      UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName()); 
     } 
     catch (ClassNotFoundException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (InstantiationException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (IllegalAccessException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (UnsupportedLookAndFeelException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

そして結果:
(ちょうど任意の二つのボタンを次々にクリックして、彼らが取得しますリンクされた)
enter image description here

PS線を太くするには、絵を描くときにストロークを変更することができます。

g2d.setStroke (new BasicStroke (5f)); 
+0

これはまだ適用されているのかどうかはわかりませんが、Swingが新しく輝いていた頃には、glasspaneを使用しようとしたときにイベントを処理するのに多くの問題がありました。 –

+0

+1コンポーネントの上にレンダリングするだけでなく、魅力的なコメントスタイル。 :-) – trashgod

+0

@ JensSchauderはい、問題はありません。ガラス板に何かイベントを処理させたいのであれば問題はありませんが、実際には小さな困難です。とにかく、それは私がガラスペインコンポーネントの "contains"メソッドをオーバーライドする理由です。 falseを返す場合(または線の形で制限する場合)、イベントをどこでも吸収することはできません(または形状境界内だけでも問題ありません)。 –

関連する問題