Relleno interno para JTextArea con imagen de fondo

Mi objective final es tener un JTextArea con una imagen de fondo. Encontré código en línea que me mostró cómo hacer esto, pero ahora estoy teniendo un problema con el texto que está en la parte superior de la imagen.

Esto es lo que quiero decir:

Imagen superpuesta de texto

¿Hay alguna manera de que pueda agregar una especie de sangría hacia adentro para que el texto no se solape con los bordes de la imagen?


Aquí está la imagen de burbuja de comentario sin formato.

Burbuja de comentario


Aquí está el código:

 import java.awt.BorderLayout; import java.awt.Container; import java.awt.Graphics; import java.awt.Image; import javax.swing.GrayFilter; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; public class myBackgroundSample { String file; public myBackgroundSample(String i) { file = i; setItUp(); } public void setItUp() { final ImageIcon imageIcon = new ImageIcon(file); JTextArea textArea = new JTextArea() { Image image = imageIcon.getImage(); public void paint(Graphics g) { setOpaque(false); g.drawImage(image, 0, 0, this); super.paint(g); } }; JFrame frame = new JFrame("Background Example"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JScrollPane scrollPane = new JScrollPane(textArea); Container content = frame.getContentPane(); content.add(scrollPane, BorderLayout.CENTER); frame.setSize(400, 400); frame.setVisible(true); } public static void main(String[] args) { // TODO Auto-generated method stub String right = "chat1.jpg"; myBackgroundSample temp = new myBackgroundSample(right); } } 

Use un borde personalizado que extienda AbstractBorder . Algo como esto:

Borde de burbuja de texto

Obtener la forma y el color exactos se deja como un ejercicio para el lector. 🙂

 import java.awt.*; import java.awt.geom.*; import javax.swing.*; import javax.swing.border.AbstractBorder; class TextBubbleBorder extends AbstractBorder { private Color color; private int thickness = 4; private int radii = 8; private int pointerSize = 7; private Insets insets = null; private BasicStroke stroke = null; private int strokePad; private int pointerPad = 4; RenderingHints hints; TextBubbleBorder( Color color) { new TextBubbleBorder(color, 4, 8, 7); } TextBubbleBorder( Color color, int thickness, int radii, int pointerSize) { this.thickness = thickness; this.radii = radii; this.pointerSize = pointerSize; this.color = color; stroke = new BasicStroke(thickness); strokePad = thickness/2; hints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int pad = radii + strokePad; int bottomPad = pad + pointerSize + strokePad; insets = new Insets(pad,pad,bottomPad,pad); } @Override public Insets getBorderInsets(Component c) { return insets; } @Override public Insets getBorderInsets(Component c, Insets insets) { return getBorderInsets(c); } @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height) { Graphics2D g2 = (Graphics2D)g; int bottomLineY = height-thickness-pointerSize; RoundRectangle2D.Double bubble = new RoundRectangle2D.Double( 0+strokePad, 0+strokePad, width-thickness, bottomLineY, radii, radii ); Polygon pointer = new Polygon(); // left point pointer.addPoint( strokePad+radii+pointerPad, bottomLineY); // right point pointer.addPoint( strokePad+radii+pointerPad+pointerSize, bottomLineY); // bottom point pointer.addPoint( strokePad+radii+pointerPad+(pointerSize/2), height-strokePad); Area area = new Area(bubble); area.add(new Area(pointer)); g2.setRenderingHints(hints); Area spareSpace = new Area(new Rectangle(0,0,width,height)); spareSpace.subtract(area); g2.setClip(spareSpace); g2.clearRect(0,0,width,height); g2.setClip(null); g2.setColor(color); g2.setStroke(stroke); g2.draw(area); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { JLabel l = new JLabel( "The quick brown fox jumped over the lazy dog!"); l.setBorder(new TextBubbleBorder(Color.MAGENTA.darker(),2,4,0)); l.setOpaque(true); l.setBackground(Color.BLACK); JOptionPane.showMessageDialog(null, l); } }); } } 

Deberías usar un Border para eso, más específicamente deberías usar BorderFactory.createEmptyBorder(int top, int left, int bottom, int right) :

 textArea.setBorder(BorderFactory.createEmptyBorder(10,10,15,10)); 

También debe anular paintComponent lugar de paint . Además, use setRows() y setColumns() para establecer el tamaño del campo textArea, luego puede usar pack() lugar de setSize(400,400) que no es recomendable. Mira este ejemplo:

enter image description here

 import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextArea; public class Test extends JFrame { class MyTextArea extends JTextArea { public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.setColor(Color.PINK); g2.setStroke(new BasicStroke(4)); g2.drawRoundRect(3, 3, getWidth()-7, getHeight()-7, 5, 5); } } public Test() { JPanel panel = new JPanel(new BorderLayout()); JTextArea textArea = new MyTextArea(); textArea.setRows(3); textArea.setColumns(25); textArea.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); panel.add(textArea, BorderLayout.NORTH); add(panel); pack(); setDefaultCloseOperation(EXIT_ON_CLOSE); setVisible(true); } public static void main(String[] args) { new Test(); } } 

Para publicar el código , sangría cada línea por cuatro espacios.

Supongo que está anulando paintComponent() * para su JTextArea . Si es así, asegúrese de que sea transparente al agregar

 setOpaque(false); 

* Esto también funciona si anula la paint() , pero como dice correctamente el trashgod, eso interferiría con paintBorder() .

Una mejor versión de TextBubbleBorder.

https://gist.github.com/wenerme/6940534

  • control de relleno del puntero
  • control lateral del puntero
  • cambio dynamic