I was wondering if there is a way to disable/prevent scrolling in a ScrollPane?
Basically I have a Canvas wrapped in a Group object to enable zooming (which is done by 'Ctrl + scroll'). Though for some reason the ScrollPane consumes the event (if it can be scrolled) before it fires any other scrollEvent (e.g. the ScrollEvent from the Canvas, Group, ScrollPane and even the ScrollPane's Parent!).
So I was wondering what the options are (if there are any) to catch a scrollEvent before it is consumed by the ScrollPane.
Thanks for your time
Thanks to joshpy I got the answer.
I forgat that EventFilters are a thing in javafx. Luckly you can consume the Event in the eventFilter as well, so here is the solution.
scrollPane.addEventFilter(ScrollEvent.SCROLL, event -> {
if(event.isControlDown())
{
zoomCanvas(event) // zoom the canvas instead of scrolling the actual pane.
event.consume();
}
});
Many thanks for the tip!
Although Im still not sure why an usual event wouldn't work.
Related
I have very simple programm and very bad bug-_-
In my programm I have ScrollPane, that contains Accordion. ScrollPane prefHeightProperty binded to Accordion heightProperty.
themeScroll.prefHeightProperty().bind(themeAccordion.heightProperty());
And when I collapse titledPane, the height of the Accordion decreases. And the height of the ScrollPane, too, must be decreased to a height of Accordion, but it does not decrease until the end.
(ScrollPane has green background)
Then I minimize the window and re-open it and see:
How can I avoid this problem?
UPD 1:
I know that I need call this code for resize scrollPane:
Platform.runLater(() -> {
themeScroll.requestLayout();
});
But where?
I tried to call it in themeAccordion.expandedPaneProperty.addListener(...), but it isn't help
And if I will call it in themeAccordion.heightProperty().addListener(...), then the problem is solved, but this code themeScroll.requestLayout(); is called many times it's bad.
I am using scala.swing, but a solution for Java Swing is also applicable to scala.swing.
Therefore I open this question as a Java Swing question.
I have JTable with TransferHandler in JScrollPane.
Usually, the table can scroll with mouse wheel motion.
While dragging, however, the scroll pane does not move with mouse wheel.
The user can scroll by moving cursor to the top or the bottom of the pane(auto scroll),
but auto scroll is slow, so I want to provide usual mouse functionality.
I tried to capture mouse wheel event in JTable.
When not dragging, it receives MouseWheelMove event, but while dragging, it receives nothing.
My guess is that mouse wheel event is delivered to something related to TransferHandler, not to JTable.
How to detect mouse wheel motion while dragging?
Any other method is welcome, as far as my aim is achieved.
It seems (at least on OS X), that the wheel events are buffered and dispatched only after the DnD gesture is complete. Here is my try:
import javax.swing._
val d = Array.fill(1000)(Array[AnyRef]((math.random * 1000).toInt.toString))
val t = new JTable(d, Array[AnyRef]("A")) {
override def processMouseWheelEvent(e: java.awt.event.MouseWheelEvent): Unit = {
println(s"Wheel: ${e.getID}")
super.processMouseWheelEvent(e)
}
def enableEventsP(e: Long): Unit = enableEvents(e)
}
t.setDragEnabled(true)
t.enableEventsP(java.awt.AWTEvent.MOUSE_WHEEL_EVENT_MASK)
val f = new JFrame
f.getContentPane.add(new JScrollPane(t), java.awt.BorderLayout.CENTER)
f.pack()
f.setVisible(true)
When I scroll the wheel while dragging and then release the mouse, the wheel events are delivered.
You may want to override the autoscroll behaviour of the JTable to make it faster, I guess. This is done in DropTarget as far as I can see. I found this example.
In my app, I show a popup dialog to show a large list of cards. I display them as images in many JLabel components in a JPanel subclass. I then put that object in a JScrollPane to allow for horizontal scrolling through the cards.
I want the unused space to be transparent with a dark background to show that what's behind it is disabled. I used setBackground(new Color(50, 50, 50, 200)) to achieve the look I want, but the content behind it does not redraw, so I get artifacting.
Here's what it looks like:
How would I go about fixing this? How do I get the content behind it to redraw when I scroll?
Thanks in advance.
Taking the window out of the equation for the momement.
The JScrollPane contains a JViewport which then contains you content. So you need to set your content pane to transparent, the viewport to transparent and then the scroll pane to transparent.
You can achieve this by using setOpaque(false) on each of these containers.
This will ensure that the repaint manager will now paint through the background.
The next problem is, Swing doesn't actually support "semi-transparent" components (that is, either it's opaque or transparent).
You can implement this by overriding the paintComponent method of the main component (the one on the viewport is probably sufficient)
Try the following...might give you some relief during scrolling.
You likely also have a problem when the main frame is maximized
or restored. You will need a listener for those events and a
similar fix.
jScrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(final AdjustmentEvent e) {
sevenWondersframe.repaint();
}
});
jScrollPane.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(final AdjustmentEvent e) {
sevenWondersframe.repaint();
}
});
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.
I have a JScrollpane which contains a scrollable client that changes its size dynamically while using the application. I want the JScrollPane to be aware of the changes without moving the viewport when the client size changes.
To clarify what I mean:
Refer to the Java Webstart example ScrollDemo2 from the article How to use scroll panes by Sun. When clicking at the bottom of the window, a circle appears partly outside the window and the scrollbars move. It's the latter behavior I want to avoid.
My guess is that it's just a matter of setting a simple flag in one of the many components that are involved in a scroll pane solution, but I just can't find where it is. Does anyone know?
I managed to solve this problem by overriding the standard behavior of the viewport in my JScrollPane. This might be a solution that is not suitable for all, but in my GUI this works like a charm.
JScrollPane pane = new JScrollPane();
pane.setViewport(
new JViewport(){
/**
* An empty override implementation to prevent undesired scrolling on
* size changes of the client.
*/
#Override
public void scrollRectToVisible(Rectangle rect){}
});
I would try something like:
Point p = scrollPane.getViewport().getViewportPosition();
revalidate();
scrollPane.getViewport().setViewportPosition(p);
You may need to wrap the last line of code in a SwingUtilities.invokeLater.
If that doesn't work then maybe you can disable/enable the viewport before and after the revalidate()?