更新时间:2022-10-17 22:02:25
使用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://***.com/a/12389479/909085
* /
公共类ComponentLinkerTest扩展了JComponent
{
私人地图< JComponent,JComponent>链接;
公共ComponentLinkerTest()
{
super();
linked = new HashMap< JComponent,JComponent> ();
}
public void link(JComponent c1,JComponent c2)
{
linked.put(c1,c2);
repaint();
}
保护void paintComponent(Graphics g)
{
Graphics2D g2d =(Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(Color.BLACK); (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)
{
返回新的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();
返回新的Point(los.x - rt.x,los.y - rt.y);
私有JRootPane getRootPaneAncestor(Component c)
{
for(Container p = c.getParent(); p!= null; p = p.getParent ())
{
if(p instanceof JRootPane)
{
return(JRootPane)p;
}
}
返回null;
public boolean contains(int x,int y)
{
return false;
}
私有静态ComponentLinkerTest链接器;
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 {
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();
}
}
}
结果: >
(只需点击任意两个按钮,它们就会被链接)
PS为了使线条变粗,可以在绘画时更改笔画:
g2d.setStroke(new BasicStroke(5f));
Just want to connect panels by drawing a line b/w them.
I am having two panels and both panels contains a Jtable.I want to connect each cell of jtable of one panel to another Jtable of another jpanel.
Here i want to draw the lines like that i have highlighted by pink color circle.
and this is the code snippet i am using to create jtables
DefaultTableModel fcdbDataModel = new DefaultTableModel(fcdbIdTxnArray,
fcdbIdTxnColumnArray);
fcdbIdTxnJTable = new FieldMapperJTable(fcdbDataModel);
here FieldMapperJTable is my customized jtable class.
You could easily do that using JFrame/JDialog GlassPane as the painting field. Just set your custom component as a glass pane for the frame and paint the link directly on it.
You can also do the same using the layered pane of the frame/dialog.
Here is a small working example of how to draw such "links" on the glass pane component:
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://***.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 ();
}
}
}
And the result:
(just click any two buttons one after another and they will get linked)
P.S. To make the lines thicker you can change the stroke when painting:
g2d.setStroke ( new BasicStroke ( 5f ) );