I am currently working on a Java Swing application. I want to use a JLayer
to decorate a JPanel
but get stuck.
Now I am going to add a JTextArea
into a JPanel
and then add the JPanel
into a JLayer
, and finally into a JScrollPane
. A JPanel
is a must because I want to add extra component beside the JTextArea
(The JTextArea
will be added to BorderLayout.CENTER
and the custom component, BorderLayout.LINE_START
). The problem is that JPanel
does not expand automatically but shrinks to (0, 0) size.
I have thought of some workarounds but they aren't quite suitable.
(1) Add a JScrollPane
into to the JLayer
and add the JLayer
into the top-level container directly. However the JLayer
also covers the JScrollPane
while I only want it to cover the JTextArea
.
(2) Avoid using a JPanel
and look for other ways to add a custom component beside the JTextArea
, but I couldn't think of any simple way to achieve it.
Here is the code:
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
public class Test
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
//add JLayer
JTextArea textArea = new JTextArea("JTextArea blah blah blah");
JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(Color.RED);
panel.add(textArea, BorderLayout.CENTER);
JLayer<JPanel> layer = new JLayer<JPanel>(panel, new LayerUI<JPanel>());
frame.add(new JScrollPane(layer), BorderLayout.CENTER);
//setup frame and show
frame.setSize(250,250);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
result:
My workaround (1):
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
public class Test
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
//add JLayer
JTextArea textArea = new JTextArea("JTextArea blah blah blah");
JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(Color.RED);
panel.add(textArea, BorderLayout.CENTER);
JLayer<JScrollPane> layer = new JLayer<JScrollPane>(new JScrollPane(panel), new LayerUI<JScrollPane>());
frame.add(layer, BorderLayout.CENTER);
//setup frame and show
frame.setSize(250,250);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
This seems to work but the JLayer
painting will cover the JScrollPane
's scroll bar which is not preferred.
(Example of covering the JScrollPane
: subclass LayerUI
:)
new LayerUI<JScrollPane>()
{
@Override
public void paint(Graphics g, JComponent c)
{
super.paint(g,c);
g.setColor(new Color(255,0,0,50));
g.fillRect(0,0,c.getWidth(),c.getHeight());
}
}
on scrolling (JScrollPane
covered by JLayer
):
So how to achieve a correct result? Thanks for solutions in advance.