1

例如,在下面的代码中,我想更改 JTextField 以显示端口即时扫描是否打开,但我不知道该怎么做。也许我需要一些辅助方法?

public void actionPerformed(ActionEvent arg0) {
  console.setText("Starting check\n" +
    "Start = "+stopServTf.getText()+
    "\nStop ="+stopServTf.getText()+
    "\nPort Start ="+startPortTf.getText()+
    "\nPort Stop ="+stopPortTf.getText());
  PortScanner p= new PortScanner(Integer.parseInt(startPortTf.getText()),
    Integer.parseInt(stopPortTf.getText()),startServTf.getText());
}

和其他方法/构造函数

public   PortScanner(int portStart, int portStop ,String ip) {
  for (int i = portStart; i <= portStop; i++) {
    try {
      Socket ServerSok = new Socket(ip, i);
      setString(i);
      //System.out.println("Port in use: " + i);
      ServerSok.close();
    } catch (Exception e) {
    }
    setStrinN(i);
    System.out.println("Port not in use: " + i);
  }
}

public static String setString(int i) {
  return "Port in use: " +i;
}

public static String setStrinN(int i){
  return "Port not in use: "+i;
} 

所以我想发送给console.setText();

4

3 回答 3

4

建议:

  • 请务必在与 Swing GUI 相关的后台线程中进行端口扫描,例如 SwingWorker 提供的一个。
  • 更新任何 Swing 组件时,请务必在 Swing 事件线程(EDT)上执行此操作。同样,SwingWorker 将有所帮助,因为它具有自动化此(发布/处理)的设施。
  • 为您的 GUI 类提供一个公共方法,允许外部类更新其文本字段,例如public void consoleSetText(String text)
  • 将 GUI 类的引用传递给助手类,以便助手类可以调用上述方法。它当然会使用 SwingWorker 方法调用 Swing 事件线程上的process(...)方法。

编辑1
这是我建议的一个例子:

class PortScannerGui {
   private JTextField startPortTf;
   private JTextField stopPortTf;
   private JTextField console;
   private JTextField stopServTf;
   private JTextField startServTf;

   // ... lots of code mising

   public void actionPerformed(ActionEvent arg0) {
      console.setText("Starting check\n" + "Start = " + stopServTf.getText()
            + "\nStop =" + stopServTf.getText() + "\nPort Start ="
            + startPortTf.getText() + "\nPort Stop =" + stopPortTf.getText());

      new SwingWorkerPortScannerWrapper(this, 
            Integer.parseInt(startPortTf.getText()), 
            Integer.parseInt(stopPortTf.getText()),
            startServTf.getText()).execute();
   }

   public void setConsoleText(String text) {
      console.setText(text);
   }
}

class SwingWorkerPortScannerWrapper extends SwingWorker<Void, Integer> {
   private PortScannerGui gui;
   private PortScanner portScanner;

   public SwingWorkerPortScannerWrapper(PortScannerGui gui, int portStart,
         int portStop, String ip) {
      this.gui = gui;
      portScanner = new PortScanner(portStart, portStop, ip);
   }

   @Override
   protected Void doInBackground() throws Exception {
      portScanner.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent evt) {
            if (PortScanner.PORT_IN_USE_NUMBER.equals(evt.getPropertyName())) {
               publish((Integer) evt.getNewValue());
            }
         }
      });

      portScanner.scan();
      return null;
   }

   @Override
   protected void process(List<Integer> chunks) {
      for (Integer chunk : chunks) {
         gui.setConsoleText("Port in use: " + chunk);
      }
   }
}

class PortScanner {
   public static final String PORT_IN_USE_NUMBER = "port in use number";
   public static final String STRIN_N = "strinN";
   private int portStart;
   private int portStop;
   private String ip;
   private int string;
   private PropertyChangeSupport propChangeSupport = new SwingPropertyChangeSupport(
         this);
   private int portInUseNumber;

   public PortScanner(int portStart, int portStop, String ip) {
      this.portStart = portStart;
      this.portStop = portStop;
      this.ip = ip;

   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      propChangeSupport.addPropertyChangeListener(listener);
   }

   public void scan() {
      for (int i = portStart; i <= portStop; i++) {
         try {
            Socket ServerSok = new Socket(ip, i);

            setPortInUseNumber(i);
            // System.out.println("Port in use: " + i);

            ServerSok.close();
         } catch (UnknownHostException e) {
            e.printStackTrace();
         } catch (IOException e) {
            e.printStackTrace();
         }
         setStrinN(i);
         System.out.println("Port not in use: " + i);
      }
   }

   public void setStrinN(int i) {
      // TODO do something with this?
   }

   public void setPortInUseNumber(int i) {
      int oldValue = portInUseNumber;
      int newValue = i;
      portInUseNumber = i;
      propChangeSupport.firePropertyChange(PORT_IN_USE_NUMBER, oldValue,
            newValue);
   }

}
于 2012-05-27T13:36:47.140 回答
2

您需要能够访问您的JTextField实例,有两种方法:

  • PortScanner将变量作为局部变量传递给类
  • 对包含文本字段的框架(或文本字段本身)有一个静态引用,以便您可以从任何地方访问它

第一种方式更正确,因为它保持封装,第二种方式更容易和简单,但在不需要如此严重的情况下也会将字段暴露给外部,这在 OOP 环境中是一个糟糕的设计选择。

于 2012-05-27T13:38:11.970 回答
1

当您调用setString(i);时,该函数会返回一个您丢弃的字符串(即不要存储在任何地方)。您要么需要存储字符串并稍后检索它,否则如果您想console.setText()使用返回的字符串进行调用,则需要传递consolePortScanner构造函数:

public PortScanner(int portStart, int portStop, String ip, JTextArea console)

并将呼叫更改setString(i);

console.setText(setString(i));

此外(由于PortScanner构造函数已更改),请调用

 PortScanner p= new PortScanner(Integer.parseInt(startPortTf.getText()),
   Integer.parseInt(stopPortTf.getText()),startServTf.getText()); 

actionPerformed()

于 2012-05-27T13:36:06.720 回答