# JTextPane und Server



## bernd (6. Jul 2004)

```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.text.*;
/**
  *
  * Beschreibung.
  *
  * @version 1.0 vom 01.07.2004
  * @author Bernd
  */

public class meinServer extends JFrame {
  // Anfang Variablen
  private JTextField jtfaus = new JTextField();
  private JButton jbusenden = new JButton();
  String chattext;
  String newline = System.getProperty("line.separator");
  //------------------------------------------------
   JScrollPane scrollPane = new JScrollPane();
  private JTextPane jtp1 = new JTextPane();
  // Ende Variablen

  public meinServer(final String title) {
    // Frame-Initialisierung
    super("UDP-Server");  // erzeugt den Fensternamen
    addWindowListener(new WindowAdapter() {
      public void windowClosing(final WindowEvent evt) { System.exit(0); } });
    setBounds(30, 30, 700, 450);
    Container cp = getContentPane();
    cp.setLayout(null);

    // Anfang Komponenten
    jtfaus.setText("");
    jtfaus.setBounds(10, 340, 500, 25);
    getContentPane().add(jtfaus);
    jbusenden.setText("senden");
    jbusenden.setBounds(10, 370, 100, 25);
    getContentPane().add(jbusenden);
    jbusenden.addActionListener(new ActionListener() {
      public void actionPerformed(final ActionEvent evt) {
        jbusendenActionPerformed(evt); } });

     jtp1.setBounds(10, 30, 500, 300);
     jtp1.setEnabled(false);
     jtp1.setContentType("TEXT/RTF");
     jtp1.setText("Wilkommen im Chat" + newline);
     getContentPane().add(jtp1);
    
    scrollPane.setViewportView(jtp1);
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setBounds(10, 30, 500, 300);
    getContentPane().add(scrollPane, BorderLayout.WEST);

    // Ende Komponenten

    setVisible(true);
  }

  // Anfang Ereignisprozeduren
  public void jbusendenActionPerformed(final ActionEvent evt) {

  }

  // Ende Ereignisprozeduren

  public static void main(final String[] args){ // Einstieg ins Programm
    new meinServer("meinServer");
     try
    {
      DatagramSocket socket = new DatagramSocket( 4711 );
      DatagramPacket packet;
      while ( true )
      {
        // Auf Anfrage warten
        packet = new DatagramPacket( new byte[1024], 1024 );
        socket.receive( packet );

        int         len     = packet.getLength();
        byte        data[]  = packet.getData();

         System.out.println (new String( data, 0, len ) );
         JTextPane jtp1 = new JTextPane();
         String eingang = (new String( data, 0, len ) );
          jtp1.setText(eingang);    // PROBLEM
      }
    }
    catch ( Exception e )
    {
      System.out.println( e );
    }

    
  }
 }
```

Ich steh mal wieder auf dem Schlauch, oben der abgebildete Server lauscht am Socket, und empfängt auch das Packet das ich ihm schicke.
Das kann man in der Eingabeaufforderung sehen: "System.out.println (new String( data, 0, len ) );"
aber er übergibt das nicht an das JTextPane "jtp1"???????????
Müsste er aber doch, oder braucht der einen Schupps wie "jtp1.repaint();" ??????


----------



## alshir (7. Jul 2004)

Hi,

ich habe das Problem bei meinem FileSend Programm auch gehabt. 
Jemand sagte mir, dass einige Befehle wie z.b. accept blockierend sind. Finde dazu aber auch kein geeignetes Material in der API. Also habe ich das auch noch nicht wirklich verstanden, was er mir damit sagen wollte.
Aber er sagte auch, dass es angeblich nur mit einem eigenen Thread lösen.

Allerdings würde ich auch gerne nochmal eine genaue Antwort auf dieses Problem haben ...

mfg
alshir


----------



## L-ectron-X (7. Jul 2004)

@alshir: Die Methode accept() der Klasse ServerSocket hat nur eine Aufgabe: das Annehmen bzw. Akzeptieren (engl. accept) von Client-Verbindungsanfragen.
Sie kehrt erst zurück, wenn die Verbindung zum Client beendet wurde, das heißt, sie ist so lange nicht mehr von einem anderen Client erreichbar. Man kann zwar eine Warteschlange für Verbindungsanfragen zur Verfügung stellen (iterativer Server), so dass alle Anfragen vom Server nacheinander bearbeitet werden. Moderne und sinnvolle Server-Programme erledigen aber Anfragen quasi parallel, wozu der Einsatz von Threads erforderlich ist.
In der Praxis funktioniert das nun etwa so, dass der Server die Verbindungsanfrage an einen Thread übergibt, der direkt mit der Client-Anwendung kommuniziert. So ist es möglich, dass mehrere Anfragen gleichzeitig bearbeitet werden.


----------



## bernd (7. Jul 2004)

Also wenn ich das richtig verstanden habe wird nach dem "socket.receive(packet);" was blockiert!
Aber wenn es blockiert wird warum kann es dann in der Eingabeaufforderung angezeigt werden???????


----------



## L-ectron-X (7. Jul 2004)

Die Methode recieve() der Klasse DatagramSocket wartet (und blockiert) so lange, bis eine Nachricht eintrifft.
Das scheint mir aber hier nicht das Problem zu sein.
Schau Dir mal genau Deinen Code an. Du hast eine Instanzvariable vom Typ JTextPane und Du erzeugst eine weitere JTextPane in Deiner main()-Methode. Aber genau diese JTextPane wurde nicht zur ContentPane Deines JFrames hinzugefügt. Somit wird auch der hinzugefügte Text nicht sichtbar, da es sich um eine anderes Objekt handelt.


----------



## bernd (7. Jul 2004)

Das hört sich verdammt logisch an, ich mach guck!
Danke erst mal!!!!!!


----------



## bernd (7. Jul 2004)

```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.text.*;
/**
  *
  * Beschreibung.
  *
  * @version 1.0 vom 01.07.2004
  * @author Bernd
  */

public class meinServer extends JFrame {
  // Anfang Variablen
  private JTextField jtfaus = new JTextField();
  private JButton jbusenden = new JButton();
  String chattext;
  String eingang;
  static final String newline = System.getProperty("line.separator"); //DAS HAB ICH GEÄNDERT VON Privat in static final!!!!
  //------------------------------------------------
   JScrollPane scrollPane = new JScrollPane();
  static final JTextPane jtp1 = new JTextPane();
  // Ende Variablen

  public meinServer(final String title) {
    // Frame-Initialisierung
    super("UDP-Server");  // erzeugt den Fensternamen
    addWindowListener(new WindowAdapter() {
      public void windowClosing(final WindowEvent evt) { System.exit(0); } });
    setBounds(30, 30, 700, 450);
    Container cp = getContentPane();
    cp.setLayout(null);

    // Anfang Komponenten
    jtfaus.setText("");
    jtfaus.setBounds(10, 340, 500, 25);
    getContentPane().add(jtfaus);
    jbusenden.setText("senden");
    jbusenden.setBounds(10, 370, 100, 25);
    getContentPane().add(jbusenden);
    jbusenden.addActionListener(new ActionListener() {
      public void actionPerformed(final ActionEvent evt) {
        jbusendenActionPerformed(evt); } });

     jtp1.setBounds(10, 30, 500, 300);
     jtp1.setEnabled(false);
     jtp1.setContentType("TEXT/RTF");
     jtp1.setText("Wilkommen im Chat" + newline);
     getContentPane().add(jtp1);
    
    scrollPane.setViewportView(jtp1);
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setBounds(10, 30, 500, 300);
    getContentPane().add(scrollPane, BorderLayout.WEST);

    // Ende Komponenten

    setVisible(true);
  }

  // Anfang Ereignisprozeduren
  public void jbusendenActionPerformed(final ActionEvent evt) {
       // ist noch im Entwurf
  }

  // Ende Ereignisprozeduren

  public static void main(final String[] args){ // Einstieg ins Programm
    new meinServer("meinServer");
     try
    {
      DatagramSocket socket = new DatagramSocket( 4711 );
      DatagramPacket packet;
      while ( true )
      {
        // Auf Anfrage warten
        packet = new DatagramPacket( new byte[1024], 1024 );
        socket.receive( packet );

        int         len     = packet.getLength();
        byte        data[]  = packet.getData();

         System.out.println (new String( data, 0, len ) );
         String eingang = (new String( data, 0, len ) );

         jtp1.setText(eingang + newline);    // PROBLEM

      }
    }
    catch ( Exception e )
    {
      System.out.println( e );
    }

    
  }
 }
```
Das hab ich geändert, "static final JTextPane jtp1 = new JTextPane();" war vorher "private" jetzt funktioniert es!
Ist bestimmt nicht die feinste Lösung, aber es funktioniert!!!!!

Nochmals Danke!!!!


----------



## alshir (7. Jul 2004)

Jaaaaa, aber warum gehts dann bei mir nicht ???


```
public static void sendFile(JTextField status, File file, String address, int port) throws IOException
    {
        
        status.setText("Connecting to host: " + address + " : " + port); // Wird ignoriert
        Socket server = new Socket(InetAddress.getByName(address), port);                    
        
        status.setText("Transfering"); // Wird ignoriert
               
        try{
            BufferedInputStream bis = new BufferedInputStream( new FileInputStream(file) );
            BufferedOutputStream out = new BufferedOutputStream( server.getOutputStream() );
            
            DataOutputStream dos = new DataOutputStream(out);
            dos.writeLong(file.length());
            
            PrintWriter pw = new PrintWriter(out);
            pw.write(file.getName());
            
            byte[] buffer = new byte[1024];
            int readbytes = 0;
            
            try {
                while( (readbytes = bis.read(buffer)) != -1 ){
                    out.write(buffer, 0, readbytes);
                }
            } catch (IOException e){
                System.err.println(e);
            }
            pw.close();
            out.close();
            bis.close();
            status.setText("Upload of " + file.length() + " bytes complete"); // Wird ausgeführt
        } catch (FileNotFoundException e){
            System.err.println(e);
        }
        
        server.close();    
    }
```

Er ignoriert meine setText Anweisungen bis auf die letzte komplett !!!


----------



## bernd (7. Jul 2004)

Was kriegste denn für ne Fehlermeldung????


----------



## alshir (7. Jul 2004)

Keine, dass ist es ja. Er ignoriert meine setText Anweisungen einfach. Nicht mehr und nicht weniger 

mfg
alshir


----------



## bernd (7. Jul 2004)

Du bekommst warscheinlich gar keine Fehlermeldung!
So wie ich das sehe gibst Du drei mal einen Befehl an das TextFeld "status",
ich denke das führt der auch aus, und zwar nacheinander.
Das würde bedeuten jeder Befehl denn anderen überschreibt, und zum schluss nur noch der letzte Befehl angezeigt wird!

Ich hoffe ich erzähl keinen Blödsinn!
War nur so ne Idee1


----------



## alshir (7. Jul 2004)

bernd hat gesagt.:
			
		

> Du bekommst warscheinlich gar keine Fehlermeldung!
> So wie ich das sehe gibst Du drei mal einen Befehl an das TextFeld "status",
> ich denke das führt der auch aus, und zwar nacheinander.
> Das würde bedeuten jeder Befehl denn anderen überschreibt, und zum schluss nur noch der letzte Befehl angezeigt wird!
> ...



Das habe ich mir anfangs auch gedacht. Dann habe ich einfach mal ne grosse Datei übertragen und siehe da, es passiert auch in der Zwischenzeit nichts. 

mfg
alshir


----------



## bernd (7. Jul 2004)

Was ist denn wenn du vor deinem Textfeld ein "System.out.println(HIER DEIN CODE);"
setzt, dann müsstest du genau verfolgen können was passiert oder????


----------



## alshir (7. Jul 2004)

Habe es folgendermaßen versucht:


```
status.setText("Transfering");
status.repaint();
```

Ergebniss: Es hat sich nichts verändert. Das Statusfeld ändert seinen Text nicht.

Dann noch auf die Art und Weise:


```
status.setText("Transfering");
System.out.println("Transfering");
```

Ergebniss: Er schreibt mir "Transfering" in die Console.

-> es hat irgendwas mit Swing zutun !!!


mfg
alshir


----------



## L-ectron-X (7. Jul 2004)

bernd hat gesagt.:
			
		

> So wie ich das sehe gibst Du drei mal einen Befehl an das TextFeld "status",
> ich denke das führt der auch aus, und zwar nacheinander.
> Das würde bedeuten jeder Befehl denn anderen überschreibt, und zum schluss nur noch der letzte Befehl angezeigt wird!


Genau so sehe ich das auch.


			
				alshir hat gesagt.:
			
		

> Das habe ich mir anfangs auch gedacht. Dann habe ich einfach mal ne grosse Datei übertragen und siehe da, es passiert auch in der Zwischenzeit nichts.


Das hat mit Deinem Problem auch nichts zu tun.


----------



## bernd (7. Jul 2004)

Dann lag ich ja doch nicht so daneben!


----------



## alshir (7. Jul 2004)

L-ectron-X hat gesagt.:
			
		

> bernd hat gesagt.:
> 
> 
> 
> ...



Öhem du solltest vielleicht nochmal mein Problem genauer betrachten 

Wenn ich doch in ein Textfield etwas hineinschreibe wie "Aufgabe beginnt", dann etwas mache, dass furchtbar lange dauert, sagen wir z.b. eine halbe Minute,  und dann in das Textfield was hineinschreibe wie z.b. "Aufgabe erledigt", muss er mir erst "Aufgabe beginnt" anzeigen und dann, nachdem er die Aufgabe abgearbeitet hat "Aufgabe erledigt".

Warum das hier nicht funktioniert, weiss ich nicht.

mfg
alshir


----------



## Illuvatar (7. Jul 2004)

Wird die Methode _zufälligerweise_ aus dem Event-Thread aufgerufen :?: Während dem Aufrufen von diesem läuft der Swing-Thread nämlich nicht. :wink: 



			
				ich hat gesagt.:
			
		

> Bei Swing-Komponenten ist zudem zu beachten, dass Swing nicht threadsicher ist, und diese aus anderen Threads nicht gezeichnet werden können, es sei denn, diese Threads wurden über SwingUtilities.invokeLater (Thread) bzw. SwingUtilities.invokeAndWait (Thread) mit dem Swing-Thread synchronisiert.



http://www.java-forum.org/de/viewtopic.php?t=5930


----------



## alshir (7. Jul 2004)

Bei mir sieht es so aus.

Ich habe eine Klasse MainFrame, welche den Code für die GUI beinhaltet. Aus dieser "Main"-Klasse wird dann bei nem ActionEvent die Methode sendFile ...... der Klasse FileSend aufgerufen. Alles ohne sonstige Threads und so.

Wenn ich das jetzt richtig verstanden habe, wird die GUI erst wieder aktualisiert, wenn die Methode abgeschlossen ist. Dann wird der letzte Befehl an die TextArea ausgeführt und deshalb erscheint es so, als ob der Rest der Befehle ignoriert wird.
Also muss ich einen eigenen Thread für sendFile erzeugen und diesen dann synchronisieren.

Ich wil jetzt nur ein "Richtig verstanden" hören   *hoff*

mfg
alshir


----------



## Illuvatar (7. Jul 2004)

Richtig verstanden :toll: 

(Jedenfalls ist das so wie ich es verstanden habe :shock: )


----------



## alshir (7. Jul 2004)

Illuvatar hat gesagt.:
			
		

> Richtig verstanden :toll:
> 
> (Jedenfalls ist das so wie ich es verstanden habe :shock: )



Lang hats gedauert 

Vielen Dank für eure Hilfe

mfg
alshir


----------

