【问题标题】:add jbutton at runtime在运行时添加 jbutton
【发布时间】:2014-04-04 18:01:53
【问题描述】:

我正在构建一个关于 Socket 编程的应用程序,其中服务器侦听客户端,如果客户端已连接,我想要

  • 如果在服务器屏幕上连接,则应为每个客户端添加一个按钮

  • 在每个按钮上添加监听器。例如为每个客户端添加发送消息功能

我在服务器中创建了一个线程来侦听客户端连接,但我无法在运行时添加 jbutton。

请回复。

【问题讨论】:

  • 到目前为止你得到了什么代码?您想要填充的面板是什么样的?您应该考虑每个新客户端连接的连接数以及窗格的拥挤程度。
  • 当然整个套接字编程系统与你的问题无关。制作一个小测试程序,当用户按下(“静态”)按钮时,新组件(如更多按钮)会动态添加到 GUI。尝试这样做并返回特定问题。更何况这个问题已经被问过很多次了:bit.ly/Oi7EUi
  • 嗨,我已经用两个客户端测试了这个程序。服务器成功连接到两个客户端。但是在运行时不会为每个客户端添加按钮。

标签: java swing sockets client-server jbutton


【解决方案1】:

这是你需要的吗? :

import javax.swing.*;

import java.awt.event.*;

public class NewButtonOnRunTime {
static JPanel panel;

static JFrame frame;

public static void main(String[] args){
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            frame = new JFrame("Add Buttons");

            JButton button = new JButton("Simulate new Client");
            button.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e)
                {
                    JButton jb = new JButton("A new Client");
                    jb.addActionListener(new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                            JOptionPane.showMessageDialog(null, "This is an button action");

                        }
                    });
                    panel.add(jb);
                    frame.revalidate();
                }
            });
            panel = new JPanel();
            panel.add(button);
            frame.add(panel);
            frame.setSize(400, 400);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        }
    });
}   

}

【讨论】:

  • 你没有在你的主目录中调用invokeLater。看Siwng's Hello World
  • @DSquare 确实是您的权利,但这只是一个虚拟示例。而且这里的可执行文件是自包含的。
  • 我不知道“可执行文件是自包含的”是如何相关的。 Swing 代码必须在 EDT 中执行。即使是最简单的 -dummy- 程序,HelloWorld 也必须这样做,没有办法绕过它。不这样做会使这成为一个不好的例子,尤其是对于新手。
  • @DSquare 你去吧
  • 您好,感谢您的回复。我有一个扩展 JFrame 类的类,并且我在 main 方法中创建了一个线程来接受客户端连接。从线程中我添加了 JButton 但它没有被添加。
【解决方案2】:

假设你已经有某种 isConnected bool,

if(isConnected){

JButton runTimeButton = new JButton();

runTimeButton.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {

        //do all the things you need to do in here,
        //alternatively, define this inner class somewhere else and pass in
        // an instance of it

        }
    });


frame.add(runTimeButton);


}

【讨论】:

  • 不,您还必须致电frame.revalidate()
  • 您不应该在按钮上使用 MouseListener,用户也可以使用键盘激活按钮。应在 EDT 的上下文中更新 UI。在可能的情况下,您应该避免将内容直接添加到顶级容器
【解决方案3】:

基于 Java 中的 ServerSocket 通信(即 TCP),如果客户端使用特定端口(例如 5555)连接到服务器,则其他客户端将无法同时使用相同端口连接到服务器,因为该端口已在使用中。因此,如果您想与客户端同时通信,每个客户端都应该使用不同的端口。

看看这个示例代码,它在连接新客户端时在运行时添加JButton: (在连接在一起的不同机器上运行客户端代码和服务器代码)

服务器代码

package com.test.socket;

import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;

public class ServerFrame extends JFrame {

    private Map<Integer, SocketVO> serverSocketMap;
    private int startingPort = 5555;

    public ServerFrame() {
    }

    public ServerFrame(String title) {
        super(title);
        setSize(Toolkit.getDefaultToolkit().getScreenSize());
        setLayout(new FlowLayout());
        initComponents();
        serverSocketMap = new HashMap<Integer, SocketVO>();
        keepStartServerSocket();
        setVisible(true);
    }

    private JTextArea area = null;

    private void initComponents() {

        area = new JTextArea(20, 20);
        add(area);
        // addDynamicButton();
    }

    private void addDynamicButton(final int port) {
        JButton button = new JButton("Client on " + port + " port");
        add(button);
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {
                Socket socket = serverSocketMap.get(port).getSocket();
                try {
                    String content = area.getText();
                    socket.getOutputStream().write(content.getBytes());

                    System.out.println("seding text area content to " + port);
                    System.out.println(content);

                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        });
    }

    class SocketVO {
        private ServerSocket serverSocket;
        private Socket socket;

        public ServerSocket getServerSocket() {
            return serverSocket;
        }

        public void setServerSocket(ServerSocket serverSocket) {
            this.serverSocket = serverSocket;
        }

        public Socket getSocket() {
            return socket;
        }

        public void setSocket(Socket socket) {
            this.socket = socket;
        }

    }

    private void keepStartServerSocket() {

        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    System.out.println("waiting for a client at port "
                            + startingPort);
                    openServerSocket(startingPort);
                    startingPort++;
                }
            }
        }).start();

    }

    private void openServerSocket(final int port) {

        ServerSocket serverSocket = null;

        try {

            serverSocket = new ServerSocket(port);
            final Socket socket = serverSocket.accept();
            SocketVO socketVO = new SocketVO();
            socketVO.setServerSocket(serverSocket);
            socketVO.setSocket(socket);
            serverSocketMap.put(port, socketVO);
            addDynamicButton(port);

            checkForCosing(port, socket);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void checkForCosing(final int port, final Socket socket) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                InputStream inputStream = null;
                try {
                    inputStream = socket.getInputStream();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

                byte[] b = new byte[1024];
                int read = 0;
                try {
                    StringBuilder builder = new StringBuilder();
                    while ((read = inputStream.read(b)) != -1) {
                        builder.append(new String(b));
                    }
                    if (builder.toString().equals("close")) {
                        closeServerSocket(port);
                        System.out.println("server port " + port + " closed");
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * the method to close corresponding sockets
     * 
     * @param port
     */
    private void closeServerSocket(int port) {

        Socket socket = serverSocketMap.get(port).getSocket();
        ServerSocket serverSocket = serverSocketMap.get(port).getServerSocket();
        try {
            socket.close();
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        new ServerFrame("Server Socket Frame");
    }

}

客户端代码:

package com.test.socket;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
    private int startingPort = 5550;


    private void bindToServer() {
        while(true) {
            try {
                Socket socket = new Socket("127.0.0.1", startingPort);
                InputStream inputStream = null;
                try {
                    inputStream = socket.getInputStream();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }

                byte[] b = new byte[1024];
                int read = 0;
                try {
                    StringBuilder builder = new StringBuilder();
                    while((read = inputStream.read(b)) != -1) {
                        builder.append(new String(b));
                    }
                    System.out.println("message from server : "+builder);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                startingPort++;
            }

            if (startingPort == 5580) {

            }
        }


    }

    public static void main(String[] args) {
        new Client().bindToServer();
    }
}

【讨论】:

    【解决方案4】:

    根据您的最后评论:

    我已经用两个客户端测试了这个程序。服务器成功连接到两个客户端。但不会在运行时为每个客户端添加按钮。

    您可以连接多个客户端,并且您还添加了一个按钮,但它在服务器上不可见。

    JFrame 上再次调用validate() 将在添加新的JButton 后解决您的问题。

    【讨论】:

    • 重新验证(或无效/验证。如果它不可用)将是首选,因为它不会使窗口闪烁
    • 非常感谢。 validate() 完美运行。我已经在我的帖子中更新了。
    【解决方案5】:
    public class Test extends JFrame {
    
    private JButton field[];
    
    public JButton[] getField() {
        return field;
    }
    
    public void test(int n) {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(0, 1));
        field = new JButton[n];
        for (int i = 0; i < field.length; i++) {
            field[i] = new JButton("" + i + "");
            field[i].addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    System.out.println("clicked button");
                }
            });
            panel.add(field[i]);
        }
        add(panel);
    }
    
    public static void main(String[] args) {
        Test test = new Test();
        test.setSize(300, 300);
        test.setVisible(true);
        test.setLocationRelativeTo(null);
        test.test(5);
    }
    

    }

    【讨论】:

    • 这没有什么动态的,OP想要在某个事件发生时添加按钮,而不是在构造函数中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多