简体   繁体   English

GUI没有响应按钮单击

[英]GUI is not responding to button clicks

I'm trying to write a simple port scanner in Java. 我试图用Java编写一个简单的端口扫描程序。 It works, but the entire window stops responding to clicks once the scanning begins. 它可以工作,但是一旦扫描开始,整个窗口将停止响应单击。 This won't allow me to use the stop button to pause the operation or exit the window. 这将不允许我使用“停止”按钮来暂停操作或退出窗口。 Here is my code: 这是我的代码:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

import javax.swing.*;
import java.awt.event.*;
public class GUIScanner {
    JFrame frame = new JFrame("Port Scanner");
    JTextField textField = new JTextField("",20);
    JPanel panel = new JPanel();
    JButton button = new JButton("Scan");
    JButton button2 = new JButton("Stop");
    JLabel label = new JLabel("");
    boolean stopped = false;
public GUIScanner() {
    initialize();
}

public static void main(String[] args) {
    GUIScanner scanner = new GUIScanner();
}

public void initialize() {
    panel.add(textField);
    panel.add(button);
    panel.add(button2);
    frame.add(panel);
    frame.setSize(500, 500);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            String address = textField.getText().toString();
            scanHost(address, 200);
        }
    });
    button2.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            if(!stopped) {
                stopped = true;
                button2.setText("Resume");
            } else {
                stopped = false;
                button2.setText("Stop");
            }
        }
    });
}
public void scanHost(String ip, int timeout) {
    while(!stopped) {
        button2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(!stopped) {
                    stopped = true;
                    button2.setText("Resume");
                } else {
                    stopped = false;
                    button2.setText("Stop");
                }
            }
        });
        for(int port = 0; port <= 65535; port++) {
            frame.setTitle("Scanning port " + port + " of 65535");
            Socket socket = new Socket();
            try {
                socket.connect(new InetSocketAddress(ip, port), timeout);
                socket.close();
                System.out.println(port);
            } catch (IOException e) {

            }
    }
    }
}
}

I'm not sure if the issue is a threading issue or if it is something else in my code. 我不确定该问题是线程问题还是代码中的其他问题。 I'm fairly inexperienced with Java. 我对Java缺乏经验。 I'm using Eclipse Oxygen if that helps. 如果有帮助,我正在使用Eclipse Oxygen。

Welcome to the wonderful world of "Honey, I blocked the Event Dispatching Thread". 欢迎来到“亲爱的,我阻止了事件调度线程”的美好世界。

Start by taking a look at Concurrency in Swing for more of an overview. 首先查看Swing中的并发,以获取更多概述。

Essentially, Swing is single threaded and NOT thread safe. 本质上,Swing是单线程的,并且不是线程安全的。 This means you should never perform long running or blocking operations within the context of the EDT, but also, you should not update the UI from outside of the context of the EDT. 这意味着您永远不要在EDT上下文中执行长时间运行或阻止操作,而且,也不应从EDT上下文之外更新UI。

Instead, you should consider using something like SwingWorker , which allows you to run blocking/long running operations in the background, but provides functionality to publish and process updates in the EDT 相反,您应该考虑使用SwingWorker东西,它允许您在后台运行阻止/长时间运行的操作,但提供在EDT中publishprocess更新的功能。

Use a SwingWorker to run another thread in the background. 使用SwingWorker在后台运行另一个线程。 This prevents Swing from being blocked when you pause the background thread. 这可以防止在您暂停后台线程时阻止Swing。 Here is the corrected version of the port scanner code: 这是端口扫描程序代码的更正版本:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

import javax.swing.*;
import java.awt.event.*;

public class GUIScanner {
    JFrame frame = new JFrame("Port Scanner");
    JTextField textField = new JTextField("", 20);
    JPanel panel = new JPanel();
    JButton button = new JButton("Scan");
    JButton button2 = new JButton("Stop");
    JLabel label = new JLabel("");
    boolean stopped = false;

    PausableSwingWorker<Void, String> scanningWorker;

    abstract class PausableSwingWorker<K, V> extends SwingWorker<K, V> {

        private volatile boolean isPaused;
        final Object lock = new Object();

        public final void pause() {

            if (!isPaused() && !isDone()) {
                isPaused = true;
            }
        }

        public final void resume() {
            if (isPaused() && !isDone()) {
                isPaused = false;
                synchronized(lock) {
                    lock.notify();
                }
            }
        }
        public final boolean isPaused() {
            return isPaused;
        }
    }

    public GUIScanner() {
        initialize();
    }

    public static void main(String[] args) {
        GUIScanner scanner = new GUIScanner();
    }

    public void initialize() {
        panel.add(textField);
        panel.add(button);
        panel.add(button2);
        frame.add(panel);
        frame.setSize(500, 500);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String address = textField.getText().toString();
                scanHost(address, 200);
            }
        });
        button2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!stopped) {
                    stopped = true;
                    button2.setText("Resume");
                    scanningWorker.pause();
                } else {
                    stopped = false;
                    button2.setText("Stop");
                    scanningWorker.resume();
                }
            }
        });
    }

    public void scanHost(String ip, int timeout) {
        scanningWorker = new PausableSwingWorker<Void, String>() {
            @Override
            public Void doInBackground() {

                for (int port = 0; port <= 65535; port++) {
                    if (!isPaused()) {
                        frame.setTitle("Scanning port " + port + " of 65535");
                        Socket socket = new Socket();
                        try {
                            socket.connect(new InetSocketAddress(ip, port), timeout);
                            socket.close();
                            System.out.println("Port " + port + " is open");
                        } catch (IOException e) {
                        }
                    }
                    else {
                        synchronized(lock) {
                            try {
                                lock.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                }
                return null;
            }
            @Override
            public void done() {
            }
        };
    scanningWorker.execute();
    }
}

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

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