Suwak + przesuwanie tekstu w TekstArea

0

Mam probrlem z programem. Nie do konca znam Javę, muszę z niej korzystać ze względu na wymagania przedmiotowe.

Do napisania miałem klient czata i server, na którym ten czat stoi. Serwer mam napisany - działa idealnie.

Z klientem mam jeden problem: w TextArea, w którym wyświetla się tekst rozmów nie mam suwaka i opcji, która pozwoli na automatyczne przesuwanie tekstu do dołu (tak jak np. w GG).

Proszę o pomoc. Czytałem wiele przykładów i nic nie pomogło.

Kod Klienta czata:


// $Id$

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;

import java.util.*;

public class CzatKlient extends JFrame
{
  // Components for the visual display of the chat windows
  private JTextField wiadomosc = new JTextField();
  private JTextArea tekst = new JTextArea();
  private JTextField adres = new JTextField();
  private JTextField adresportu = new JTextField();
  // The socket connecting us to the server
  private static Socket socket;

  // The streams we communicate to the server; these come
  // from the socket
  private static DataOutputStream dout;
  private static DataInputStream din;
  String host;
  int port;
  static int znak=0;
  static String napis="Połącz";
  static String nick;

 
  void DemoButton_actionPerformed(ActionEvent e) {
		processMessage(wiadomosc.getText());
		wiadomosc.setText( "" );
	  }
  private static void processMessage( String message ) 
  {
	  try {
	    	message= nick +": " + message;
	    	dout.writeUTF( message );
	  	  } 
	  catch( IOException ie ) { System.out.println( ie ); }
	  
  }
 
  

 
public static void main(String[] args)
{
  	JFrame frame = new JFrame("Czat");
	frame.setSize(400,600);
	
	JLabel label1 = new JLabel();
	label1.setBounds(10, 10, 300, 20);
	label1.setText("Wpisz adres serwera:");
	
	
	JTextField portu = new JTextField();
	portu.setBounds(235,10,40,20);
	portu.setText("1234");
	
	JTextField adres = new JTextField();
	adres.setBounds(150,10,80,20);
	adres.setText("127.0.0.1");
	
	final JButton przycisk = new JButton();
	przycisk.setBounds(280,10,80,20);
	przycisk.setText(napis);
	
	JTextArea tekst = new JTextArea(380,480);
	tekst.setBounds(10, 55, 380, 480);
	tekst.setEditable(false);	
	tekst.setAutoscrolls(true);
	tekst.setLineWrap(true);
	tekst.setWrapStyleWord(true);
	tekst.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
	
	
	JTextField polenick = new JTextField();
	polenick.setBounds(15,33,80,20);
	polenick.setText("nick");
	
	final JTextField wiadomosc = new JTextField();
	wiadomosc.setBounds(10, 540, 380, 20);

	
	Container ct = frame.getContentPane();

	ct.setLayout(null);
	

	ct.add(label1);
	ct.add(portu);
	ct.add(adres);
	ct.add(przycisk);
	ct.add(tekst);
	ct.add(polenick);
	ct.add(wiadomosc);

	
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setVisible(true);
	
wiadomosc.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { processMessage(e.getActionCommand()); wiadomosc.setText(""); } } );


przycisk.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) 
{ 
	if (znak==0) 
	{
		znak=1;	
	} 
	else 
	{
		znak=0;
		try {
			napis="Połącz";
			przycisk.setText(napis);
			socket.close();
	} 
	catch (IOException e1) {
	
	e1.printStackTrace();
}} } } );

while(true)
{
	
if (znak==1)
	{
   String host=adres.getText();
   int port=Integer.parseInt(portu.getText()); 
   nick=polenick.getText();
   
   			try 
   			{		
	   		napis="Rozłącz";
    		przycisk.setText(napis);
    		socket = new Socket( host, port );

    		System.out.println( "connected to "+socket );

    		din = new DataInputStream( socket.getInputStream() );
    		dout = new DataOutputStream( socket.getOutputStream() );
	      
    		//new Thread().start();
	      	} 
   			catch( IOException ie ) { System.out.println( ie ); }
	        
		    try 
		    {
		      while (true) 
		      { 
		        String message = din.readUTF();
		        tekst.append( message+"\n" ); 
		      }
		    }
		    catch( IOException ie ) { System.out.println( ie ); 
		    
		    }
		    } //koniec ifa
		 

	} //koniec while'a
}

} //koniec klasy

Kod serwera (musi być wywoływany z terminala - pierwszy argument: port na którym ma stać serwer, np. java Server 1234)

// $Id$

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;

public class Server
{
  // The ServerSocket we'll use for accepting new connections
  private ServerSocket ss;

  // A mapping from sockets to DataOutputStreams.  This will
  // help us avoid having to create a DataOutputStream each time
  // we want to write to a stream.
  private Hashtable outputStreams = new Hashtable();

  // Constructor and while-accept loop all in one.
  public Server( int port ) throws IOException {

    // All we have to do is listen
    listen( port );
  }

  private void listen( int port ) throws IOException {

    // Create the ServerSocket
    ss = new ServerSocket( port );

    // Tell the world we're ready to go
    System.out.println( "Listening on "+ss );

    // Keep accepting connections forever
    while (true) {

      // Grab the next incoming connection
      Socket s = ss.accept();

      // Tell the world we've got it
      System.out.println( "Connection from "+s );

      // Create a DataOutputStream for writing data to the
      // other side
      DataOutputStream dout = new DataOutputStream( s.getOutputStream() );

      // Save this stream so we don't need to make it again
      outputStreams.put( s, dout );

      // Create a new thread for this connection, and then forget
      // about it
      new ServerThread( this, s );
    }
  }

  // Get an enumeration of all the OutputStreams, one for each client
  // connected to us
  Enumeration getOutputStreams() {
    return outputStreams.elements();
  }

  // Send a message to all clients (utility routine)
  void sendToAll( String message ) {

    // We synchronize on this because another thread might be
    // calling removeConnection() and this would screw us up
    // as we tried to walk through the list
    synchronized( outputStreams ) {

      // For each client ...
      for (Enumeration e = getOutputStreams(); e.hasMoreElements(); ) {

        // ... get the output stream ...
        DataOutputStream dout = (DataOutputStream)e.nextElement();

        // ... and send the message
        try {
        	String dopliku=message+"\n";
          dout.writeUTF( message );
          
          FileChannel fc= new RandomAccessFile("logi.txt","rw").getChannel();
          fc.position(fc.size());
          fc.write(ByteBuffer.wrap(dopliku.getBytes()));
          fc.close();
          
        } catch( IOException ie ) { System.out.println( ie ); }
      }
    }
  }

  // Remove a socket, and it's corresponding output stream, from our
  // list.  This is usually called by a connection thread that has
  // discovered that the connectin to the client is dead.
  void removeConnection( Socket s ) {

    // Synchronize so we don't mess up sendToAll() while it walks
    // down the list of all output streamsa
    synchronized( outputStreams ) {

      // Tell the world
      System.out.println( "Removing connection to "+s );

      // Remove it from our hashtable/list
      outputStreams.remove( s );

      // Make sure it's closed
      try {
        s.close();
      } catch( IOException ie ) {
        System.out.println( "Error closing "+s );
        ie.printStackTrace();
      }
    }
  }

  // Main routine
  // Usage: java Server <port>
  static public void main( String args[] ) throws Exception {

    // Get the port # from the command line
    int port = Integer.parseInt( args[0] );

    // Create a Server object, which will automatically begin
    // accepting connections.
    new Server( port );
  }
}

Do uruchmienia serwera jest porzebna klasa ServerThread:

// $Id$

import java.io.*;
import java.net.*;

public class ServerThread extends Thread
{
  // The Server that spawned us
  private Server server;

  // The Socket connected to our client
  private Socket socket;

  // Constructor.
  public ServerThread( Server server, Socket socket ) {

    // Save the parameters
    this.server = server;
    this.socket = socket;

    // Start up the thread
    start();
  }

  // This runs in a separate thread when start() is called in the
  // constructor.
  public void run() {

    try {

      // Create a DataInputStream for communication; the client
      // is using a DataOutputStream to write to us
      DataInputStream din = new DataInputStream( socket.getInputStream() );

      // Over and over, forever ...
      while (true) {

        // ... read the next message ...
        String message = din.readUTF();

        // ... tell the world ...
        System.out.println( "Sending "+message );

        // ... and have the server send it to all clients
        server.sendToAll( message );
      }
    } catch( EOFException ie ) {

      // This doesn't need an error message
    } catch( IOException ie ) {

      // This does; tell the world!
      ie.printStackTrace();
    } finally {

      // The connection is closed for one reason or another,
      // so have the server dealing with it
      server.removeConnection( socket );
    }
  }
}
		
0

Dodaj coś takiego:

JScrollPane sp=new JScrollPane(tekst);
//i ewentualnie coś takiego
sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
//i zamień add(tekst) na
add(sp);
0

OK. Suwak już jest. Ma stały rozmiar, co jest małym minusem, ale ok.

Co zrobić, by ostatnio wpisany tekst był zawsze widoczny (przesuwanie widoku w TextArea, by zawwze bylo widać ostatni wpis)?

0

Fragmenty po zmianach:

JScrollPane sp=new JScrollPane(tekst);
	sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
	sp.setBounds(10,55,380,480);
...
ct.add(sp);
0
  1. Na razie nie wiem jak zapewmić widoczność nowo dopisanego tekstu(zainteresowało mnie to).
  2. Jaki masz system i jaką wersję Javy ? W każdym programie, który napisałem lub oglądałem rozmiar
    suwaka się zmieniał.
  3. Jeśli masz w miarę nową Javę (1.5 na pewno starczy), to nie musisz korzystać z metody
    getContentPane(), po prostu piszesz (w konstruktorze) add(sp);
    pozdrawiam
0

Nie mogę tak zrobić. Próbowałem napisać add(sp); to Eclipse zaznaczał to jako błąd. Mam nowszą Javę ściągnąć? Którą?

A co do tego przesuwania to coś z setCarriage() niby ma być, ale nie wiem jak ta metoda działa..

0

OK. Przesuwanie tekstu:

tekst.setCaretPosition(tekst.getText().length());

Teraz tylko jak zmienić rozmiar suwaka?

0

Co masz na mysli pisząc o zmianie rozmiaru suwaka ? Szerokość paska i suwaka, czy długość suwaka. Długość zmienia sę sama, im więcej tekstu tym suwak krótszy.

0

Suwak ma niewłaściwy rozmiar na początku. Po włączeniu programu nie powienien być tego rozmiaru.

user image

0

Jeśli zrezygnujesz z instrukcji

sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

, to suwak pojawi się dopiero wtedy gdy będzie potrzebny.
W jakim systemie suwak wygląda tak jak na powyższym rysunku ?
pozdrawiam

0

Usunięcie tej linii nic nie daje.

Mam Mac OS X.

1 użytkowników online, w tym zalogowanych: 0, gości: 1