Table control with sliding row headers in JavaFX - java

The album view in iTunes has a slick effect where the album title and cover art stay in view at all times. If you slide down the screen they stay pinned to the top of the screen until they bump into the next album, then they slide away.
Notice how the top album is still fully visible even though the user has scrolled down a ways.
What is this control or effect called? I'm coming up with blanks trying to Google for it.
How can I do this in JavaFX? I want to mimic this in my Java-based GUI. Can TableView do this, or maybe some third-party control?

The easiest way to do this is with a ScrollPane. Inside your ScrollPane you define your rows and their layouts (probably each row is an HBox containing an ImageView and a TableView which is set to the height of the ImageView). Then, the TableViews inside your ScrollPane need to let the ScrollPane override their scrolling - that is, their onScroll bubbles up to the ScrollPane.
Then you override the onScroll behavior for your ScrollPane. The algorithm for the scrolling could go like this:
There are two modes.
1) Scrolling IN an album scrolls the TableView in that row. If the scrolling goes beyond the boundaries of the TableView's scrollHeight (the range between 0 and scrollHeight), then the mode switches to scrolling TO an album.
2) Scrolling TO an album scrolls the ScrollPane an amount up to the height of the current row. Scrolling an amount greater than the current row's height moves to the next album and switches the mode back to Scrolling IN that album.
3) Edge Cases: Scrolling within the ScrollPane beyond the boundaries of the ScrollPane's scrollHeight (the range between 0 and scrollHeight) immediately moves to the next album and switches the mode back to Scrolling IN that album.
I'd give a code example, but I've never actually seen anybody try to do this. I just know you CAN do it.

I would recommend you to take a look to the SpreadsheetView in ControlsFX
The SpreadsheetView allow you to fix at the top of the screen any number of line. So you would have the first part of your behavior.
Regarding the fact of bumping into another, it would be more difficult but not impossible with the SpreadsheetView.
Anyway, if you want to implement that behavior in the TableView, you will find very useful tricks in the SpreadsheetView code.

This is how a section title acts as default in a UITableView.
https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UITableView_Class/index.html
This should help you on how to create and use UITableView

Related

Java FX TextArea ScrollLeft Precision with Backspace

In the TextArea widget of Java FX 2.2, the method getScrollLeft is described in the documentation as returning
The number of pixels by which the content is horizontally scrolled.
More precisely, it accesses the value of the property ScrollLeft which has the above description.
When I slide either the horizontal or vertical scrollbar, this variable is adjusted, as expected. However when I press "backspace" on a line that is longer than the screen width such that the scroll amount decreases, or at the first character of a row, the property is not adjusted even though the scroll position changes.
A hacky way to fix this is to access the scrollbar directly, get how much of it is being scrolled, and calculate the appropriate value based on that information. I'd prefer not to do this.
Is there an accepted way to solve this problem, or am I misusing the scrollbar information?

Forcing JScrollPane to scroll by (X) pixels

I have a JScrollPane scroller that I would like to make move a specified amount of pixels either vertically or horizontally.
Specifically, I'm making a tile-based game in which the tile panel is wrapped in a JScrollPane that has its scrollbars hidden from the user. I need the code to adjust the scrolling such that every time I call my movePlayer() method in the tile panel, the scrollbar(s) automatically move over by the length of one tile.
Most of my searches so far have only yielded results for scrollBy in javascript.
Is there a way to programmatically force the bar to scroll in Java?
Take a look at JViewport#getViewRect, JViewport#getViewPosition, and JViewport#setViewPosition
These will allow to adjust the JScrollPane's viewport position.
You can also take a look JComponent#scrollRectToVisible which allows to ask that a given area of a component be made visible if it is within a scrollpane/viewport
You can take a look at Moving a view port over a larger image; JLablel+JScrollPane for example

LWUIT Horizontal list scrolling gimping vertical form scrolling

In LWUIT, I have a form that has around 4 horizontal lists. The lists' horizontal scrolling words perfectly.
However, when I want to scroll vertically up and down the form, it just ends up scrolling horizontally whichever list where the swipe begins, even though I'm swiping up and down and not left and right.
Is there any way to fix this?
Edit:
This is my layout for the form:
this.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
this.setScrollableY(true);
This was a bug in LWUIT that wasn't designed for doing that, we fixed it in Codename One. Its not a trivial fix since we needed to refactor quite a lot of things.

JScrollbar scroll per 50 px

I'm working on a program that includes a scrollbar.
In the program I got a scrollable field of 500px and I want the scrollbar to scroll per 50px.
So I get 10 pages.
I dont want to be able to show 50% of a page I only want to be able to show 1 page at a time.
So how do I change the scroll dimensions?
Or is there a better way to accomplish this?
Greets,
And thanks in advance
Bram
You can make the scrollable field implement the Scrollable interface, which declares two methods the scroll field will use to decide how far it scrolls, getScrollableUnitIncrement (scroll-wheel, clicking the scroll arrow) and getScrollableBlockIncrement (clicking the scrollbar's track).
If you're really only ever going to want it to be 50, you can use
jScrollPane.getVerticalScrollBar().setUnitIncrement(50);
jScrollPane.getVerticalScrollBar().setBlockIncrement(50);
However, if the user then drags the scrollbar until half a page is shown (I don't think this behavior can be easily changed), scrolling will still jump 50 pixels and show half of the next page... If you implement Scrollable, you can base the amount scrolled on what is currently visible.
Try this with you JScrollPane
scrollPane.getVerticalScrollBar().setUnitIncrement(50);
This helps when you scroll with JScrollPane buttons up/down but you be able show a half of page by moving knob with mouse.
As alternative I can propose to watch knob position with AdjustmentListener and shift scrollPane value manually.
scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener()
{
public void adjustmentValueChanged(AdjustmentEvent e)
{
scrollPane.getVerticalScrollBar().setValue(e.getValue() / 50 * 50);
}
});
But I think it isn't good idea. May be somebody will propose better way.

JXMultiSplitPane going bonkers when I switch tabs

I'm using JXMultiSplitPane (from SwingX 1.6.2) to implement a three-pane horizontal interface. In the center pane is a JTabbedPane with two tabs: one with a JTextArea (in a JScrollPane, of course) used for entering Markdown code and the other a JEditorPane (again, in a scroll pane) for displaying a rendered HTML preview. When the user switches to the preview pane, the text in the editor is processed and displayed in the preview pane.
My problem is that if I enter text in the editor with long lines, and then switch to the preview, the center pane will expand. Sometimes it's just by a little bit, other times it'll take up more room than is actually on the screen. But if I move one of the resize handles manually, everything will snap back in place.
I've found only two ways to deal with this before it happens:
Manually resize one of the panes before entering any text.
Give the center pane a weight of 1 in the MultiSplitLayout model.
I can't use the second one since it will expand the center pane to take up almost the whole window by default.
Is there a way to fix this?
Update
After a little more testing, even technique (2) doesn't keep the size constant; switching between the two tabs changes the size of the center pane slightly.
I now believe that the problem is partly with the tabbed pane. The JTextArea and the JEditorPane do not have the same size and that JTabbedPane is resizing when I switch between them (since I'm resetting the JEditorPane text every time. This wouldn't be a problem except that JXMultiSplitPane will keep automatically resizing the center pane until the user forces a specific size by resizing manually.
So I should be able to fix the issue by making the size of the JTabbedPane fixed, but still able to be resized by the handle bars. Any tips on doing that?
The MultiSplitLayout is .. a LayoutManager, so you have to understand how it works (me too, not overly familiar with it myself :-)
The basic layout happens according to the component's prefSize, the weights are for distributing excess/missing space relative to the pref. By default, the dividers are "floating", that is they are positioned between the components as layouted by the basic mechanism. The moment a user touches a divider, dividers are "not-floating", comp sized to fit in-between the dividers. That's the reason for you not seeing the size-greed after moving the divider once. So one ways out is to
setup the JXMultiSplitPane as usual, add the components and realize the frame
fix the dividers after the manager has done its initial layout
String layout = "(ROW " +
"(LEAF name=selector weight=0.15)" +
"(LEAF name=center weight=0.7)" +
"(LEAF name=list weight=0.15)" +
")";
JXMultiSpitPane pane = new JXMulitSplitPane((MultiSplitLayout.parseModel(layout))
// add components and realize the frame
...
pane.getMultiSplitLayout().setFloatingDividers(false);
Alternatively, give more weight to the weights - force the layoutManager to use them for the layout itself (instead of only for the distribution of excess/missing space). A side-effect is that the prefSize of the comps might be set (by the layout, which is a no-no-never, but who's perfect ;-)
pane.getMulitSplitLayout().setLayoutByWeights(true);
Not sure which way I would prefer or if/how that could be made easier in the multisplit ..

Categories

Resources