Creating a Bordered Panel in JavaFX

Saturday, August 22nd, 2009

Recently I was looking for an easy, relatively general way to visually separate arbitrary groups of components with a border. Behold the BorderPanel:

BorderPanel is simply a CustomNode that wraps any number of nodes in a Panel (which is a custom layout Container), and sticks a border around it.

Here would be the code to generate the above layout (assuming that the widgets were contained within the “vbox” object:

BorderPanel {
  borderColor: Color.DARKSLATEGRAY
  borderWidth:10
  layoutPadding: 10
  content: [ vbox ]
}

The above layout is alright, but really I wanted it to put a border around some AnimatedCharts from the previous post:

Since I can put a border around anything now though, separating groups of charts is pretty straight forward:

Which is just two BorderPanels contained in an HBox:

HBox {
content: [
  BorderPanel {
    content: HBox { content: [chart,chart1] }
  },
  BorderPanel {
    content: HBox {content: [chart2] }
  }
 ]
}

BorderPanel itself is pretty small. Here’s the create function:

override public function create():Node {
  panel = Panel {
    content: bind [border, content]
    onLayout: function() {
      for (c in content) {
        c.layoutX = borderWidth + layoutPadding;
        c.layoutY = borderWidth + layoutPadding;
      }
      updateBorder();
    }
  }
}

It simply creates the wrapper panel, “prepending” the border to the user added content (so that it always appears behind the components). The “onLayout” function is defined to move the “layoutX/Y” of each component out of the way of the border, plus some user-defined padding.

Here’s the function which creates the border, which is called whenever any of the dependent variables are updated.

function updateBorder() {
  var width = panel.width + borderWidth * 2 + layoutPadding * 2;
  var height = panel.height + borderWidth * 2 + layoutPadding * 2;
  var rect = Rectangle {
    width: width
    height: height
  }
  var innerRect = Rectangle {
    width: width - borderWidth * 2
    height: height - borderWidth * 2
    x: borderWidth
    y: borderWidth
    arcWidth: 30
    arcHeight: 30
  }
  border = ShapeSubtract {
    fill: borderColor
    a: rect
    b: innerRect
    effect: DropShadow {}
  }
}

The border itself is a shape subtraction of a rounded rectangle from a larger rectangle which encompasses the size of the entire panel. There is also a drop shadow added to give a subtle sense of depth.

The idea of creating a border that looks like this was actually inspired by this year’s Extreme GUI Makeover at JavaOne, which featured an Email client written partly in JavaFX.

Tags:

6 Responses to “Creating a Bordered Panel in JavaFX”

  1. William Antônio wrote:
    August 22nd, 2009 at 9:51 pm |

    nice!!
    New component to JFXtras??

  2. Stephen Chin wrote:
    August 23rd, 2009 at 1:51 am |

    Ditto William’s sentiments… very nice!

    We already have a border framework in JFXtras with lines, text, pipes, shapes, etc. This would make a great addition if you would be interested in contributing it to our next release.

  3. sanderson wrote:
    August 23rd, 2009 at 10:37 am |

    @Stephen and @William — Whoops, I didn’t know about the Borders in JXTras — and you even blogged about it to boot.

    I’d be happy to contribute this, but I’ll have to check out the border package in JFXtras to see something like this isn’t already there.

  4. William Antônio wrote:
    August 23rd, 2009 at 8:09 pm |

    Yes, i know, but this could be a new bordered panel! =D

  5. Charles Tam wrote:
    August 24th, 2009 at 9:17 pm |

    Thanks Sten for sharing your ideas and examples.

  6. Jim Weaver wrote:
    August 26th, 2009 at 8:12 am |

    Yes, it would definitely be a great addition to JFXtras. Nice work, Sten!

    Jim Weaver

Leave a Reply