在 JavaFX 中,我有一个
ScrollPane
,其中包含一个 TilePane
,其中包含各种 Button
。
此应用程序将在触摸屏上运行,因此用户将通过在 ScrollPane 中拖动手指来滚动,但如果手指开始在子 Button 上拖动,则 ScrollPane 不会滚动。由于当今触摸 UI 的工作方式,这对用户来说是意想不到的行为。
我希望按钮响应单击,但我希望将拖动事件发送到底层 ScrollPane(如果它使用拖动事件进行平移)。
我已将
setPannable()
的 ScrollPane
属性设置为 true,并且我尝试在 Button
的各种 setOnDrag*()
方法上设置处理程序,然后触发 ScrollPane
的 fireEvent()
方法,但什么也没发生。
示例:
button.setOnDragDone(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
scrollPane.fireEvent(event);
}
});
我该怎么做?
按钮的问题是
ButtonBehavior
为 MouseEvent.MOUSE_PRESSED
注册了默认映射。此映射会消耗该事件,并且 ScrollPane 不再接收该事件以进行平移计算。在以前的 JFX 版本中,可以简单地调用 ButtonSkin.consumeMouseEvents(false)
来解决这个问题。对于当前版本,这不再起作用。我认为这是一个错误,当我有时间时我可能会报告它。
作为解决方法,我将
MouseEvent.MOUSE_PRESSED
重定向到 viewPort
的 ScrollPane
:
ScrollPane pane = new ScrollPane(bar)
{
@Override
protected Skin<?> createDefaultSkin()
{
Skin<?> skin = super.createDefaultSkin();
for (Node ch : getChildren())
{
if (ch.getStyleClass().contains("viewport"))
viewPort = ch;
}
return skin;
}
};
pane.addEventFilter(MouseEvent.MOUSE_PRESSED, e ->
{
if (lastFiredEvent != e)
{
lastFiredEvent = e.copyFor(e.getSource(), viewPort);
viewPort.fireEvent(lastFiredEvent);
}
});
编辑:我报告了该错误。当链接可用时,将在此处发布链接。
我也遇到过这种情况。我通过从 Label 扩展并实现 Toggle 接口编写了一个 PannableToggle 类,也许有一个可选择的伪状态接口?然而..
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.MouseEvent;
public class PannableToggle extends Label implements javafx.scene.control.Toggle {
private final ObjectProperty<ToggleGroup> toggleGroup = new SimpleObjectProperty<>();
private final BooleanProperty selected = new SimpleBooleanProperty(false);
public PannableToggle() { this(null); }
public PannableToggle(String text) {
super(text);
updateStyle();
setOnMouseClicked(this::handleMouseClicked);
}
private void handleMouseClicked(MouseEvent event) {
if (!isSelected() && getToggleGroup() != null) {
getToggleGroup().selectToggle(this);
}
}
@Override
public void setSelected(boolean selected) {
if (this.selected.get() != selected) {
this.selected.set(selected);
updateStyle();
}
}
@Override
public boolean isSelected() { return selected.get(); }
@Override
public ToggleGroup getToggleGroup() { return toggleGroup.get(); }
@Override
public void setToggleGroup(ToggleGroup group) {
this.toggleGroup.set(group);
if (group != null) {
group.getToggles().add(this);
}
}
@Override
public ObjectProperty<ToggleGroup> toggleGroupProperty() { return toggleGroup; }
@Override
public BooleanProperty selectedProperty() { return selected; }
private void updateStyle() {
String style = isSelected() ? " -fx-underline: true;"
: null;
setStyle(style);
}
// Fluent API for setting text
public PannableToggle withText(String text) {
setText(text);
return this;
}
// Fluent API for setting toggle group
public PannableToggle withToggleGroup(ToggleGroup group) {
setToggleGroup(group);
return this;
}
}
试试这个,
consume
TouchEvent
在ScrollPane
例如...
ScrollPane.addEventHandler(TouchEvent.ANY, new EventHandler<TouchEvent>() {
@Override
public void handle(TouchEvent t) {
t.consume();
}
});