JavaFX 之 Canvas


技術概述

javaFX Canvas API提供了一個靈活的畫筆。它可以通過創建canvas對象,獲取其GraphicsContext以及調用繪圖操作以在屏幕上呈現自定義形狀,它可以在JavaFX場景圖中使用。本次項目你畫我猜要求呈現出一個畫板並且能夠繪制自定義圖形,因此學習此組件來應用於項目中。

技術詳述

定義GraphicsContext對象g,之后使用GraphicsContext提供的一組圖形命令來實現繪制圖像。

GraphicsContext g = getGraphicsContext2D();

設置監聽器來獲取畫筆的大小和顏色

nowSize.addListener(evt -> {
        g.setLineWidth(nowSize.get() * Math.min(getWidth(), getHeight()));
    });
nowColor.addListener(evt -> g.setStroke(nowColor.get()));

實現畫筆繪制操作事件,包括按下鼠標,拖動鼠標,釋放鼠標三個響應事件

//鼠標按下事件
setOnMousePressed(evt -> {
        if (!myTurn || !evt.isPrimaryButtonDown())
            return;
        nowPi = new PainInfo();
        pis.add(nowPi);

        g.beginPath();
        double x = evt.getX() / getWidth();
        double y = evt.getY() / getHeight();

        nowPi.xys.add(new BinaryDoubleTuple(x, y));

        g.moveTo(x * getWidth(), y * getHeight());
        g.lineTo(x * getWidth(), y * getHeight());
        g.stroke();
        
        count = 0;
    });
 //鼠標拖動事件   
setOnMouseDragged(evt -> {
        if (!myTurn || !evt.isPrimaryButtonDown())
            return;
        count++;
        if (count % 20 == 0) {
            double x = evt.getX() / getWidth();
            double y = evt.getY() / getHeight();
            nowPi.xys.add(new BinaryDoubleTuple(x, y));

            g.lineTo(x * getWidth(), y * getHeight());
            g.stroke();
        }
        
    });
//鼠標釋放事件
setOnMouseReleased(evt -> {
        g.closePath();
        refresh();

        PainInfo painInfoLast=null;
        if(pis!=null) {
        	painInfoLast= pis.get(pis.size()-1);
        }
        
        HashMap <String,Object> hm = new HashMap<>();
        
        Color color1;
        double size1;
        color1 = nowColor.get();
        size1 = nowSize.get();
        hm.put("drawed", new TernaryTuple<>(color1,size1,painInfoLast.xys));
        System.out.println("i do it");
        NewIo.send(ClientPost.Type.DRAW, hm);
        System.out.println("i do it end");
    });

技術使用中遇到的問題和解決過程

問題:畫布的大小無法隨着窗口自適應,用戶在放大或縮小窗口后畫布仍保持原大小。
解決方法:在javaFX中沒有方法可以調整畫布自適應,唯一的解決方案是從Canvas擴展。

重寫isResizable()方法並返回true

@Override
public boolean isResizable() {
    return true;
}

重寫prefWidth()和prefHeight()方法,返回getWidth()和getHeight()的值

@Override
public double prefWidth(double var1) {
    return getWidth();
}

@Override
public double prefHeight(double var1) {
    return getHeight();
}

將偵聽器添加到畫布的width和height屬性中,以便在畫布大小更改時觸發重繪。

//添加窗口大小監聽器
widthProperty().addListener(evt -> refresh());
heightProperty().addListener(evt -> refresh());

//設計重繪方法
private void refresh() {
    Color color = nowColor.get();
    double size = nowSize.get();
    clear();
    for (PainInfo pi : pis) {
        nowColor.set(pi.color);
        nowSize.set(size);
        g.beginPath();
        BinaryDoubleTuple first = pi.xys.getFirst();
        g.moveTo(first.first * getWidth(), first.second * getHeight());
        for (BinaryDoubleTuple xy : pi.xys) {
            g.lineTo(xy.first * getWidth(), xy.second * getHeight());
            g.stroke();
        }
        g.closePath();
    }
    nowColor.set(color);
    nowSize.set(size);
}

將畫布的width和height屬性綁定到父窗格StackPane的width和height屬性。

DngCanvas dc = new DngCanvas();
StackPane ret = new StackPane(dc);
dc.widthProperty().bind(ret.widthProperty());
dc.heightProperty().bind(ret.heightProperty());

總結

javafx中的Canvas能很好的幫助我們實現畫板繪制功能,必要時也需創建子類對其進行功能拓展和完善,以滿足項目產品的需求。

參考文獻

Canvas JavaFX8

JavaFX - Resize Canvas when screen is resized


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM