Border painting components as part of the border?

I wonder, if anyone knows about limitations or tricks on using Swing components as part of a border. While this worked quite well with a JLabel (the label's paint will be called when painting the border), using a JPanel instead seems not to work (the panel's children don't get painted, and the panel's position is off).

The following resembles the paint routine as used for a JLabel within a border:

publicvoid paintBorder(Component c, Graphics g,int x,int y,int width,int height){

g.setColor(c1);

g.drawRect(x, y, width - 1, height - 1);

g.setColor(c2);

g.fillRect(x + 1, y + 1, width - 2, label.getPreferredSize().height + 10);

Graphics g2 = g.create(x + 10, y + 5, width - 15, label.getPreferredSize().height);

label.setBounds(x + 10, y + 5, width - 15, label.getPreferredSize().height - 1);

label.paint(g2);

}

Any idea why JPanel doesn't work using the same approach?

Thanks.

[1227 byte] By [stefan.schulza] at [2007-11-27 10:04:22]
# 1

Try this class on for size. I believe the difference is with the SwingUtilities.paintComponent method, that handles the painting of the added component rather than doing it manually. It does the painting alright but I believe it has a few bugs you can work out.

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import java.net.*;

import java.util.*;

import javax.swing.*;

import javax.swing.border.*;

import javax.swing.event.*;

import javax.swing.table.*;

public class ComponentTitledBorder implements Border, MouseListener, SwingConstants{

int offset = 5;

Component comp;

JComponent container;

Rectangle rect;

Border border;

public ComponentTitledBorder(Component comp, JComponent container, Border border){

this.comp = comp;

this.container = container;

this.border = border;

container.addMouseListener(this);

}

public boolean isBorderOpaque(){

return true;

}

public void paintBorder(Component c, Graphics g, int x, int y, int width, int height){

Insets borderInsets = border.getBorderInsets(c);

Insets insets = getBorderInsets(c);

int temp = (insets.top-borderInsets.top)/2;

border.paintBorder(c, g, x, y+temp, width, height-temp);

Dimension size = comp.getPreferredSize();

rect = new Rectangle(offset, 0, size.width, size.height);

SwingUtilities.paintComponent(g, comp, (Container)c, rect);

}

public Insets getBorderInsets(Component c){

Dimension size = comp.getPreferredSize();

Insets insets = border.getBorderInsets(c);

insets.top = Math.max(insets.top, size.height);

return insets;

}

private void dispatchEvent(MouseEvent me){

if(rect!=null && rect.contains(me.getX(), me.getY())){

Point pt = me.getPoint();

pt.translate(-offset, 0);

comp.setBounds(rect);

comp.dispatchEvent(new MouseEvent(comp, me.getID()

, me.getWhen(), me.getModifiers()

, pt.x, pt.y, me.getClickCount()

, me.isPopupTrigger(), me.getButton()));

if(!comp.isValid())

container.repaint();

}

}

public void mouseClicked(MouseEvent me){

dispatchEvent(me);

}

public void mouseEntered(MouseEvent me){

dispatchEvent(me);

}

public void mouseExited(MouseEvent me){

dispatchEvent(me);

}

public void mousePressed(MouseEvent me){

dispatchEvent(me);

}

public void mouseReleased(MouseEvent me){

dispatchEvent(me);

}

}

ICE

icewalker2ga at 2007-7-13 0:39:23 > top of Java-index,Desktop,Core GUI APIs...
# 2

Thanks for the help. Unfortunately, the paintComponent method does not get it completely right, either, when using a JPanel. It solved some problems with double painting, but didn't correctly paint its children.

I replaced the Border with a Panel now. It's a bit more expensive to do, but at least works as desired.

Thanks anyway. :)

stefan.schulza at 2007-7-13 0:39:23 > top of Java-index,Desktop,Core GUI APIs...