JavaFX – ClipView [ Scroll + Pane ]


JavaFX 1.3 introduces many new controls with CSS support. Please refer to UI Controls documentation. You may use new ScrollView control instead of approach mentioned below.

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:

var dzone_url = “http://blogs.sun.com/rakeshmenonp/entry/javafx_clipview”;
var dzone_style = ‘2’;

Advertisements

About Rakesh Menon
-

13 Responses to JavaFX – ClipView [ Scroll + Pane ]

  1. Tom says:

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

  2. Tim says:

    Nice example. When you make the main window resizable the ClipView will not change and keep it’s size of 300×200. 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).

  3. Rakesh Menon says:

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

  4. Abdullah says:

    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.

  5. Rakesh Menon says:

    @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..

  6. Charles Tam says:

    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)

  7. nihar says:

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

  8. Rakesh Menon says:

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

  9. Mike Caron says:

    Hi Rakesh, seems that launching this JNLP on Snow Leopard crashes. I grabbed the code and it seems to be related to ScrollBar. If I create a simple stage with a single component, a horizontal scrollbar, I get an invalid memory access of location 0x0… blah blah. I’m on NetBeans 6.8 and using JFX 1.2.3.

    Any thoughts?

  10. Pawel says:

    @Charles I’ve had the same problem in my application because I missed the LayoutInfo Part so the ClipView had the same size as its content. The size of ClipView should be smaller to scroll it.

  11. Rakesh Menon says:

    I think the exception is thrown when invalid values are set to ClipView.
    You can ensure that the value assigned to ClipView are valid

    clipX: bind Math.max(0, hScroll.value)
    clipY: bind Math.max(0, vScroll.value)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: