- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我尝试使用 JavaFX 在 Java 中创建一个非常基本的照片编辑器程序。到目前为止,我的画笔和橡皮擦工作得很好,方法如下:
package application;
import java.io.File;
import javax.imageio.ImageIO;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.fxml.FXML;
import javafx.geometry.Point2D;
import javafx.scene.canvas.*;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
public class EditorController {
private boolean eraser = false;
@FXML
private Canvas canvas;
@FXML
private ColorPicker colorPicker;
@FXML
private TextField brushSize;
@FXML
private TextField selectedTool;
private Point2D last = null;
public void initialize() {
GraphicsContext gc = canvas.getGraphicsContext2D();
canvas.setOnMouseReleased(e -> {last = null;});
canvas.setOnMouseClicked(e -> {
if (!eraser) {
double size = Double.parseDouble(brushSize.getText());
float mouseX = (float) e.getX();
float mouseY = (float) e.getY();
gc.fillOval(mouseX-(size/2), mouseY-(size/2), size, size);
}
});
canvas.setOnMouseDragged(e -> {
System.out.println(eraser);
double size = Double.parseDouble(brushSize.getText());
gc.setLineCap(StrokeLineCap.ROUND);
gc.setLineWidth(size);
float mouseX = (float) e.getX();
float mouseY = (float) e.getY();
if (last != null && !eraser) {
gc.strokeLine(last.getX(), last.getY(), mouseX, mouseY);
} else if (eraser) {
gc.clearRect(mouseX, mouseY, size, size);
}
last = new Point2D(mouseX, mouseY);
});
}
public void onSave() {
try {
Image snapshot = canvas.snapshot(null, null);
ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), "png", new File("paint.png"));
} catch (Exception e) {
System.out.println("Failed to save image: " + e);
}
}
public void onLoad() {
// not implemented yet
}
// not implemented yet
public void onUndo() { }
public void onRedo() { }
public void onSmaller() { }
public void onBigger() { }
public void onResetView() { }
public void onFitView() { }
public void onFillView() { }
public void onNewLayer() { }
public void onDeleteLayer() { }
public void onDuplicateLayer() { }
public void onGroupLayers() { }
public void onMergeLayers() { }
public void onAddMask() { }
public void onBrush() { eraser = false; selectedTool.setText("Brush"); }
public void onEraser() { eraser = true; selectedTool.setText("Eraser"); }
public void onExit() {
Platform.exit();
}
}
现在我想为画笔设置羽化/硬度值(就像在 photoshop 中一样),这样我就可以画出看起来更柔和的线条,但我不确定如何使用 JavaFX 实现它?里面有没有这样的工具?
所以举一个视觉示例:左边的画笔是 Feather 笔刷,右边的不是(这就是我目前拥有的)
最佳答案
简单的绘图应用。
它使用径向渐变渲染到 Canvas 上绘制的图像,但您可以直接将渐变绘制到 Canvas 上。渐变是一种颜料,因此您可以将其直接设置为 setFill 的参数。在图形上下文中。
我的示例中的解决方案可能不会完全为您提供所需的解决方案,但也许您可以根据需要对其进行调整。
这是我为演示目的而组合的一个快速应用程序,如果需要功能更强大的绘图应用程序,它的结构可以更好。
创建“Feather 笔刷”的代码是基于渐变的:
private RadialGradient createSoftBrushGradient(Color primaryColor) {
return new RadialGradient(
0, 0,
.5, .5,
.5,
true,
CycleMethod.NO_CYCLE,
new Stop(0, primaryColor),
new Stop(1, Color.TRANSPARENT)
);
}
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.*;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class SprayPaint extends Application {
private final IntegerProperty brushDiameter = new SimpleIntegerProperty();
private final ObjectProperty<Image> brushImage = new SimpleObjectProperty<>();
private final ToggleGroup brushHardnessSelection = new ToggleGroup();
private final RadioButton hardBrushSelection = new RadioButton();
private final RadioButton softBrushSelection = new RadioButton();
private final Circle hardBrush = new Circle();
private final Circle softBrush = new Circle();
private final SnapshotParameters snapshotParams = new SnapshotParameters();
private final Canvas canvas = new Canvas(600, 450);
@Override
public void start(Stage stage) {
snapshotParams.setFill(Color.TRANSPARENT);
Pane controls = createControls();
StackPane canvasHolder = new StackPane(canvas);
canvasHolder.setStyle("-fx-border-color: gray;");
canvasHolder.setMaxSize(Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE);
VBox layout = new VBox(
10,
controls,
canvasHolder
);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
enableDrawing(canvas);
}
private void enableDrawing(Canvas canvas) {
EventHandler<MouseEvent> drawHandler = event -> {
Image brush = snapshotBrushImage();
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.drawImage(
brush,
event.getX() - brushDiameter.doubleValue() / 2,
event.getY() - brushDiameter.doubleValue() / 2
);
};
canvas.setOnMousePressed(drawHandler);
canvas.setOnMouseDragged(drawHandler);
}
private Image snapshotBrushImage() {
if (brushImage.get() == null) {
if (hardBrushSelection == brushHardnessSelection.getSelectedToggle()) {
brushImage.set(snapshot(hardBrush));
} else { // soft brush selected
brushImage.set(snapshot(softBrush));
}
}
return brushImage.get();
}
private Image snapshot(Circle brushNode) {
return brushNode.snapshot(snapshotParams, null);
}
private Pane createControls() {
hardBrush.radiusProperty().bind(
brushDiameter.divide(2.0)
);
softBrush.radiusProperty().bind(
brushDiameter.divide(2.0)
);
hardBrushSelection.getStyleClass().addAll("toggle-button", "left-pill");
hardBrushSelection.getStyleClass().remove( "radio-button");
StackPane hardBrushGraphic = new StackPane(hardBrush);
hardBrushGraphic.setMinSize(40, 40);
hardBrushSelection.setGraphic(hardBrushGraphic);
hardBrushSelection.setToggleGroup(brushHardnessSelection);
softBrushSelection.getStyleClass().addAll( "toggle-button", "right-pill");
softBrushSelection.getStyleClass().remove( "radio-button");
StackPane softBrushGraphic = new StackPane(softBrush);
softBrushGraphic.setMinSize(40, 40);
softBrushSelection.setGraphic(softBrushGraphic);
softBrushSelection.setToggleGroup(brushHardnessSelection);
hardBrushSelection.setSelected(true);
HBox brushSelectionPanel = new HBox(hardBrushSelection, softBrushSelection);
Slider brushDiameterSlider = new Slider(8, 40, 20);
brushDiameterSlider.setMajorTickUnit(4);
brushDiameterSlider.setMinorTickCount(0);
brushDiameterSlider.setShowTickMarks(true);
brushDiameter.setValue((int) Math.round(brushDiameterSlider.getValue()));
brushDiameterSlider.valueProperty().addListener((observable, oldValue, newValue) ->
brushDiameter.setValue((int) Math.round(newValue.doubleValue()))
);
Label diameterLabel = new Label();
diameterLabel.textProperty().bind(
brushDiameter.asString()
);
ColorPicker colorPicker = new ColorPicker();
hardBrush.fillProperty().bind(
colorPicker.valueProperty()
);
colorPicker.valueProperty().addListener((observable, oldColor, newColor) ->
softBrush.setFill(
createSoftBrushGradient(newColor)
)
);
colorPicker.setValue(Color.NAVY);
brushDiameter.addListener((observable, oldValue, newValue) ->
brushImage.set(null)
);
colorPicker.valueProperty().addListener((observable, oldValue, newValue) ->
brushImage.set(null)
);
brushHardnessSelection.selectedToggleProperty().addListener((observable, oldValue, newValue) ->
brushImage.set(null)
);
Button clear = new Button("Clear");
clear.setOnAction(e ->
canvas.getGraphicsContext2D().clearRect(
0, 0, canvas.getWidth(), canvas.getHeight()
)
);
HBox controlPanel = new HBox(
10,
colorPicker,
brushSelectionPanel,
new Label("Diameter: "),
brushDiameterSlider,
diameterLabel,
clear
);
controlPanel.setMinWidth(450);
controlPanel.setMinHeight(Pane.USE_PREF_SIZE);
return controlPanel;
}
private RadialGradient createSoftBrushGradient(Color primaryColor) {
return new RadialGradient(
0, 0,
.5, .5,
.5,
true,
CycleMethod.NO_CYCLE,
new Stop(0, primaryColor),
new Stop(1, Color.TRANSPARENT)
);
}
}
关于java - 如何使用 JavaFX 创建 Feather 笔刷?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70142710/
我计划将数据文件格式从 parquet 更改为 feather。 Parquet 有压缩选项(lz4 等),我已经使用过它们。但我无法在 Feather 或箭头文件中找到它们。不支持压缩吗? 最佳答案
我同时使用 R 和 Python,我想将我的一个 pandas DataFrame 编写为一个 feather,以便我可以在 R 中更轻松地使用它。但是,当我尝试将其编写为 feather 时,我得到
在 Feathers 中,目标是将某个服务上可访问的数据限制为仅由当前登录用户拥有的数据。 假设我使用的是 Feathers 认证,这个服务上可用的数据存储在一个数据库表中,包含用户 ID 的表列称为
我尝试使用本地身份验证,但收到错误消息“无效登录”。 我从客户端发送“本地”授权。在服务器上接收数据 { strategy: 'local', email: 'email@gmail.co
我正在尝试在取自 Feather 球比赛的源音频文件中查找其中一名球员击球的实例。出于同样的目的,我用正面(命中声音)和负面(没有命中声音:评论/人群声音等)标签标记了时间戳,如下所示: shot_t
我有一个(每天增长的)大约 100 个大 excel 文件的列表,我用 Python 对其进行分析。由于我必须对所有文件运行几个循环,我的分析变得越来越慢。因此,我想将所有 excel 文件转换为 F
我正在处理一个包含 2000 万多条记录的非常庞大的数据集。我正在尝试将所有数据保存为 Feather 格式以便更快地访问,并在我继续分析时追加。 有没有办法将 Pandas 数据帧附加到现有的 Fe
我正在尝试根据关联表的值过滤数据,当我查找全部时它工作正常但是当我尝试按名称搜索时,我得到一个列不存在错误 我已经设置了一个钩子(Hook),如 https://github.com/feathers
我的 Feathers 应用程序需要能够具有两种 JWT 身份验证策略。对于users服务,我需要有,例如,all: [authenticate('carrier')]而不是 all: [authen
我确信这是非常简单的事情,但由于某种原因,我在尝试将feathersjs客户端与一个非常简单的jQuery应用程序集成时遇到超时。感兴趣的文件位于下面的 src 中。该存储库仅包含连接到 NedB 数
如何创建一个异步函数超时错误处理程序作为驻留在服务文件中的 Feather 中的钩子(Hook)来处理钩子(Hook)中的 Promise? 按照@Bergi on my previous quest
我有一项自定义服务,必须以 CSV 格式返回数据。 我无法使用标准 Express 路由,因为我需要在此端点上使用 Feathers 的 Hook 。 我找不到返回非 HTML、非 JSON 数据的
我正在尝试将 .rds file进入.feather file用于在 Python 中使用 Pandas 进行阅读。 library(feather) # Set working directory
有没有办法使用 pd.to_feather 附加到 .feather 格式文件? 我也很好奇是否有人知道最大文件大小方面的一些限制,以及在读取 .feather 文件时是否可以查询某些特定数据(例如读
我正在尝试将 .rds file进入.feather file用于在 Python 中使用 Pandas 进行阅读。 library(feather) # Set working directory
我应该使用 feather css 图标,但是图标在我的 mvc 元素上不起作用。我尝试更改文件路径,但它再次不起作用。 @font-face { font-family: "feather"
我是 Python 的新手,我正在尝试下载 feather库,但出现错误。我已经更新了 pip 和 setuptools,但我仍然遇到错误。这是我从 PyCharm 获得的输出: Collec
我正在使用 feathers.js 并尝试将对 payment-info.html 页面的访问限制为已登录的用户。 const app = feathers(); app.configure(conf
我正在评估 feathers.js对于一个项目。我喜欢它的愿望。因此,我决定尝试构建一个基本的内容管理系统,作为一种学习努力。事情进行的还算顺利。但是,我想在应用程序启动时将一些静态内容(文章)加载到
按照文档,我意识到有一个允许批量创建的选项,但我不明白在哪里以及如何设置该选项,这里是代码: // Initializes the `test` service on path `/test` con
我是一名优秀的程序员,十分优秀!