Я начал играть с JavaFX
GraphicsContext
. Особенно мне интересна часть Clipping.
поэтому я попытался создать графику и создать для нее обтравочную маску (простой прямоугольник, который перемещается)
но я заметил с ним какое-то странное поведение (не уверен, что это ошибка или из-за неправильного использования кода)
ниже вы можете найти пример приложения, чтобы показать проблему.
Описание того, что я ожидал от своего кода: белый холст с ПУРПУРНЫМ прямоугольником с текстом, который виден только над пурпурным цветом (хотя он нарисован поперек)
на самом деле это именно то, что вы видите в первую очередь!
когда вы перемещаете окно приложения, ПУРПУРНЫЙ прямоугольник перемещается (как и ожидалось)! но заливка ANTIQUEWHITE становится видимой (чего я никогда не ожидал), и любая область, которая когда-либо была покрыта MAGENTA, теперь видна (без отсечения)
ANTIQUEWHITE и MAGENTA используются, чтобы сделать более очевидным, что что-то идет не так. поскольку весь холст очищается в начале и делается только одна обрезка, это не должно быть проблемой при перерисовке (или закрашивании старого рисунка)
запустите приложение и переместите его, чтобы увидеть эффект «лотерейного скретч-билета».
public class ClippingExampleApp extends Application {
private boolean clip = true;
private static Bounds clippingArea = new BoundingBox(100, 50, 300, 300);
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Clipping Test App");
primaryStage.setX(100);
primaryStage.setY(50);
Group root = new Group();
Canvas canvas = new Canvas(640, 480);
root.getChildren().add(canvas);
primaryStage.setScene(new Scene(root));
ChangeListener<Number> updateBounds = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
clippingArea = new BoundingBox(primaryStage.getX(), primaryStage.getY(), 300, 300);
draw(canvas, clip);
}
};
primaryStage.yProperty().addListener(updateBounds);
primaryStage.xProperty().addListener(updateBounds);
primaryStage.widthProperty().addListener(updateBounds);
primaryStage.heightProperty().addListener(updateBounds);
primaryStage.show();
clippingArea = new BoundingBox(primaryStage.getX(), primaryStage.getY(), 300, 300);
draw(canvas, clip);
}
private static void draw(Canvas canvas, boolean clip) {
GraphicsContext gc = canvas.getGraphicsContext2D();
// CLEAR THE COMPLETE CANVAS
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
gc.save();
if (clip) {
// clipping rect
gc.rect(clippingArea.getMinX(), clippingArea.getMinY(), clippingArea.getWidth(), clippingArea.getHeight());
gc.clip();
// fill the whole background (this should only affect the clipped
// area
gc.setFill(Color.ANTIQUEWHITE);
gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
// this should overlap the Color.ANTIQUEWHITE - so no ANTIQUEWHITE is visible
gc.setFill(Color.MAGENTA);
gc.fillRect(clippingArea.getMinX(), clippingArea.getMinY(), clippingArea.getWidth(), clippingArea.getHeight());
// finally fill the text, which sould only be visible where the magenta rect is...
String text = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.";
gc.setFill(Color.BLACK);
gc.fillText(text, 50, 100);
}
gc.restore();
}
}