我正在尝试通过拖动来创建一些带有矩形的节点的选择 一切都很好,但我不能让选择回归正常。 更清楚的是,我的问题是:想象一下,在桌面中你做了一个矩形选择,当回来时(不想选择最后一个图标),最后一个图标仍然被选中。
public class BorderPaneConInstallazioni extends BorderPane {
List<DragSelectable> selectable = new LinkedList<>();
public BorderPaneConInstallazioni() {
VBoxSelectable v1 = new VBoxSelectable(Color.FUCHSIA);
VBoxSelectable v2 = new VBoxSelectable(Color.BLACK);
VBoxSelectable v3 = new VBoxSelectable(Color.RED);
VBoxSelectable v4 = new VBoxSelectable(Color.BLUEVIOLET);
VBoxSelectable v5 = new VBoxSelectable(Color.FORESTGREEN);
v1.getChildren().add(new Label("Ciao"));
v2.getChildren().add(new Label("Ciao"));
v3.getChildren().add(new Label("Ciao"));
v4.getChildren().add(new Label("Ciao"));
v5.getChildren().add(new Label("Ciao"));
selectable.add(v1);
selectable.add(v2);
selectable.add(v3);
selectable.add(v4);
selectable.add(v5);
setTop(v1);
setLeft(v2);
setCenter(v3);
setRight(v4);
setBottom(v5);
registerEvents();
}
private void deselectAll(){
for(DragSelectable sel : selectable) sel.deselect();
}
private Rectangle resizeRectangle = null;
public void registerEvents() {
setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle (MouseEvent event){
resizeRectangle = new Rectangle(event.getSceneX(), event.getSceneY(), 0, 0);
resizeRectangle.setStyle(" -fx-fill: transparent;\n" +
" -fx-stroke: #00000080;\n" +
" -fx-stroke-width: 1;\n" +
" -fx-stroke-dash-array: 4 4 4 4;");
getChildren().add(resizeRectangle);
event.consume();
}
});
setOnDragDetected(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
startFullDrag();
}
});
setOnMouseDragged( (mouseEvent) -> {
// only on primary
if (mouseEvent.getButton().equals(MouseButton.PRIMARY) == false) {
return;
}
List<Node> lista = pick(this,mouseEvent.getSceneX(),mouseEvent.getSceneY(),new LinkedList<Node>());
System.out.println(lista);
List<Node> selezionati = new LinkedList<>();
for(Node nodo : lista){
if(nodo instanceof DragSelectable){
DragSelectable b = (DragSelectable) nodo;
b.seleziona();
selezionati.add(nodo);
}
}
System.out.println(selezionati);
if(selezionati.size() != 0) {
for (DragSelectable corrente : selectable) {
if (!selezionati.contains(corrente)) {
// corrente.deseleziona();
Node nodo = (Node) corrente;
if(!resizeRectangle.getBoundsInLocal().intersects(nodo.getBoundsInLocal())){
corrente.deseleziona();
}
}
}
}
mouseEvent.consume();
nodeY (layoutY) to on-screen mouseY
Bounds boundsInScene = resizeRectangle.localToScene(resizeRectangle.getBoundsInLocal());
double width = mouseEvent.getSceneX() - boundsInScene.getMinX();
double height = mouseEvent.getSceneY() - boundsInScene.getMinY();
if(width >= 0) {
resizeRectangle.setHeight(height);
resizeRectangle.setWidth(width);
} else{
resizeRectangle.setHeight(0);
resizeRectangle.setWidth(0);
}
});
setOnMouseDragReleased(new EventHandler<MouseDragEvent>() {
@Override
public void handle(MouseDragEvent event) {
deselectAll();
getChildren().remove(resizeRectangle);
resizeRectangle = null;
event.consume();
}
});
}
public static List<Node> pick(Node node, double sceneX, double sceneY, List<Node> result) {
Point2D p = node.sceneToLocal(sceneX, sceneY, true /* rootScene */);
// check if the given node has the point inside it, or else we drop out
if (!node.contains(p)) return result;
// at this point we know that _at least_ the given node is a valid
// answer to the given point, so we will return that if we don't find
// a better child option
if (node instanceof Parent) {
// we iterate through all children in reverse order, and stop when we find a match.
// We do this as we know the elements at the end of the list have a higher
// z-order, and are therefore the better match, compared to children that
// might also intersect (but that would be underneath the element).
Node bestMatchingChild = null;
List<Node> children = ((Parent)node).getChildrenUnmodifiable();
for (int i = children.size() - 1; i >= 0; i--) {
Node child = children.get(i);
p = child.sceneToLocal(sceneX, sceneY, true /* rootScene */);
if (child.isVisible() && !child.isMouseTransparent() && child.contains(p)) {
bestMatchingChild = child;
break;
}
}
if (bestMatchingChild != null) {
result.add(bestMatchingChild);
return pick(bestMatchingChild, sceneX, sceneY,result);
}
}
return result;
}
}
public class VBoxSelectable extends VBox implements DragSelectable {
public Background back = new Background(new BackgroundFill(Color.FUCHSIA, new CornerRadii(2), new Insets(0)));
public final Background backBianco = new Background(new BackgroundFill(Color.WHITE, new CornerRadii(2), new Insets(0)));
String selezionato;
public VBoxSelectable(Color color){
back = new Background(new BackgroundFill(color, new CornerRadii(2), new Insets(0)));
selezionato = color.toString();
}
@Override
public void select() {
setBackground(back);
}
@Override
public void deselect() {
setBackground(backBianco);
}
@Override
public String toString(){
return selezionato;
}
}
DragSelectable
是方法select()
和deselect()
的界面。
我注意到的是,当我返回时,pick功能选择的唯一节点(我在这里找到http://fxexperience.com/2016/01/node-picking-in-javafx/)是矩形而没有别的,所以什么都不会被取消选择。
为了完整性,我还将插入接口和主类。
public interface DragSelectable {
public void select();
public void deselect();
}
和主
public class Main extends Application {
public static Scene scena;
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = new BorderPaneConInstallazioni();
primaryStage.setTitle("Hello World");
Scene scene = new Scene(root,800,800);
scena = scene;
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我如何解决我的问题?
javafx中是否内置了实现此功能的内容?