views:

1269

answers:

4

Specifically, I currently have a JPanel with a TitledBorder. I want to customize the look of the border. In my app's current state, the title is drawn, but not the line border itself.

If I bind an imagePainter to the panelBorder method for Panel objects, I can put a custom image around panels -- however it only shows up on those panels that I haven't explicitly set the border on in the code. Here's what that code looks like:

<style id="PanelStyle">
    <state>
        <imagePainter method="panelBorder" path="images/thick border.png" sourceInsets="3 3 3 3" />
    </state>
</style>
<bind style="PanelStyle" type="region" key="Panel" />

How can I do the opposite -- that is, make this custom image only show up on panels I've applied a TitledBorder to?

I have also tried using a named panel:

panel.setName("MyPanel")

and a name binding:

<bind style="PanelStyle" type="name" key="MyPanel">

This allows me to change the style of only particular panels, which is good. However, it does not solve the original problem: I still can't customize my panel's NamedBorder.

If I specify a NamedBorder, my PanelBorder painter is ignored, and just the name is printed. If I take away my NamedBorder, I can use my custom border graphic, but then I have to poke and prod my layout to get a JLabel in the same place that the title was previously, which is undesirable.

Further research has uncovered that the reason there is no rendered line is that TitledBorder's constructor takes an argument of another Border, which it renders in addition to the title. I was not passing this argument, and the default depends on your selected L&F. Back when I was using the System L&F, the default was a LineBorder. Apparently Synth's default is an EmptyBorder. Explicitly specifying the LineBorder gets me the line back, which solves most of my problem.

The rest of my problem involves using a custom graphic for the LineBorder. For now I'm getting by rendering my custom graphic as a second PanelBackground image -- it gets composited on top of the actual background and achieves the desired visual effect, though it's not the ideal implementation.

+1  A: 

Specify the name of the component you want to apply the special style to, not the region:

<bind style="PanelStyle" type="name" key="mySpecialPanel" />

In your Java code, you'll need to set the component's name to match the name you supplied in the XML:

panel.setName("mySpecialPanel");

You might consider extending JPanel so that all panels have the same name:

public class MySpecialPanel extends JPanel 
{    
   public MySpecialPanel(String title) 
   {
       super(title);
       this.setName("mySpecialPanel");    
   } 
}
SpooneyDinosaur
A: 

Hi :) We had the same problem. Ofcourse your work a round (you described above) works but it is not a solution.

The work a round we used is:

Instaed:

BorderFactory.createTitledBorder("title");

You should use:

Border objBorder = BorderFactory.createLineBorder(Color.black); //Also u can create all the rest borders here.

BorderFactory.createTitledBorder(objBorder, "title");

A: 

ivo_zlatev, it works. Can you please explain the reason, thank you

cherishchen
A: 

ha, got the reason. From TitledBorder.getBorder, if synth look and feel is used. TitledBorder.border should be defined in the xml file.

public Border getBorder()       {       
    Border b = border;
if (b == null)
    b = UIManager.getBorder("TitledBorder.border");
    return b; 
}

so my answer is:

<object id="TitledBorder_Color" class="java.awt.Color">
  <int>140</int>

  <int>125</int>

  <int>100</int>

  <int>255</int>
 </object>

 <object id="LineBorder" class="javax.swing.border.LineBorder">
  <object idref="TitledBorder_Color"/>
 </object>

 <defaultsProperty key="TitledBorder.border" type="idref" value="LineBorder"/>
cherishchen