JavaFX does not seem to have support for scroll views. So, you have to
implement it on your own. Here is how I started implementing my own scroll view supporting
vertical scrolling:
package scrollviewdemo; import javafx.scene.CustomNode; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.control.ScrollBar; import javafx.util.Math; import javafx.scene.shape.Rectangle; import javafx.scene.paint.Paint; public class ScrollView extends CustomNode { public-init var node: Node; public var width: Float; public var height: Float; var group: Group; var gap = bind group.layoutBounds.height - height; def scrollBar: ScrollBar = ScrollBar { translateX: bind width - scrollBar.width min: 0 max: bind Math.max(0, gap) visible: bind gap > 0 vertical: true height: bind height } override function create() { Group { content: [ Group { content: [ group = Group { translateY: bind - scrollBar.value content: [node] } ] clip: Rectangle { width: bind width - {if (gap > 0) scrollBar.width else 0} height: bind height } }, scrollBar ] } } }
This is how it can be used in a simple application:
var stage: Stage = Stage { title: "Application title" width: 200 height: 200 scene: Scene { content: [ ScrollView { width: bind stage.scene.width height: bind stage.scene.height node: VBox { content: for (i in [0..20]) ImageView { image: Image { // some picture url: "{__DIR__}pic.png" } } } } ] } }
To support mouse scroll wheel I added the following to the ScrollView class:
override var onMouseWheelMoved = function(event) { // multiplying by 4 makes the scrolling faster and still smooth scrollBar.value += event.wheelRotation * 4; }
However, as it turned out, transparent components don’t receive mouse events, so the mouse
wheel worked only when the mouse pointer was on top of a non-transparent object. So, to work
around this, I had to fill the scroll view background using an opaque rectangle. The resulting
ScrollView component looks like this:
package scrollviewdemo; import javafx.scene.CustomNode; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.control.ScrollBar; import javafx.util.Math; import javafx.scene.shape.Rectangle; import javafx.scene.paint.Paint; public class ScrollView extends CustomNode { public-init var node: Node; public var width: Float; public var height: Float; public var fill: Paint; var group: Group; var gap = bind group.layoutBounds.height - height; def scrollBar: ScrollBar = ScrollBar { translateX: bind width - scrollBar.width min: 0 max: bind Math.max(0, gap) visible: bind gap > 0 vertical: true height: bind height } override function create() { Group { content: [ Rectangle { fill: bind fill width: bind width - {if (gap > 0) scrollBar.width else 0} height: bind height }, Group { content: [ group = Group { translateY: bind - scrollBar.value content: [node] } ] clip: Rectangle { width: bind width - {if (gap > 0) scrollBar.width else 0} height: bind height } }, scrollBar ] } } override var onMouseWheelMoved = function(event) { // multiplying by 4 makes the scrolling faster and still smooth scrollBar.value += event.wheelRotation * 4; } }
And the following line should be added to the Main.fx to make it work:
package scrollviewdemo; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.layout.VBox; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.paint.Color; var stage: Stage = Stage { title: "Application title" width: 200 height: 200 scene: Scene { content: [ ScrollView { width: bind stage.scene.width height: bind stage.scene.height fill: Color.WHITE node: VBox { content: for (i in [0..20]) ImageView { image: Image { // some picture url: "{__DIR__}pic.png" } } } } ] } }
Nice work, Martin. You might want to look at the javafx.scene.layout.ClipView class as well.
Thanks,
Jim Weaver
add please coordinates X,Y
public class ScrollView extends CustomNode {
…
public var x:Float; //<— add
public var y:Float; //<— add
…
override function create() {
Group {translateX: bind x translateY:bind y //<— add
…
__________
Thanks!
i was wondering reusing the Swing ScrollPanes was no option?
AFAIK should be possible to use Swing Components via SwingComponent.wrap(new JComponent) or so.
But ofc kudos to your work. good to see some usefull programming on javaFX instead of some flashy nothing :-)
Thanks a lot!
Its great
Amazing, I’m exchanging my Sun’s blog interest by this one.
hi! thanks a lot !! its amazing!!
actually , i’m implementing a mobile aplication .. i’m trying to use this code but i block because i can’t move the scrollBar from the keybord :(((
would you pleaz help me .. it would be nice