简体   繁体   中英

How can jButton1ActionPerformed and jButton2ActionPerformed share a BufferedReader/BufferedWriter?

Well I created a program using sockets with the intent for an IRC Client. jButton2 is supposed to submit messages. jButton1 is to connect to the IRC Server. http://i.stack.imgur.com/SiUO7.png Is there any way for me to make the variable public? Any time I try to make it public or private or final or static or move it, there is always some very strange issues.

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

Then the BotListenerThread is to receive and send back ping/pong as well as to put the output text into my textArea but due to it being in a different file I can not seem to find a way to modify the jTextArea from this... Any tips for this??

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

You can't make a local variable public, and you shouldn't make your class fields public, but you can pass any object to another either via a constructor parameter or a setter method. What you would need to do is to pass your GUI object into the BotListenerThread class, and then call public methods on the GUI from within BotListenerThread, taking care to obey Swing's threading rules -- something that I worry about with your code.

ie, change this:

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

to this:

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

And change the BotListenerThread constructor to accept a GUI object and use it to set a field.

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

A better overall solution however is to use MVC and to not to have BotListenerThread directly interact with the View class (the GUI), but rather the BotListenerThread, as part of the "Control", change the state of the Model class -- the class that holds your program logic, and then have Model notify all of its listeners that its state has been changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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