Как jButton1ActionPerformed и jButton2ActionPerformed могут совместно использовать BufferedReader/BufferedWriter?

Ну, я создал программу с использованием сокетов с намерением для IRC-клиента. jButton2 должен отправлять сообщения. JButton1 должен подключиться к IRC-серверу. ли я сделать переменную общедоступной? Каждый раз, когда я пытаюсь сделать его общедоступным, приватным, финальным, статичным или перемещать его, всегда возникают некоторые очень странные проблемы.

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    try {
        String server = jTextField2.getText();
        String nick = jTextField4.getText();
        String login = jTextField5.getText();
        String pass = jTextField6.getText();
        String channel = jTextField3.getText();
        Socket socket = new Socket(server, 6667);
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(socket.getOutputStream()));
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
        writer.write("NICK " + nick + "\r\n");
        writer.write("USER " + login + " 0 * Programming Bot" + "\r\n");
        if (pass.equals("")) {
        } else {
            writer.write("nickserv IDENTIFY " + pass + "\r\n");
            writer.write("ns set autoop on" + "\r\n");
        }
        writer.flush();
        String line;
        while ((line = reader.readLine()) != null) {
            jTextArea1.append(line + "\r\n");
            // 004 indicates we are logged in
            if (line.indexOf("004") >= 0) {
                // We are now logged in so we can leave the loop
                break;
            } else if (line.indexOf("433") >= 0) {
                jTextArea1.append("Nickname is already in use.\r\n");
                return;
            }
        }

        // Join the channel.
        writer.write("JOIN " + channel + "\r\n");
        writer.flush();

        Thread bl = new Thread(new BotListenerThread(reader, writer, channel));
        bl.start();
        writer.write("PRIVMSG dema Hello\u00A0There." + "\r\n");

    } catch (IOException ex) {
        Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
    }

}                                        

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
// Cannot access reader here
//writer.write("PRIVMSG dema "+jTextField1.getText()+"\r\n");
//writer.flush();
}          

Тогда BotListenerThread должен получить и отправить обратно пинг / понг, а также поместить выходной текст в мою textArea, но из-за того, что он находится в другом файле, я не могу найти способ изменить jTextArea из этого... Любого советы для этого??

package ambassadorirc;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;

public class BotListenerThread implements Runnable // threads implement the runnable interface
{
BufferedReader reader;
BufferedWriter writer;
String channel;

// our constructor requires the reader, writer and channel from the main program
public BotListenerThread(BufferedReader reader, BufferedWriter writer, String channel) {
    this.reader = reader;
    this.writer = writer;
    this.channel = channel;
}

public void run() {
    System.out.println("Listener ready...");
    String line = "";
    // Keep reading lines from the server.
    try {
        // again we use the infinite loop
        while ((line = reader.readLine()) != null) 
        {
            if (line.toLowerCase().startsWith("ping ")) {
                // We must respond to PINGs to avoid being disconnected.
                writer.write("PONG " + line.substring(5, line.length()) + "\r\n");                              
                                    // every time you issue a command you MUST flush to send it
                writer.flush();
            }
            // the next lines are a VERY unsafe implementation of an auto-op script ;)
            else if (line.contains("myNich") && line.contains("JOIN :"+channel))
            {
                System.out.println("Opping myNick");
                writer.write("MODE "+channel+" +o myNick\r\n");
                writer.flush();
            }
            else {
                // print the line received from the server
                System.out.println(line);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

1 ответ

Вы не можете сделать локальную переменную общедоступной, и вы не должны делать свои поля класса общедоступными, но вы можете передать любой объект другому либо с помощью параметра конструктора, либо с помощью метода установки. Что вам нужно сделать, это передать ваш объект GUI в класс BotListenerThread, а затем вызвать публичные методы GUI изнутри BotListenerThread, заботясь о соблюдении правил многопоточности Swing - то, что меня беспокоит в вашем коде.

т.е. измени это:

Thread bl = new Thread(new BotListenerThread(reader, writer, channel));

к этому:

// note the difference from the line above
Thread bl = new Thread(new BotListenerThread(reader, writer, channel, this)); 

И измените конструктор BotListenerThread, чтобы он принимал объект GUI и использовал его для установки поля.

public class BotListenerThread implements Runnable  {
  private BufferedReader reader;
  private BufferedWriter writer;
  private String channel;
  private MyGuiClass gui;

  public BotListenerThread(BufferedReader reader, BufferedWriter writer, 
             String channel, MyGuiClass gui) {
    this.reader = reader;
    this.writer = writer;
    this.channel = channel;   
    this.gui = gui;
  }

  // now the gui variable is usable

Однако лучшее общее решение - использовать MVC и не допускать непосредственного взаимодействия BotListenerThread с классом View (GUI); вместо этого BotListenerThread, как часть "Control", изменяет состояние класса Model - класса которая содержит логику вашей программы, и затем Model уведомит всех своих слушателей, что ее состояние было изменено.

Другие вопросы по тегам