Java L&F 定制:如何使用 Synth 定制 BorderFactory 边框?

发布于 2024-07-07 15:55:47 字数 1271 浏览 15 评论 0原文

具体来说,我目前有一个带有 TitledBorder 的 JPanel。 我想自定义边框的外观。 在我的应用程序的当前状态下,绘制了标题,但没有绘制线条边框本身。

如果我将 imagePainter 绑定到 Panel 对象的 panelBorder 方法,我可以在面板周围放置一个自定义图像 - 但是它只显示在那些我没有在代码中显式设置边框的面板上。 该代码如下所示:

<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" />

我怎样才能做相反的事情——也就是说,使这个自定义图像仅显示在我应用了 TitledBorder 的面板上?

我还尝试使用命名面板:

panel.setName("MyPanel")

和名称绑定:

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

这允许我仅更改特定面板的样式,这很好。 但是,它并没有解决最初的问题:我仍然无法自定义面板的 NamedBorder。

如果我指定 NamedBorder,我的 PanelBorder 画家将被忽略,并且仅打印名称。 如果我拿走我的 NamedBorder,我可以使用我的自定义边框图形,但随后我必须戳戳我的布局才能在标题之前所在的位置获得 JLabel,这是不可取的。

进一步的研究发现,没有渲染线条的原因是 TitledBorder 的构造函数采用另一个 Border 的参数,除了标题之外,它还渲染该边框。 我没有传递这个参数,默认值取决于您选择的 L&F。 当我使用 System L&F 时,默认值是 LineBorder。 显然 Synth 的默认值是 EmptyBorder。 显式指定 LineBorder 可以让我恢复线条,这解决了我的大部分问题。

我的问题的其余部分涉及使用 LineBorder 的自定义图形。 现在,我将自定义图形渲染为第二个 PanelBackground 图像 - 它合成在实际背景之上并实现所需的视觉效果,尽管这不是理想的实现。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

德意的啸 2024-07-14 15:55:47

指定要应用特殊样式的组件的名称,而不是区域:

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

在 Java 代码中,您需要设置组件的名称以匹配您在 XML 中提供的名称:

panel.setName("mySpecialPanel");

您可以考虑扩展 JPanel,以便所有面板都具有相同的名称:

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

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");    
   } 
}
怎言笑 2024-07-14 15:55:47

哈,原因明白了。
来自 TitledBorder.getBorder,如果使用合成器外观。 TitledBorder.border 应在 xml 文件中定义。

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

所以我的答案是:

<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"/>

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"/>
生生不灭 2024-07-14 15:55:47

我们有同样的问题。 当然,您的解决方法(如上所述)有效,但它不是解决方案。

我们使用的解决方法是:

而不是:

BorderFactory.createTitledBorder("title");

您应该使用:

Border objBorder = BorderFactory.createLineBorder(Color.black); 
//Also you can create all the rest of the borders here.
BorderFactory.createTitledBorder(objBorder, "title");

We had the same problem. Of course your workaround (which you described above) works but it is not a solution.

The workaround we used is:

Instead of:

BorderFactory.createTitledBorder("title");

You should use:

Border objBorder = BorderFactory.createLineBorder(Color.black); 
//Also you can create all the rest of the borders here.
BorderFactory.createTitledBorder(objBorder, "title");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文