如何使用Vaadin标签从另一个类打印arrayList?

时间:2018-11-29 09:06:19

标签: java arraylist vaadin mousemove

我有一个Canvas.java类,其中有一个mousemove代码来跟踪鼠标位置,并将其保存到数组中。如果我从此类本身打印此代码,则鼠标位置正确打印。但是,有什么方法可以从另一个类访问此数组,并使其仍然打印出来(例如,我希望它在MainLayout.java中显示为Vaadin标签)?看来标签仅显示“ []”代替我要打印的坐标。

Canvas.java:

package com.vaadin.starter.beveragebuddy.ui.components;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasSize;
import com.vaadin.flow.component.HasStyle;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.dom.ElementFactory;
import elemental.json.JsonObject;
import java.util.ArrayList;

/**
 * Canvas component that you can draw shapes and images on. It's a Java wrapper
 * for the
 * <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">HTML5
 * canvas</a>.
 * <p>
 * Use {@link #getContext()} to get API for rendering shapes and images on the
 * canvas.
 * <p>
 */
@Tag("canvas")
@SuppressWarnings("serial")
public class Canvas extends Component implements HasStyle, HasSize {

    private CanvasRenderingContext2D context;
    private Element element;
    private boolean isDrawing = false;
    private boolean mouseIsDown = false;
    private double endX;
    private double endY;

    public static ArrayList <BoundingBox> arrayBoxes = new ArrayList<BoundingBox>();
    public static ArrayList <MousePosition> mousePosArray = new ArrayList<MousePosition>();

    public static ArrayList<BoundingBox> getArrayBoxes() {
        return arrayBoxes;
    }

    public static ArrayList<MousePosition> getMousePosArray() {
        return mousePosArray;
    }

    public static void setMousePosArray(ArrayList<MousePosition> mousePosArray) {
        Canvas.mousePosArray = mousePosArray;
    }

    /**
     * Creates a new canvas component with the given size.
     * <p>
     * Use the API provided by {@link #getContext()} to render graphics on the
     * canvas.
     * <p>
     * The width and height parameters will be used for the canvas' coordinate
     * system. They will determine the size of the component in pixels, unless
     * you explicitly set the component's size with {@link #setWidth(String)} or
     * {@link #setHeight(String)}.
     *
     * @param width
     *            the width of the canvas
     * @param height
     *            the height of the canvas
     */
    public Canvas(int width, int height) {

        context = new CanvasRenderingContext2D(this);


        element = getElement();
        element.getStyle().set("border", "1px solid");

        getElement().setAttribute("width", String.valueOf(width));
        getElement().setAttribute("height", String.valueOf(height));

        element.addEventListener("mousedown", event -> {  // Retrieve Starting Position on MouseDown

            Element boundingBoxResult = ElementFactory.createDiv();
            element.appendChild(boundingBoxResult);

            JsonObject evtData = event.getEventData();

            double xBox = evtData.getNumber("event.x");
            double yBox = evtData.getNumber("event.y");
            boundingBoxResult.setAttribute("data-x", String.format("%f", xBox));
            boundingBoxResult.setAttribute("data-y", String.format("%f", yBox));

            BoundingBox newBox = new BoundingBox(0, xBox, yBox, 0.0, 0.0);
            arrayBoxes.add(newBox);

            isDrawing = true;
            mouseIsDown=true;

        }).addEventData("event.x").addEventData("event.y");


        element.addEventListener("mouseup", event -> {  // Draw Box on MouseUp

            Element boundingBoxResult2 = ElementFactory.createDiv();
            element.appendChild(boundingBoxResult2);

            JsonObject evtData2 = event.getEventData();

            endX = evtData2.getNumber("event.x");
            endY = evtData2.getNumber("event.y");
            boundingBoxResult2.setAttribute("end-x", String.format("%f", endX));
            boundingBoxResult2.setAttribute("end-y", String.format("%f", endY));

            double xcoordi = 0;
            double ycoordi = 0;
            double boxWidth = 0;
            double boxHeight = 0;

            for (int i = 0; i < arrayBoxes.size(); i++) {
                arrayBoxes.get(i).setName(i + 1);
                arrayBoxes.get(i).setWidth(endX, arrayBoxes.get(i).xcoordi);
                arrayBoxes.get(i).setHeight(endY, arrayBoxes.get(i).ycoordi);
                xcoordi = arrayBoxes.get(i).getXcoordi();
                ycoordi = arrayBoxes.get(i).getYcoordi();
                boxWidth = arrayBoxes.get(i).getWidth();
                boxHeight = arrayBoxes.get(i).getHeight();

            }

                mouseIsDown=false;
                context.beginPath();
                context.setFillStyle("limegreen");
                context.setLineWidth(2);
                context.strokeRect(xcoordi, ycoordi, boxWidth, boxHeight);
                context.fill();

            System.out.println(arrayBoxes.toString());

        }).addEventData("event.x").addEventData("event.y");

        element.addEventListener("mousemove", event -> {  // Retrieve Mouse Position when Moving

                JsonObject mousePos = event.getEventData();

                double mouseX = mousePos.getNumber("event.x");
                double mouseY = mousePos.getNumber("event.y");

                MousePosition currentPos = new MousePosition(mouseX, mouseY);
                mousePosArray.add(0, currentPos);
                setMousePosArray(mousePosArray);
                System.out.println(mousePosArray.get(0));
//                System.out.println(mousePosArray.get(mousePosArray.size() -1));



     }).addEventData("event.x").addEventData("event.y");


    }

MainLayout.java:

package com.vaadin.starter.beveragebuddy.backend;

import com.vaadin.flow.component.dependency.HtmlImport;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.html.NativeButton;
import com.vaadin.flow.router.Route;
import com.vaadin.starter.beveragebuddy.ui.components.BoundingBox;
import com.vaadin.starter.beveragebuddy.ui.components.Canvas;
import com.vaadin.starter.beveragebuddy.ui.components.CanvasRenderingContext2D;
import com.vaadin.starter.beveragebuddy.ui.components.MousePosition;
import com.vaadin.flow.component.textfield.TextField;
import java.util.ArrayList;

@HtmlImport("frontend://styles/shared-styles.html")
@Route("")

public class MainLayout extends Div {

    private CanvasRenderingContext2D ctx;
    private Canvas canvas;
    ArrayList<MousePosition> mousePosArray = Canvas.getMousePosArray();
    ArrayList<BoundingBox> bb = Canvas.getArrayBoxes();


    public MainLayout() {
        H2 title = new H2("Annotation UI");
        title.addClassName("main-layout__title");

        canvas = new Canvas(1580, 700);

        ctx = canvas.getContext();

        Label label = new Label("Coordinates: " + mousePosArray);
        canvas.addComponent(label);
        add(label);

       }
    }

CanvasRenderingContext2D.java:

package com.vaadin.starter.beveragebuddy.ui.components;

import java.io.Serializable;
import java.util.ArrayList;

/**
 * The context for rendering shapes and images on a canvas.
 * <p>
 * This is a Java wrapper for the <a href=
 * "https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D">same
 * client-side API</a>.
 */
public class CanvasRenderingContext2D {

    private Canvas canvas;
    public static ArrayList<BoundingBox> arrayBoxes = new ArrayList<BoundingBox>();

    protected CanvasRenderingContext2D(Canvas canvas) {
        this.canvas = canvas;
    }

    public void setFillStyle(String fillStyle) {
        setProperty("fillStyle", fillStyle);
    }

    public void setStrokeStyle(String strokeStyle) {
        setProperty("fillStyle", strokeStyle);
    }

    public void setLineWidth(double lineWidth) {
        setProperty("lineWidth", lineWidth);
    }

    public void setFont(String font) {
        setProperty("font", font);
    }

    public void arc(double x, double y, double radius, double startAngle,
            double endAngle, boolean antiClockwise) {
        callJsMethod("arc", x, y, radius, startAngle, endAngle, antiClockwise);
    }

    public void beginPath() {
        callJsMethod("beginPath");
    }

    public void clearRect(double x, double y, double width, double height) {
        callJsMethod("clearRect", x, y, width, height);
        Canvas.arrayBoxes.clear();
    }

    public void closePath() {
        callJsMethod("closePath");
    }

    /**
     * Fetches the image from the given location and draws it on the canvas.
     * <p>
     * <b>NOTE:</b> The drawing will happen asynchronously after the browser has
     * received the image.
     * 
     * @param src
     *            the url of the image to draw
     * @param x
     *            the x-coordinate of the top-left corner of the image
     * @param y
     *            the y-coordinate of the top-left corner of the image
     */
    public void drawImage(String src, double x, double y) {
        runScript(String.format(
                "var zwKqdZ = new Image();" + "zwKqdZ.onload = function () {"
                        + "$0.getContext('2d').drawImage(zwKqdZ, %s, %s);};"
                        + "zwKqdZ.src='%s';",
                x, y, src));
    }

    /**
     * Fetches the image from the given location and draws it on the canvas.
     * <p>
     * <b>NOTE:</b> The drawing will happen asynchronously after the browser has
     * received the image.
     * 
     * @param src
     *            the url of the image to draw
     * @param x
     *            the x-coordinate of the top-left corner of the image
     * @param y
     *            the y-coordinate of the top-left corner of the image
     * @param width
     *            the width for the image
     * @param height
     *            the height for the image
     */
    public void drawImage(String src, double x, double y, double width,
            double height) {
        runScript(String.format("var zwKqdZ = new Image();"
                + "zwKqdZ.onload = function () {"
                + "$0.getContext('2d').drawImage(zwKqdZ, %s, %s, %s, %s);};"
                + "zwKqdZ.src='%s';", x, y, width, height, src));
    }

    public void fill() {
        callJsMethod("fill");
    }

    public void fillRect(double x, double y, double width, double height) {
        callJsMethod("fillRect", x, y, width, height);
    }

    public void fillText(String text, double x, double y) {
        callJsMethod("fillText", text, x, y);
    }

    public void lineTo(double x, double y) {
        callJsMethod("lineTo", x, y);
    }

    public void moveTo(double x, double y) {
        callJsMethod("moveTo", x, y);
    }

    public void rect(double x, double y, double width, double height) {
        callJsMethod("rect", x, y, width, height);
    }

    public void restore() {
        callJsMethod("restore");
    }

    public void rotate(double angle) {
        callJsMethod("rotate", angle);
    }

    public void save() {
        callJsMethod("save");
    }

    public void scale(double x, double y) {
        callJsMethod("scale", x, y);
    }

    public void stroke() {
        callJsMethod("stroke");
    }

    public void strokeRect(double x, double y, double width, double height) {
        callJsMethod("strokeRect", x, y, width, height);
    }

    public void strokeText(String text, double x, double y) {
        callJsMethod("strokeText", text, x, y);
    }

    public void translate(double x, double y) {
        callJsMethod("translate", x, y);
    }

    protected void setProperty(String propertyName, Serializable value) {
        runScript(String.format("$0.getContext('2d').%s='%s'", propertyName,
                value));
    }

    /**
     * Runs the given js so that the execution order works with callJsMethod().
     * Any $0 in the script will refer to the canvas element.
     */
    private void runScript(String script) {
        canvas.getElement().getNode().runWhenAttached(
                // This structure is needed to make the execution order work
                // with Element.callFunction() which is used in callJsMethod()
                ui -> ui.getInternals().getStateTree().beforeClientResponse(
                        canvas.getElement().getNode(),
                        context -> ui.getPage().executeJavaScript(script,
                                canvas.getElement())));
    }

    protected void callJsMethod(String methodName, Serializable... parameters) {
        canvas.getElement().callFunction("getContext('2d')." + methodName,
                parameters);
    }

}

BoundingBox.java:

package com.vaadin.starter.beveragebuddy.ui.components;

public class BoundingBox {

    public double xcoordi = 0;
    public double ycoordi = 0;
    public double boxWidth = 0;
    public double boxHeight = 0;
    public int name;

    public BoundingBox(int name, double xcoordi, double ycoordi, double boxWidth, double boxHeight) {
        this.name = name;
        this.xcoordi = xcoordi;
        this.ycoordi = ycoordi;
        this.boxWidth = boxWidth;
        this.boxHeight = boxHeight;
    }

    public int getName() {
        return name;
    }

    public void setName(int name) {
        this.name = name;
    }

    public double getXcoordi() {
        return xcoordi;
    }

    public void setXcoordi(double xcoordi) {
        this.xcoordi = xcoordi;
    }

    public double getYcoordi() {
        return ycoordi;
    }

    public void setYcoordi(double ycoordi) {
        this.ycoordi = ycoordi;
    }

    public double getWidth() {
        return boxWidth;
    }

    public void setWidth(double endX, double xcoordi) {
        boxWidth = endX - xcoordi;
    }

    public double getHeight() {
        return boxHeight;
    }

    public void setHeight(double endY, double ycoordi) {
        boxHeight = endY - ycoordi;
    }

    @Override
    public String toString() {
        return "{" +
                "Box=" + name +
                ", X=" + xcoordi +
                ", Y=" + ycoordi +
                ", Width=" + boxWidth +
                ", Height=" + boxHeight +
                '}';
    }
}

MousePosition.java:

package com.vaadin.starter.beveragebuddy.ui.components;

public class MousePosition {

    public double mouseX;
    public double mouseY;

    public MousePosition(double mouseX, double mouseY) {
        this.mouseX = mouseX;
        this.mouseY = mouseY;
    }

    public double getMouseX() {
        return mouseX;
    }

    public void setMouseX(double mouseX) {
        this.mouseX = mouseX;
    }

    public double getMouseY() {
        return mouseY;
    }

    public void setMouseY(double mouseY) {
        this.mouseY = mouseY;
    }

    @Override
    public String toString() {
        return "MousePosition{" +
                "mouseX=" + mouseX +
                ", mouseY=" + mouseY +
                '}';
    }
}

非常感谢您的帮助,谢谢!

1 个答案:

答案 0 :(得分:0)

好的,使用更新的代码,看来您的问题是您从未更新标签。

您最初设置了标签文本,但是当数组更改时,它不会自动更新。您可以做的就是允许将侦听器添加到画布,并在值更改时通知它。

在最简单的情况下,侦听器可以只是Java Runnable(如果要传递值,则可以是Supplier)。我的示例返回了Vaadin Registration,可通过调用registration.remove()来删除监听器。

Canvas.java

private List<Runnable> mouseMoveListeners = new ArrayList<>(0);

...

public Registration addMouseMoveListener(Runnable listener) {
    mouseMoveListeners.add(listener);
    return () -> mouseMoveListeners.remove(listener);
}

在您当前的mousemove监听器中

// Your current code in the mousemove listener
MousePosition currentPos = new MousePosition(mouseX, mouseY);
mousePosArray.add(0, currentPos);
setMousePosArray(mousePosArray);
System.out.println(mousePosArray.get(0));

// Add this to run all the listeners that have been added to the canvas
mouseMoveListeners.forEach(Runnable::run);

然后在您的MainLayout构造函数的末尾,像这样

 canvas.addMouseMoveListener(() -> label.setValue("Coordinates: " + mousePosArray));

这是未经测试的代码,但是类似的方法应该可行。关键是,当数组更改时,您必须以某种方式通知MainLayout。