首页 > 解决方案 > 使用套接字将 JFrame 绘图从客户端发送到服务器

问题描述

我正在尝试将我的 java 文件发送到其中我有一个带有按钮的 JFrame 绘图,该按钮将背景颜色从客户端更改为服务器。服务器收到该绘图并打开它,但是当我单击按钮时没有任何变化。我究竟做错了什么?同样由于某种原因,该应用程序有时无法运行。

带图的代码

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();
        }

    }

}


这是客户端文件

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();
    }


}

这是服务器文件

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();
    }
}

标签: javaswingsocketsjframe

解决方案


我建议您多阅读有关套接字通信的内容。如果你有一个服务器套接字,它应该一直运行。在您的代码中,您在收到来自客户端的数据后立即关闭您的套接字连接。

另一件事是;您只使用一种类型限制了您的交流:DrawingTwo() 类。在您的服务器端,您无法接收任何其他数据。

让我们逐步看一下您的代码。

您必须为通信目的定义一个新对象

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;
    }   
}

您在这里有 3 个字段。

  1. 绘图二;是你的实际布局
  2. 布尔笑脸;指示您的按钮的情况
  3. 布尔 IsInitialConnection; 决定是否初始化,以便您的服务器初始化布局或更改笑脸

您的服务器必须一直监听

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();
    }
}

请注意isRunning现在总是正确的。您必须处理异常和其他情况才能停止或重新启动它。

在您的 DrawingTwo 类中为您的 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();
            }

        }
}

请记住,您的按钮有 2 个功能

  1. 更改您已经处理过的客户端上的布局
  2. 将信号发送到您的服务器,以便它也可以更改它

最后是客户端类。

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();
    }   
}

您在此处创建一个 CommunicationObject 并将您的 DrawingTwo 类分配给它。

看一下从DrawingTwo中将JButton提取到Client类中的位置,以便将 ActionListener 绑定到它。通过这个动作监听器,您现在可以与您的服务器进行通信。

注意 由于客户端和服务器都可以访问 DrawingTwo,因此您不需要通过套接字发送整个类。只需向服务器发送一条消息,它应该自己创建一个实例。


推荐阅读