Canvas “我怎么能?”;突出显示“;或者在JavaFX8画布周围放置边框?

Canvas “我怎么能?”;突出显示“;或者在JavaFX8画布周围放置边框?,canvas,javafx-8,Canvas,Javafx 8,我正试图为图像查看器桌面产品组装一个简单的POC。我的查看器需要支持注释,因此我决定尝试使用我正在查看的图像的主画布,然后使用较小的画布对象来放置注释 注释需要能够被拖动、删除、重新排序等 但是,要显示选中的画布,我需要将其高亮显示,或在其上放置阴影,或在其周围环绕边框 我看不到可以在那里应用的CSS样式。我已经用HBox包装了它来模拟这种效果,但我想知道是否有可能用另一种方式 谢谢 Canvas是节点的一个直接子类,因此它只支持为节点定义的CSS属性。这些不包括应用边框的标准方法,例如-fx背

我正试图为图像查看器桌面产品组装一个简单的POC。我的查看器需要支持注释,因此我决定尝试使用我正在查看的图像的主画布,然后使用较小的画布对象来放置注释

注释需要能够被拖动、删除、重新排序等

但是,要显示选中的画布,我需要将其高亮显示,或在其上放置阴影,或在其周围环绕边框

我看不到可以在那里应用的CSS样式。我已经用HBox包装了它来模拟这种效果,但我想知道是否有可能用另一种方式


谢谢

Canvas
节点
的一个直接子类,因此它只支持为
节点
定义的CSS属性。这些不包括应用边框的标准方法,例如
-fx背景色
-fx边框色

但是,
节点
支持
-fx effect
属性,因此您可以使用该属性。下面是一个使用内联样式的“快速而肮脏”示例(在实际应用中,我建议使用外部样式表;根据您的要求,可能会将
Canvas
子类化以提供“选择”行为):

导入javafx.application.application;
导入javafx.beans.property.ObjectProperty;
导入javafx.beans.property.SimpleObject属性;
导入javafx.scene.scene;
导入javafx.scene.canvas.canvas;
导入javafx.scene.canvas.GraphicsContext;
导入javafx.scene.layout.HBox;
导入javafx.scene.paint.Color;
导入javafx.stage.stage;
公共类CanvasCSSEffect扩展应用程序{
@凌驾
公共无效开始(阶段primaryStage){
画布画布1=新画布(400400);
画布画布2=新画布(400400);
GraphicsContext gc1=canvas1.getGraphicsContext2D();
gc1.毛织物(颜色:玉米丝);
gc1.fillRect(0,040400);
GraphicsContext gc2=canvas2.getGraphicsContext2D();
gc2.设置填充(颜色:仿古白色);
gc2.fillRect(0,040400);
ObjectProperty selectedCanvas=新建SimpleObject属性();
selectedCanvas.addListener((obs、oldCanvas、newCanvas)->{
if(oldCanvas!=null){
oldCanvas.setStyle(“”);
}
if(newCanvas!=null){
setStyle(“-fx效果:内部阴影(高斯,#039ed3,10,1.0,0,0);”;
}
});
canvas1.setOnMouseClicked(e->selectedCanvas.set(canvas1));
canvas2.setOnMouseClicked(e->selectedCanvas.set(canvas2));
HBox根=新的HBox(10,canvas1,canvas2);
primaryStage.setScene(新场景(根));
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}

当我尝试您的示例时,它按预期在画布周围放置了一个框。当我把这个应用到画布上时,画布上只有文本,而且是透明的,它改变了文本的颜色。有没有一种方法可以让它在只有文本的画布上执行与您的示例相同的操作?嗯,这不是很有趣吗。。。我需要再做一点试验。我猜这个效果应用于第一个不透明像素,或者一些类似的算法。除非你能用底色填充画布,否则你可能不得不求助于在
窗格
中进行包装。我已经能够在画布周围使用HBox来模拟这一点,从而满足我的需要。这个选择让我很伤心。如果我添加一个新类来处理selectionHandler(只是扩展窗格),我就不能在scenebuilder中使用它。当我回到电脑前,我会用一个FXML友好的类来更新它,这个类管理选择。你需要多个选择吗(如果不需要,支持ToggleGroup是一个很好的选择…)我在这里发布了另一个关于这个主题的问题:,我只需要选择突出显示的节点并取消选择当前选中的任何节点。这一切都是可行的,但是与SceneBuilder的集成是痛苦的。我真的很感谢你的帮助。
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class CanvasCSSEffect extends Application {

    @Override
    public void start(Stage primaryStage) {
        Canvas canvas1 = new Canvas(400, 400);
        Canvas canvas2 = new Canvas(400, 400);

        GraphicsContext gc1 = canvas1.getGraphicsContext2D();
        gc1.setFill(Color.CORNSILK);
        gc1.fillRect(0, 0, 400, 400);

        GraphicsContext gc2 = canvas2.getGraphicsContext2D();
        gc2.setFill(Color.ANTIQUEWHITE);
        gc2.fillRect(0, 0, 400, 400);

        ObjectProperty<Canvas> selectedCanvas = new SimpleObjectProperty<>();
        selectedCanvas.addListener((obs, oldCanvas, newCanvas) -> {
            if (oldCanvas != null) {
                oldCanvas.setStyle("");
            }
            if (newCanvas != null) {
                newCanvas.setStyle("-fx-effect: innershadow(gaussian, #039ed3, 10, 1.0, 0, 0);");
            }
        });

        canvas1.setOnMouseClicked(e -> selectedCanvas.set(canvas1));
        canvas2.setOnMouseClicked(e -> selectedCanvas.set(canvas2));

        HBox root = new HBox(10, canvas1, canvas2);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}