JavaFX has new layout - ClipView - which can be used to implement scroll or pannable view.

We can set a node to ClipView which needs to be clipped and shown. The clip area can be controlled by specifying attributes - clipX and clipY. ClipView can also handle panning using mouse, which can enabled using pannable attribute.

For Applet mode, click on above image

For standalone mode

In above sample a large image is added to ImageView, which in-turn is added to ClipView. The clipX and clipY attributes are bound to horizontal and vertical ScrollBars. The clip rectangle can be updated by moving the scrollbars.

var scrollClipView : ClipView = ClipView {
    clipX: bind hScroll.value
    clipY: bind vScroll.value
    node: imageView
    pannable: false
    layoutInfo: LayoutInfo {
        width: 300
        height: 200
    }
}

The second ImageView is again added to ClipView. This time clipX and clipY are not bound to scrollbars. Instead the pannable attribute is set to true. User can move the image using mouse.

Try it out and let me know feedback!

Source:

Comments:

Great layout, something to add to the FXExtra's project?

Posted by Tom on July 06, 2009 at 02:37 PM IST #

@Tom ClipView is available in JavaFX 1.2 http://java.sun.com/javafx/1.2/docs/api/javafx.scene.layout/javafx.scene.layout.ClipView.html

Posted by Rakesh Menon on July 06, 2009 at 02:54 PM IST #

Nice example. When you make the main window resizable the ClipView will not change and keep it's size of 300x200. How to make the ClipView resize with the main window.
If I delete the layoutInfo, the content of the panel will resize with the main window. But is not pannable anymore (even if pannable is set to true).

Posted by Tim on July 13, 2009 at 03:25 PM IST #

@Tim You can bind the width and height of LayoutInfo of ClipView to scene.width and scene.height

Posted by Rakesh Menon on July 14, 2009 at 09:39 AM IST #

Good example Rakesh, thanks for your efforts.
I have a question regarding ClipView: I have ListViews in a HBox and number of ListViews changes during runtime. I assigned node property of a ClipView to the HBox and succesfully bound width of the ClipView to width of the layoutInfo of the scene. The problem is that I couldn't make my horizontal scrollbar recalculate its max value when number of ListViews change...
I tried binding max value to width of the HBox, but that didn't work. Binding max to total width of ListViews didn't work either. Currently I'm stuck with this. Any help is appreciated.

Posted by Abdullah on August 24, 2009 at 01:25 PM IST #

@Abdullah Your requirement sound similar to the scroll-view items displayed in another sample
http://blogs.sun.com/rakeshmenonp/entry/javafx_drag_and_drop

In Main.fx it binds the scrollbar max value to
Math.max(hBox.boundsInLocal.width - <width of scrollbar>, 1)

Hope this helps..

Posted by Rakesh Menon on August 25, 2009 at 10:47 AM IST #

Hi Rakesh, I'm running JFX 1.2.1, and experiencing runtime problem as below.
init:
deps-jar:
compile:
jar:
standard-run:
Exception in trigger:
com.sun.javafx.runtime.AssignToBoundException: Cannot assign to bound variable
at com.sun.javafx.runtime.location.FloatVariable.setAsFloat(FloatVariable.java:111)
at javafx.scene.layout.ClipView.set$clipX(ClipView.fx:52)
at javafx.scene.layout.ClipView$_SBECL.onChange(ClipView.fx:54)
at com.sun.javafx.runtime.location.FloatVariable.notifyListeners(FloatVariable.java:146)
at com.sun.javafx.runtime.location.FloatVariable.replaceValue(FloatVariable.java:94)
at com.sun.javafx.runtime.location.AbstractBindingExpression.pushValue(AbstractBindingExpression.java:94)
at com.sun.javafx.runtime.location.AbstractBindingExpression.pushFrom(AbstractBindingExpression.java:107)
at com.sun.javafx.runtime.location.Locations$7.compute(Locations.java:283)
at com.sun.javafx.runtime.location.AbstractVariable.update(AbstractVariable.java:128)
at com.sun.javafx.runtime.location.AbstractVariable.ensureValid(AbstractVariable.java:163)
at com.sun.javafx.runtime.location.FloatVariable.getAsFloat(FloatVariable.java:177)
at javafx.scene.layout.ClipView$_SBECL.compute(ClipView.fx:207)
at com.sun.javafx.runtime.location.AbstractVariable.update(AbstractVariable.java:128)
at com.sun.javafx.runtime.location.AbstractVariable.invalidate(AbstractVariable.java:142)
at com.sun.javafx.runtime.location.AbstractLocation$2.onAction(AbstractLocation.java:234)
at com.sun.javafx.runtime.location.AbstractLocation$2.onAction(AbstractLocation.java:228)
at com.sun.javafx.runtime.location.AbstractLocation.iterateChildren(AbstractLocation.java:181)
at com.sun.javafx.runtime.location.AbstractLocation.invalidateDependencies(AbstractLocation.java:254)
at com.sun.javafx.runtime.location.AbstractLocation.invalidate(AbstractLocation.java:108)
at com.sun.javafx.runtime.location.AbstractVariable.invalidate(AbstractVariable.java:140)
at com.sun.javafx.runtime.location.AbstractLocation$2.onAction(AbstractLocation.java:234)
at com.sun.javafx.runtime.location.AbstractLocation$2.onAction(AbstractLocation.java:228)
at com.sun.javafx.runtime.location.AbstractLocation.iterateChildren(AbstractLocation.java:181)
at com.sun.javafx.runtime.location.AbstractLocation.invalidateDependencies(AbstractLocation.java:254)
at com.sun.javafx.runtime.location.ObjectVariable.notifyListeners(ObjectVariable.java:142)
at com.sun.javafx.runtime.location.ObjectVariable.replaceValue(ObjectVariable.java:110)
at com.sun.javafx.runtime.location.ObjectVariable.set(ObjectVariable.java:121)
at clipview.Main.set$hScroll(Main.fx:66)
at clipview.Main.set$hScroll(Main.fx:66)
at clipview.Main.javafx$run$(Main.fx:66)
at clipview.Main.javafx$run$(Main.fx:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.javafx.runtime.provider.GUIRuntimeProvider$1.run(GUIRuntimeProvider.java:65)
at com.sun.javafx.tk.swing.SwingToolkit$StartupRoutine.run(SwingToolkit.fx:593)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Exception in trigger:
com.sun.javafx.runtime.AssignToBoundException: Cannot assign to bound variable
at com.sun.javafx.runtime.location.FloatVariable.setAsFloat(FloatVariable.java:111)
at javafx.scene.layout.ClipView.set$clipY(ClipView.fx:66)
at javafx.scene.layout.ClipView$_SBECL.onChange(ClipView.fx:68)
at com.sun.javafx.runtime.location.FloatVariable.notifyListeners(FloatVariable.java:146)
at com.sun.javafx.runtime.location.FloatVariable.replaceValue(FloatVariable.java:94)
at com.sun.javafx.runtime.location.AbstractBindingExpression.pushValue(AbstractBindingExpression.java:94)
at com.sun.javafx.runtime.location.AbstractBindingExpression.pushFrom(AbstractBindingExpression.java:107)
at com.sun.javafx.runtime.location.Locations$7.compute(Locations.java:283)
at com.sun.javafx.runtime.location.AbstractVariable.update(AbstractVariable.java:128)
at com.sun.javafx.runtime.location.AbstractVariable.ensureValid(AbstractVariable.java:163)
at com.sun.javafx.runtime.location.FloatVariable.getAsFloat(FloatVariable.java:177)
at javafx.scene.layout.ClipView$_SBECL.compute(ClipView.fx:208)
at com.sun.javafx.runtime.location.AbstractVariable.update(AbstractVariable.java:128)
at com.sun.javafx.runtime.location.AbstractVariable.invalidate(AbstractVariable.java:142)
at com.sun.javafx.runtime.location.AbstractLocation$2.onAction(AbstractLocation.java:234)
at com.sun.javafx.runtime.location.AbstractLocation$2.onAction(AbstractLocation.java:228)
at com.sun.javafx.runtime.location.AbstractLocation.iterateChildren(AbstractLocation.java:181)
at com.sun.javafx.runtime.location.AbstractLocation.invalidateDependencies(AbstractLocation.java:254)
at com.sun.javafx.runtime.location.AbstractLocation.invalidate(AbstractLocation.java:108)
at com.sun.javafx.runtime.location.AbstractVariable.invalidate(AbstractVariable.java:140)
at com.sun.javafx.runtime.location.AbstractLocation$2.onAction(AbstractLocation.java:234)
at com.sun.javafx.runtime.location.AbstractLocation$2.onAction(AbstractLocation.java:228)
at com.sun.javafx.runtime.location.AbstractLocation.iterateChildren(AbstractLocation.java:181)
at com.sun.javafx.runtime.location.AbstractLocation.invalidateDependencies(AbstractLocation.java:254)
at com.sun.javafx.runtime.location.ObjectVariable.notifyListeners(ObjectVariable.java:142)
at com.sun.javafx.runtime.location.ObjectVariable.replaceValue(ObjectVariable.java:110)
at com.sun.javafx.runtime.location.ObjectVariable.set(ObjectVariable.java:121)
at clipview.Main.set$vScroll(Main.fx:76)
at clipview.Main.set$vScroll(Main.fx:76)
at clipview.Main.javafx$run$(Main.fx:76)
at clipview.Main.javafx$run$(Main.fx:76)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.javafx.runtime.provider.GUIRuntimeProvider$1.run(GUIRuntimeProvider.java:65)
at com.sun.javafx.tk.swing.SwingToolkit$StartupRoutine.run(SwingToolkit.fx:593)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Posted by Charles Tam on September 22, 2009 at 09:38 AM IST #

Hi Rakesh,

How i can increase the size of a scroll thumb in javafx 1.2 ?

Posted by nihar on October 18, 2009 at 05:39 PM IST #

@nihar That functionality is not available in 1.2. It will be available in next release.

Posted by Rakesh Menon on October 23, 2009 at 04:25 PM IST #

Post a Comment:
  • HTML Syntax: NOT allowed

This blog copyright 2009 by Rakesh Menon