简体   繁体   English

使用 sockets 从客户端向服务器发送 JFrame 绘图

[英]Sending a JFrame drawing from Client to Server using sockets

I'm trying to send my java file where I have a JFrame drawing with button that changes the color of the background from Client to Server.我正在尝试发送我的 java 文件,其中我有一个 JFrame 绘图,带有将背景颜色从客户端更改为服务器的按钮。 The server recieves that Drawing and opens it but when I click buttons nothing change.服务器收到该绘图并打开它,但是当我单击按钮时没有任何变化。 What am I doing wrong?我究竟做错了什么? Also for some reason the app doesn't run sometimes.同样由于某种原因,该应用程序有时无法运行。

Code with the drawing带图的代码

package Drawings;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import javax.swing.*;

public class DrawingTwo extends JFrame {


    public static final int DEFAULT_WIDTH = 300;
    public static final int DEFAULT_HEIGHT = 300;

    public Color tvColor;
    public Color smileColor;
    public int h;
    public int h2;
    public int h3;
    public int h4;
    public int h5;
    public int h6;
    public String l;
    public DrawComponent c;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new DrawingTwo();
            }
        });

    }

    public DrawingTwo() {
        super();
        setOneChanell();

        Container container = getContentPane();
        container.setBackground(new Color(242, 212, 252));
        container.setLayout(new BorderLayout(20, 20));
        container.setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));

        ButtonListener listener = new ButtonListener();

        JLabel lb = new JLabel(l);
        lb.setText(l);
        container.add(lb);
        JButton j2 = new JButton("2");
        j2.addActionListener(listener);
        container.add(j2, BorderLayout.NORTH);

        c = new DrawComponent();
        container.add(c, BorderLayout.CENTER);

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }

    public void setOneChanell() {
        this.tvColor = new Color(255, 153, 153);
        this.smileColor = new Color(255, 247, 10);
        this.h = 110;
        this.h2 = 55;
        this.h3 = 60;
        this.h4 = 60;
        this.h5 = 0;
        this.h6 = -180;
        this.l = "Канал для веселых";
    }

    public void setTwoChanell() {
        this.tvColor = new Color(172, 194, 157);
        this.smileColor = new Color(0, 161, 219);
        this.h = 115;
        this.h2 = 87;
        this.h3 = 50;
        this.h4 = 40;
        this.h5 = 0;
        this.h6 = +180;
        this.l = "Канал для грустных";
    }

    public class DrawComponent extends JComponent {

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.black);
            g.fillRect(37, 26, 210, 130);

            g.setColor(tvColor);
            g.fillRect(42, 30, 200, 120);

            g.setColor(Color.darkGray);
            g.fillRect(135, 156, 15, 20);

            g.setColor(Color.darkGray);
            g.fillRect(83, 170, 120, 13);


            g.setColor(smileColor);
            g.fillOval(100, 45, 80, 80);


            g.setColor(Color.BLACK);
            g.drawArc(120, 70, 10, 10, 0, 360);
            g.drawArc(150, 70, 10, 10, 0, 360);

            g.drawString(l, 83, 200);
            g.setColor(Color.BLACK);
            g.drawArc(h, h2, h3, h4, h5, h6);
        }

    }

    public class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent event) {
            JButton button = (JButton) event.getSource();
            if (button.getText().equals("2")) {
                setTwoChanell();
                button.setText("1");

            } else {
                setOneChanell();
                button.setText("2");
            }
            c.repaint();
        }

    }

}


THis is Client file这是客户端文件

package ClientToServer;

import java.io.*;

import java.net.Socket;

import Drawings.DrawingTwo;


public class Client {

    public static void main(String[] args) throws IOException {

        Socket socket = new Socket("localhost", 12345);
        OutputStream outputStream = socket.getOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(new DrawingTwo());
        objectOutputStream.flush();
        objectOutputStream.close();
    }


}

This is Server file这是服务器文件

package ClientToServer;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

import Drawings.DrawingTwo;

import javax.swing.*;

public class Server {



    public static void main(String[] args) throws IOException, ClassNotFoundException {

        ServerSocket serverSocket = new ServerSocket(12345);
        Socket client = serverSocket.accept();
        ObjectInputStream inputStream = new ObjectInputStream(client.getInputStream());

        DrawingTwo object = (DrawingTwo) inputStream.readObject();
        object.setVisible(true);
        object.setTitle("Server");
        object.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        client.close();
        inputStream.close();
        serverSocket.close();
    }
}

I suggest you to read about socket communications a bit more.我建议您多阅读有关套接字通信的内容。 If you have a server socket, it should run all the time.如果你有一个服务器套接字,它应该一直运行。 In your code you close your socket connection right after you receive the data from client.在您的代码中,您在收到来自客户端的数据后立即关闭您的套接字连接。

Another thing is;另一件事是; you have limited your communication with only one type: DrawingTwo() class.您只使用一种类型限制了您的通信:DrawingTwo() class。 On your server side, you cannot receive any other data.在您的服务器端,您无法接收任何其他数据。

Let's take a look step by step on your code.让我们逐步看一下您的代码。

You must define a new object for communication purposes您必须定义一个新的 object 用于通信目的

import java.io.Serializable;

public class CommunicationObject implements Serializable{
    
    private DrawingTwo mDrawingTwo;
    private boolean mSmileyFace = true;
    private boolean mIsInitialConnection = true;
    
    
    public DrawingTwo getmDrawingTwo() {
        return mDrawingTwo;
    }
    public void setmDrawingTwo(DrawingTwo mDrawingTwo) {
        this.mDrawingTwo = mDrawingTwo;
    }
    public boolean ismSmileyFace() {
        return mSmileyFace;
    }
    public void setmSmileyFace(boolean mSmileyFace) {
        this.mSmileyFace = mSmileyFace;
    }
    public boolean ismIsInitialConnection() {
        return mIsInitialConnection;
    }
    public void setmIsInitialConnection(boolean mIsInitialConnection) {
        this.mIsInitialConnection = mIsInitialConnection;
    }   
}

You have 3 fields here.您在这里有 3 个字段。

  1. DrawingTwo;绘图二; is your actual layout是你的实际布局
  2. boolean SmileyFace; boolean 笑脸; indicates your button's situation指示您的按钮的情况
  3. boolean IsInitialConnection; boolean IsInitialConnection; decides whether it is initialization so your Server inits layout or changes the smiley face决定是否初始化,以便您的服务器初始化布局或更改笑脸

Your server must listen all the time您的服务器必须一直监听

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JFrame;

public class Server {

    static boolean isRunning = true;

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ServerSocket serverSocket = new ServerSocket(12345);
        Socket client = null;
        ObjectInputStream inputStream = null;
        InputStream is = null;
        DrawingTwo drawingTwo = null;
        CommunicationObject communicationObject = null;

        while (isRunning) {
            client = serverSocket.accept();
            inputStream = new ObjectInputStream(client.getInputStream());

            is = client.getInputStream();

            communicationObject = (CommunicationObject) inputStream.readObject();

            if (communicationObject.ismIsInitialConnection()) {
                drawingTwo = (DrawingTwo) communicationObject.getmDrawingTwo();
                drawingTwo.setVisible(true);
                drawingTwo.setTitle("Server");
                drawingTwo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            } else {                

                if (communicationObject.ismSmileyFace()) {
                    drawingTwo.setOneChanell();                     
                } else {
                    drawingTwo.setTwoChanell();                     
                }
                drawingTwo.c.repaint();

            }

        }
        client.close();
        inputStream.close();
        serverSocket.close();
    }
}

Please note that isRunning is always true now.请注意isRunning现在总是正确的。 You must handle the exceptions and other situations to stop it or restart it.您必须处理异常和其他情况才能停止或重新启动它。

Create a getter for your JButton in your DrawingTwo class在您的 DrawingTwo class 中为您的 JButton 创建一个吸气剂

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeListener;

public class DrawingTwo extends JFrame{

      public static final int DEFAULT_WIDTH = 300;
        public static final int DEFAULT_HEIGHT = 300;

        public Color tvColor;
        public Color smileColor;
        public int h;
        public int h2;
        public int h3;
        public int h4;
        public int h5;
        public int h6;
        public String l;
        public DrawComponent c;
        
        
        private JButton j2;
        
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new DrawingTwo();
                }
            });

        }
        
        public DrawingTwo() {
            super();
            setOneChanell();

            Container container = getContentPane();
            container.setBackground(new Color(242, 212, 252));
            container.setLayout(new BorderLayout(20, 20));
            container.setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));

            ButtonListener listener = new ButtonListener();

            JLabel lb = new JLabel(l);
            lb.setText(l);
            container.add(lb);
            j2 = new JButton("2");
            j2.addActionListener(listener);
            container.add(j2, BorderLayout.NORTH);

            c = new DrawComponent();
            container.add(c, BorderLayout.CENTER);

            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            pack();
            setVisible(true);
                        
           
        }
        
        public void setOneChanell() {
            this.tvColor = new Color(255, 153, 153);
            this.smileColor = new Color(255, 247, 10);
            this.h = 110;
            this.h2 = 55;
            this.h3 = 60;
            this.h4 = 60;
            this.h5 = 0;
            this.h6 = -180;
            this.l = "1";
        }

        public void setTwoChanell() {
            this.tvColor = new Color(172, 194, 157);
            this.smileColor = new Color(0, 161, 219);
            this.h = 115;
            this.h2 = 87;
            this.h3 = 50;
            this.h4 = 40;
            this.h5 = 0;
            this.h6 = +180;
            this.l = "2";
        }
                
        public JButton getJButton() {
            return j2;
        }


        public class DrawComponent extends JComponent {
            
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.black);
                g.fillRect(37, 26, 210, 130);

                g.setColor(tvColor);
                g.fillRect(42, 30, 200, 120);

                g.setColor(Color.darkGray);
                g.fillRect(135, 156, 15, 20);

                g.setColor(Color.darkGray);
                g.fillRect(83, 170, 120, 13);


                g.setColor(smileColor);
                g.fillOval(100, 45, 80, 80);


                g.setColor(Color.BLACK);
                g.drawArc(120, 70, 10, 10, 0, 360);
                g.drawArc(150, 70, 10, 10, 0, 360);

                g.drawString(l, 83, 200);
                g.setColor(Color.BLACK);
                g.drawArc(h, h2, h3, h4, h5, h6);
            }

        }
        
        public class ButtonListener implements ActionListener {

            @Override
            public void actionPerformed(ActionEvent event) {
                JButton button = (JButton) event.getSource();
                if (button.getText().equals("2")) {
                    setTwoChanell();
                    button.setText("1");

                } else {
                    setOneChanell();
                    button.setText("2");
                }
                c.repaint();
            }

        }
}

Remember that you have 2 functionalities for your button请记住,您的按钮有 2 个功能

  1. Change the layout on your client, which you have already handled更改您已经处理过的客户端上的布局
  2. Send the signal to your server, so it can change it too将信号发送到您的服务器,以便它也可以更改它

At last, the Client class.最后是客户端 class。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;

public class Client {
    
    static OutputStream outputStream;
    static ObjectOutputStream objectOutputStream;
    static Socket socket;    
    
    public static void main(String[] args) throws UnknownHostException, IOException {
        
        DrawingTwo drawingTwo = new DrawingTwo();
        
        CommunicationObject communicationObject = new CommunicationObject();        
        communicationObject.setmDrawingTwo(drawingTwo);
        communicationObject.setmIsInitialConnection(true);
        
        write(communicationObject);
                
        JButton button = drawingTwo.getJButton();
        
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {

                try {
                    if (button.getText().equals("2")) {
                        
                        communicationObject.setmIsInitialConnection(false);
                        communicationObject.setmSmileyFace(false);
                        write(communicationObject);
                    } else {
                        communicationObject.setmIsInitialConnection(false);
                        communicationObject.setmSmileyFace(true);
                        write(communicationObject);
                    }
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
        });
    }
    
    
    public static void write(CommunicationObject comObject) throws IOException
    {       
        socket = new Socket("localhost", 12345);
        
        outputStream = socket.getOutputStream();
        objectOutputStream = new ObjectOutputStream(outputStream);
                
        objectOutputStream.writeObject(comObject);
        
        objectOutputStream.flush();     
        objectOutputStream.close();
    }   
}

You create a CommunicationObject here and assign your DrawingTwo class to it.您在此处创建一个 CommunicationObject 并将您的 DrawingTwo class 分配给它。

Take a look where you extract the JButton from DrawingTwo into Client class, so you can bind ActionListener to it.看一下从DrawingTwo中将JButton提取到客户端class 的位置,以便您可以将 ActionListener 绑定到它。 From this action listener you can now communicate with your server.通过这个动作监听器,您现在可以与您的服务器进行通信。

NOTE Since both Client and Server has access to DrawingTwo, you don't need to send whole class via socket.注意由于客户端和服务器都可以访问 DrawingTwo,因此您不需要通过套接字发送整个 class。 Just send a message to Server, that it should create an instance by itself.只需向服务器发送一条消息,它应该自己创建一个实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM