I put a JTextArea in a JPanel. This JPanel has a picture on the background, and the JTextArea is translucent (translucid red) to show the background through. I don't want the user to be able to edit or select the text, I want it to act just as a JLabel (but with multiple lines and easy to word wrap and adjust to screen resize).
I tried all these options:
text.setEditable(false);
text.setFocusable(false);
text.setEnabled(false);
text.setHighlighter(null);
but still some change of color happens as the user drags the mouse over the JTextArea. Anyone knows what is going on?
You can't simply set the background color of a component to "transparent" and expect Swing to deal with it. You need to flag the component as transparent (setOpaque(false)
), only then will Swing's repaint manager know that it has to update the components under it.
This then leads you to the problem of how to paint the background (as Swing only has the concept of fully opaque or fully transparent).
To do this, you need to supply your own paint routines (override paintComponent
, fill the background, update the component)...this is essentially what Rob Camick's solution is doing, it just provides a nice wrapper component for you...
Below is an example of using a JLabel
using text wrapped in HTML and a JTextArea
, both updated to support "translucency"...
Using a JLabel
Using a JTextArea
Now, it would be a lot easier to achieve using Rob's wrapper class, but this provides you with the idea of what is going wrong and what you would need to do to fix it.
public class MultiLineLabel {
public static void main(String[] args) {
new MultiLineLabel();
}
public MultiLineLabel() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BackgroundPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TransclucentLabel extends JLabel {
public TransclucentLabel(String text) {
super(text);
setVerticalAlignment(TOP);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Insets insets = getInsets();
int x = insets.left;
int y = insets.top;
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.top + insets.bottom);
g2d.setColor(new Color(255, 0, 0, 128));
g2d.fillRect(x, y, width, height);
super.paintComponent(g);
}
}
public class TransclucentTextArea extends JTextArea {
public TransclucentTextArea(String text) {
super(text);
setOpaque(false);
setLineWrap(true);
setWrapStyleWord(true);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Insets insets = getInsets();
int x = insets.left;
int y = insets.top;
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.top + insets.bottom);
g2d.setColor(new Color(255, 0, 0, 128));
g2d.fillRect(x, y, width, height);
super.paintComponent(g);
}
}
public class BackgroundPane extends JPanel {
private BufferedImage background;
public BackgroundPane() {
setLayout(new BorderLayout());
// addLabel();
addTextArea();
setBorder(new EmptyBorder(24, 24, 24, 24));
try {
background = ImageIO.read(new File("/path/to/your/image"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
protected void addTextArea() {
StringBuilder sb = new StringBuilder(128);
sb.append("I put a JTextArea in a JPanel. This JPanel has a picture on the background, and the JTextArea is translucent (translucid red) to show the background through. I don't want the user to be able to edit or select the text, I want it to act just as a JLabel (but with multiple lines and easy to word wrap and adjust to screen resize).\n\n");
sb.append("I tried all these options:\n\n");
sb.append("text.setEditable(false);\n");
sb.append("text.setFocusable(false);\n");
sb.append("text.setEnabled(false);\n");
sb.append("text.setHighlighter(null);\n\n");
sb.append("but still some change of color happens as the user drags the mouse over the JTextArea. Anyone knows what is going on?\n");
add(new TransclucentTextArea(sb.toString()));
}
protected void addLabel() {
StringBuilder sb = new StringBuilder(128);
sb.append("<html>");
sb.append("<p>I put a JTextArea in a JPanel. This JPanel has a picture on the background, and the JTextArea is translucent (translucid red) to show the background through. I don't want the user to be able to edit or select the text, I want it to act just as a JLabel (but with multiple lines and easy to word wrap and adjust to screen resize).</p><br>");
sb.append("<p>I tried all these options:</p><br>");
sb.append("<p>text.setEditable(false);<br>");
sb.append("text.setFocusable(false);<br>");
sb.append("text.setEnabled(false);<br>");
sb.append("text.setHighlighter(null);</p><br>");
sb.append("<p>but still some change of color happens as the user drags the mouse over the JTextArea. Anyone knows what is going on?</p>");
add(new TransclucentLabel(sb.toString()));
}
@Override
public Dimension getPreferredSize() {
return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g.drawImage(background, x, y, this);
}
}
}
}