2016-04-26 158 views
0

我現在遇到輸入和輸出流的問題。它不會將套接字輸入流轉換爲byte []或將套接字輸出流轉換爲int。如何讓程序實際發送byte []數組到服務器?下面是更新後的代碼:如何將GraphicsContext從客戶端發送到服務器,然後發送到所有其他客戶端?

import java.io.*; 
import java.net.*; 
import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.control.TextArea; 
import javafx.scene.control.TextField; 
import javafx.scene.control.Button; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.GridPane; 
import javafx.scene.canvas.Canvas; 
import javafx.scene.canvas.GraphicsContext; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import javafx.embed.swing.SwingFXUtils; 
import javafx.scene.image.*; 
import javax.imageio.ImageIO; 

public class PaintClient extends Application { 
    //GUI components 
    private TextField tfRed = new TextField(""); 
    private TextField tfGreen = new TextField(""); 
    private TextField tfBlue = new TextField(""); 
    private Button btSetColor = new Button("Set Color"); 
    private Button btReset = new Button("Reset"); 
    private Button btSend = new Button("Send"); 
    //Networking components 
    private Socket socket; 
    private ByteArrayOutputStream byteOut; 
    private ByteArrayInputStream byteIn; 

    @Override 
    public void start(Stage primaryStage) { 

    tfRed.setPrefWidth(80); 
    tfGreen.setPrefWidth(80); 
    tfBlue.setPrefWidth(80); 

    GridPane gridPane = new GridPane(); 
    gridPane.add(new Label("Color"), 0, 0); 
    gridPane.add(tfRed, 1, 0); 
    gridPane.add(tfGreen, 2, 0); 
    gridPane.add(tfBlue, 3, 0); 
    gridPane.add(btSetColor, 4, 0); 
    gridPane.add(btReset, 2, 1); 
    gridPane.add(btSend, 3, 1); 

    Canvas canvas = new Canvas(365,375); 
    final GraphicsContext gc = canvas.getGraphicsContext2D(); 
    initDraw(gc); 

    BorderPane bPane = new BorderPane(); 
    bPane.setTop(gridPane); 
    bPane.setCenter(canvas); 

    Scene scene = new Scene(bPane, 375, 450); 
    primaryStage.setTitle("Drawing Canvas"); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 

    canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, 
     new EventHandler<MouseEvent>(){ 

     @Override 
     public void handle(MouseEvent event) { 
      gc.beginPath(); 
      gc.moveTo(event.getX(), event.getY()); 
      gc.stroke(); 
     } 
    }); 
    canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, 
     new EventHandler<MouseEvent>(){ 

     @Override 
     public void handle(MouseEvent event) { 
      gc.lineTo(event.getX(), event.getY()); 
      gc.stroke(); 
     } 
    }); 


    //Networking 
    try { 
     socket = new Socket("localhost", 8000); 
     byteIn = new ByteArrayInputStream(socket.getInputStream()); 
     byteOut = new ByteArrayOutputStream(socket.getOutputStream()); 
     new Thread(() -> run()).start(); 
    } 
    catch (IOException ex) { 
     ex.printStackTrace(); 
    } 
    } 

    public void run(){ 
    while(true) { 
     /*try { 

     } catch (IOException ex) { 
      ex.printStackTrace(); 
     }*/ 
    } 
    } 

    public void process (Canvas canvas) { 
    try { 
     WritableImage image = canvas.snapshot(null, null); 
     BufferedImage bImage = SwingFXUtils.fromFXImage(image, null); 
     ImageIO.write(bImage, "jpg", byteOut); 
     byteOut.flush(); 
     byte[] byteImage = byteOut.toByteArray(); 
     byteOut.close(); 
     byteOut.write(byteImage); 
     } catch (IOException ex) { 
      System.err.println(ex); 
    } 
    } 

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

    private void initDraw(GraphicsContext gc) { 
     double canvasWidth = gc.getCanvas().getWidth(); 
     double canvasHeight = gc.getCanvas().getHeight(); 

     //Event handler when set color button is clicked 
     btSetColor.setOnAction(e -> { 
      if(!(tfRed.getText().trim().isEmpty()) && !(tfGreen.getText().trim().isEmpty()) && 
       !(tfBlue.getText().trim().isEmpty())) { 
       int red = Integer.parseInt(tfRed.getText()); 
       int green = Integer.parseInt(tfGreen.getText()); 
       int blue = Integer.parseInt(tfBlue.getText()); 
       gc.setStroke(Color.rgb(red, green, blue)); 
      } 
     }); 

     gc.setLineWidth(5); 
     gc.fill(); 
     gc.strokeRect(
      0,    //x of the upper left corner of the drawing area 
      0,    //y of the upper left corner of the drawing area 
      canvasWidth, //width of the drawing area 
      canvasHeight); //height of the drawing area 
     gc.setLineWidth(1); 

     //Event handler when reset button is clicked 
     btReset.setOnAction(e -> { 
      gc.clearRect(5, 5, 355, 365); 
     }); 
    } 
} 
+0

*編輯* ---我不需要將GraphicsContext添加到任何其他客戶端的GraphicsContexts中,只需要將GraphicsContext替換爲其他類型。 – seeuuaye08

回答

0

直接發送GraphicsContext是不可能的,因爲GraphicsContext是沒有明確Serializable。下面給出了實現你打算的典型方法。答:請記住用戶操作爲「命令」並將它們發送給服務器/其他客戶端。這些命令將在客戶端執行,並且您將擁有相同的呈現視圖。作爲實現的例子,您可以用您自己的API封裝GraphicsContext API,以創建這些命令。

public void fillOvalX(double x, double y, double w, double h) { 
    // a possible approach 
    commands.put(new DrawCommand(Type.FILL_OVAL, x, y, w, h)); 
    g.fillOval(x, y, w, h); 
} 

B.通過調用snapshot()執行GraphicsContext的快照到一個JavaFX Image。然後使用SwingFXUtils將其轉換爲BufferedImage,最後使用ImageIOByteArrayOutputStream將其轉換爲byte[]。然後可以通過網絡將數組byte[]序列化。在連接的另一端,您需要按相反的順序執行相同的操作。這些鏈接提供了足夠的信息來做到這一點。

+0

非常感謝您的反饋。在我最初在這裏發佈後,我正在研究snapshot()和ByteArrayStreams。我會很快嘗試。 – seeuuaye08

+0

我編輯了代碼以顯示現在卡在哪裏。編輯中說明了我的問題。 – seeuuaye08

相關問題