我要查找的是类似于IntelliJ IDE的scoll-bar:
到目前为止,我唯一可以做的方法就是拥有这段代码,但是这并没有修饰我的舞台-我不想拥有它,它看起来更像是一种解决方法,而不是对滚动条的实际控制。采用此解决方案将需要进行巨大的更改,并将其应用到坚实的背景中,仅因为根已经更改。到目前为止的代码:
主要
primaryStage.initStyle(StageStyle.TRANSPARENT);
root.getScene().setFill(Color.TRANSPARENT);
CSS
* {
-fx-background: transparent;
}
.scroll-pane {
-fx-background-color: transparent;
}
代码产生(蓝色背景是桌面墙纸,我只希望它在场景边界内是透明的,而不是下图所示)
答案 0 :(得分:1)
您可以很容易地使滚动条轨道透明:
.scroll-bar .track {
-fx-fill: transparent;
}
除非您使用自己的皮肤,否则无法删除这些按钮:
.scroll-bar {
-fx-skin: "hs.mediasystem.util.javafx.control.MinimalScrollBarSkin";
}
最后,IntelliJ屏幕快照具有通过滚动条显示的滚动窗格的内容。现在有点棘手,因为滚动条仍将保留空间,背景将是其父级,而不是ScrollPane
的内容。
您只能通过编写自己的ScrollPane
(将其子类化,并在其layoutChildren
中自定义内容的位置并使透明滚动条与内容重叠)来实现。
我没有一个例子,但是应该可以实现。
无论如何,这是MinimalScrollBarSkin的代码(可能有更简单的方法实现,但这对我有用):
package hs.mediasystem.util.javafx.control;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.NumberBinding;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.Skin;
import javafx.scene.layout.Region;
import javafx.scene.shape.Rectangle;
/**
* Scrollbar skin without increment/decrement buttons.
*/
public class MinimalScrollBarSkin implements Skin<ScrollBar> {
private ScrollBar scrollBar;
private Region group;
private Rectangle track = new Rectangle();
private Rectangle thumb = new Rectangle();
public MinimalScrollBarSkin(final ScrollBar scrollBar) {
this.scrollBar = scrollBar;
this.group = new Region() {
NumberBinding range = Bindings.subtract(scrollBar.maxProperty(), scrollBar.minProperty());
NumberBinding position = Bindings.divide(Bindings.subtract(scrollBar.valueProperty(), scrollBar.minProperty()), range);
{
// Children are added unmanaged because for some reason the height of the bar keeps changing
// if they're managed in certain situations... not sure about the cause.
getChildren().addAll(track, thumb);
track.setManaged(false);
track.getStyleClass().add("track");
thumb.setManaged(false);
thumb.getStyleClass().add("thumb");
scrollBar.orientationProperty().addListener(obs -> setup());
setup();
}
private void setup() {
track.widthProperty().unbind();
track.heightProperty().unbind();
if(scrollBar.getOrientation() == Orientation.HORIZONTAL) {
track.relocate(0, -16);
track.widthProperty().bind(scrollBar.widthProperty());
track.setHeight(16);
}
else {
track.relocate(-16, 0);
track.setWidth(16);
track.heightProperty().bind(scrollBar.heightProperty());
}
thumb.xProperty().unbind();
thumb.yProperty().unbind();
thumb.widthProperty().unbind();
thumb.heightProperty().unbind();
if(scrollBar.getOrientation() == Orientation.HORIZONTAL) {
thumb.relocate(0, -16);
thumb.widthProperty().bind(Bindings.max(16, scrollBar.visibleAmountProperty().divide(range).multiply(scrollBar.widthProperty())));
thumb.setHeight(16);
thumb.xProperty().bind(Bindings.subtract(scrollBar.widthProperty(), thumb.widthProperty()).multiply(position));
}
else {
thumb.relocate(-16, 0);
thumb.setWidth(16);
thumb.heightProperty().bind(Bindings.max(16, scrollBar.visibleAmountProperty().divide(range).multiply(scrollBar.heightProperty())));
thumb.yProperty().bind(Bindings.subtract(scrollBar.heightProperty(), thumb.heightProperty()).multiply(position));
}
}
@Override
protected double computeMaxWidth(double height) {
if(scrollBar.getOrientation() == Orientation.HORIZONTAL) {
return Double.MAX_VALUE;
}
return 16;
}
@Override
protected double computeMaxHeight(double width) {
if(scrollBar.getOrientation() == Orientation.VERTICAL) {
return Double.MAX_VALUE;
}
return 16;
}
};
}
@Override
public void dispose() {
scrollBar = null;
group = null;
}
@Override
public Node getNode() {
return group;
}
@Override
public ScrollBar getSkinnable() {
return scrollBar;
}
}
答案 1 :(得分:0)
john16384的答案是完美的,除了不能通过鼠标或触摸移动滚动拇指之外,因此我在其中添加了此功能。 PS:我还将滚动条宽度16更改为有价值的值,该值可以通过CSS定义,但超出主题范围
this.group = new Region() {
private double preDragThumbPos;
private Point2D dragStart;
final NumberBinding range = Bindings.subtract(scrollBar.maxProperty(), scrollBar.minProperty());
final NumberBinding position = Bindings.divide(Bindings.subtract(scrollBar.valueProperty(), scrollBar.minProperty()), this.range);
{
// Children are added unmanaged because for some reason the height of the bar keeps changing
// if they're managed in certain situations... not sure about the cause.
this.getChildren().addAll(MinimalScrollBarSkin.this.track, MinimalScrollBarSkin.this.thumb);
MinimalScrollBarSkin.this.track.setManaged(false);
MinimalScrollBarSkin.this.track.getStyleClass().add("track");
MinimalScrollBarSkin.this.thumb.setManaged(false);
MinimalScrollBarSkin.this.thumb.getStyleClass().add("thumb");
scrollBar.orientationProperty().addListener(obs -> this.setup());
MinimalScrollBarSkin.this.thumb.setOnMousePressed((mouseEvent) -> {
if (mouseEvent.isSynthesized()) {
mouseEvent.consume();
} else {
if (MinimalScrollBarSkin.this.getSkinnable().getMax() > MinimalScrollBarSkin.this.getSkinnable().getMin()) {
dragStart = MinimalScrollBarSkin.this.thumb.localToParent(mouseEvent.getX(), mouseEvent.getY());
double value = Utils.clamp(MinimalScrollBarSkin.this.getSkinnable().getMin(), MinimalScrollBarSkin.this.getSkinnable().getValue(), MinimalScrollBarSkin.this.getSkinnable().getMax());
preDragThumbPos = (value - MinimalScrollBarSkin.this.getSkinnable().getMin()) / (MinimalScrollBarSkin.this.getSkinnable().getMax() - MinimalScrollBarSkin.this.getSkinnable().getMin());
mouseEvent.consume();
}
}
});
MinimalScrollBarSkin.this.thumb.setOnMouseDragged((mouseEvent) -> {
if (mouseEvent.isSynthesized()) {
mouseEvent.consume();
} else {
if (MinimalScrollBarSkin.this.getSkinnable().getMax() > MinimalScrollBarSkin.this.getSkinnable().getMin()) {
if (this.trackLength() > this.thumbLength()) {
Point2D pos = MinimalScrollBarSkin.this.thumb.localToParent(mouseEvent.getX(), mouseEvent.getY());
if (dragStart == null) {
dragStart = MinimalScrollBarSkin.this.thumb.localToParent(mouseEvent.getX(), mouseEvent.getY());
}
double value = MinimalScrollBarSkin.this.getSkinnable().getOrientation() == Orientation.VERTICAL ? pos.getY() - dragStart.getY() : pos.getX() - this.dragStart.getX();
double change = preDragThumbPos + value / (this.trackLength() - this.thumbLength());
double newValue = change * (MinimalScrollBarSkin.this.getSkinnable().getMax() - MinimalScrollBarSkin.this.getSkinnable().getMin()) + MinimalScrollBarSkin.this.getSkinnable().getMin();
if (!Double.isNaN(newValue)) {
MinimalScrollBarSkin.this.getSkinnable().setValue(boundedSize(MinimalScrollBarSkin.this.getSkinnable().getMin(), newValue, MinimalScrollBarSkin.this.getSkinnable().getMax()));
}
}
mouseEvent.consume();
}
}
});
this.setup();
}
private double trackLength() {
return MinimalScrollBarSkin.this.getSkinnable().getOrientation() == Orientation.VERTICAL ? MinimalScrollBarSkin.this.track.getHeight() : MinimalScrollBarSkin.this.track.getWidth();
}
private double thumbLength() {
return MinimalScrollBarSkin.this.getSkinnable().getOrientation() == Orientation.VERTICAL ? MinimalScrollBarSkin.this.thumb.getHeight() : MinimalScrollBarSkin.this.thumb.getWidth();
}
private double boundedSize(double min, double value, double max) {
return Math.min(Math.max(value, min), Math.max(min, max));
}
private void setup() { ... }
}
@ 4673_j的更新
scrollpane在放置内容时将获得滚动条(而不是皮肤)的首选宽度/高度,因此在我们的皮肤中将首选宽度/高度设置为1或0(取决于您的跟踪样式)将解决此问题。 例如,将设置功能修改为:
if (this.scrollBar.getOrientation() == Orientation.HORIZONTAL) {
this.track.relocate(0, -size);
this.track.widthProperty().bind(this.scrollBar.widthProperty());
this.track.setHeight(size);
this.getSkinnable().setPrefHeight(track.getStrokeWidth());
} else {
this.track.relocate(-size, 0);
this.track.setWidth(size);
this.track.heightProperty().bind(this.scrollBar.heightProperty());
this.getSkinnable().setPrefWidth(track.getStrokeWidth());
}