wucher wichtel: 2 Probleme mit Java-Browser (URL verändern & Layout)

Hallo!

Wie einige vielleicht schon wissen, versuche ich Java zu lernen :) Das Lernen hat bei JavaScript mit viel Geduld und noch mehr Beispielen ganz gut geklappt. Das Problem bei Java ist, ist dass die Beispiele geringer werden, die man z.B. im Netz findet. Jetzt wollte ich mal einen Browser schreiben. Das ist mit Java nicht besonders schwer. Aber ich will auch ermöglichen, dass die URL der Seite per Textfield verändert werden kann. Aber das klappt leider nicht. Zudem kommt, dass ich massive Probleme mit den Layoutmanagern habe. Mein Browser sollte in etwa so aussehen:

|---------------------|
| |Textfield|    |ok| |
|---------------------|
|                     |
|      Browser        |
|                     |
|                     |

Aber aussehen tut es so:

|---------------------|
|                     |
| |Textfield|    |ok| |

Browser
---------------------

Natürlich wird das komplette Fenster in zwei Teile geteilt (GridLayout), aber wie kann ich das erreichen (Welcher LayoutManager), dass das Textfield mit dem JButton nur genausoviel Platz einnimmt, wie es soll? Wenn man bei anderen Anwendungen die Fenstergröße verändert, dann wird die Tool-Leiste auch nicht größer, sondern nur z.B. das Dokument (Word) oder die Website (Firefox).
Wie kann ich für ein JPanel (Ist das für mein Vorhaben das richtige?), das das TextField und den Button enthält, eine feste Höhe angeben? Von mir aus 100px o.ä.?

Jetzt zu meinem zweiten Problem:
Wie schon klar geworden ist möchte ich ein JTextfield, in das der Anwender eine Adresse angeben kann. Diese Adresse soll dann per Klick auf den OK-Button angezeigt werden. Doch ich habe starke Probleme das Verändern der URL zu erreichen. Wie muss ich es schreiben, dass es klappt?

Hier der Quelltext mit Kommentaren:

  
package test;  
  
import javax.swing.*;  
import javax.swing.event.*;  
import java.io.*;  
import java.net.*;  
import java.awt.event.*;  
import java.awt.*;  
  
  
class Test{  
    String neueSeite;  
}  
  
class Adresse{  
    static void SetzeURL(Test nS){  
        nS.neueSeite = adresse.getText();  
        //Hier meckert Java, weil es adresse nicht kennt. Ich weiß aber nicht, wie ich es schreiben muss, damit Java weiß was ich damit mein?!  
    }  
}  
  
public class JBrowserTextField extends JEditorPane implements HyperlinkListener {  
  JBrowserTextField( String url )  
  {  
    setEditable( false );  
    addHyperlinkListener( this );  
  
    try  
    {  
      setPage( new URL(url) );  
    }  
    catch ( IOException e ) { e.printStackTrace(); }  
  }  
  public void hyperlinkUpdate( HyperlinkEvent event )  
  {  
    HyperlinkEvent.EventType typ = event.getEventType();  
  
    if ( typ == HyperlinkEvent.EventType.ACTIVATED )  
    {  
      try  
      {  
        setPage( event.getURL() );  
      }  
      catch( IOException e ) {  
        JOptionPane.showMessageDialog( this,  
                                      "Can't follow link to "  
                                        + event.getURL().toExternalForm(),  
                                      "Error",  
                                      JOptionPane.ERROR_MESSAGE);  
      }  
    }  
  }  
  
    public static void main(String[] args){  
        String startseite = "http://www.selfhtml.org";  
  
        JFrame f = new JFrame();  
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        f.setLayout(new GridLayout(2,0));  
  
        JPanel eingabe = new JPanel();  
        final JTextField adresse = new JTextField(startseite);  
        final JButton ok = new JButton("OK");  
  
        eingabe.add(adresse);  
        eingabe.add(ok);  
        f.add(eingabe);  
  
        ActionListener al = new ActionListener(){  
            public void actionPerformed(ActionEvent e){  
                Adresse neueURL = new Adresse();  
                JBrowserTextField( neueURL );  
                //Hier meckert Java wegen dem Fehler weiter oben (siehe erster Kommentar).  
  
//Wie muss ich in diesem ActionListener Java sagen, dass ich die URL verändern will? Stimmt das wenigstens ansatzweise mit JBrowserTextField(neueURL);?  
  
//Wie kann ich den String mit der Adresse überall verfügbar machen? Ich habe das jetzt mit mehreren Klassen "gelöst" (Test & Adresse), weil ich ein Beispiel fand, das mir wenigstens diesen Weg gezeigt hat. Sicher ist das total umständlich oder sogar falsch, aber ich weiß nicht, wie ich es anders machen kann. Habt ihr einen Tipp?  
  
            }  
        };  
  
  
        f.setSize(600,500);  
        f.add(new JScrollPane(new JBrowserTextField(startseite)));  
        f.setVisible(true);  
    }  
}  

Vielen Dank für eure Hilfe!
ciao, ww

--
Yet it seems that some have succeeded in finding a way which instead of leading you to a dead end offers you a way out - a way to freedom. Apparently, developing your physical abilities is like pressing harder against the wall of natural limits. And the harder you press the farther you are from true freedom which logically thinking is the direction opposite to the wall.
  1. Hallo,

    ich kümmere mich jetzt nur mal um dein erstes Problem.

    Wie einige vielleicht schon wissen, versuche ich Java zu lernen :) Das Lernen hat bei JavaScript mit viel Geduld und noch mehr Beispielen ganz gut geklappt. Das Problem bei Java ist, ist dass die Beispiele geringer werden, die man z.B. im Netz findet.

    Das glaube ich dir nicht...
    Geringer als bei JavaScript, vielleicht. Aber man findet wirklich
    massenhaft Code und Beispiele.

    |---------------------|
    | |Textfield|    |ok| |
    |---------------------|
    |                     |
    |      Browser        |
    |                     |
    |                     |

    Aber aussehen tut es so:

    |---------------------|
    |                     |
    | |Textfield|    |ok| |

    Browser
    ---------------------

    Natürlich wird das komplette Fenster in zwei Teile geteilt (GridLayout),

    In zwei _gleich große_ Teile. Deshalb sieht das so aus.

    aber wie kann ich das erreichen (Welcher LayoutManager), dass das Textfield mit dem JButton nur genausoviel Platz einnimmt, wie es soll?

    Mit mehreren LayoutManagern sollte das möglich sein. Im Grunde würde
    ich aber zum GridBagLayout raten. Damit kriegst du das gewünschte
    Ergebnis recht schnell hin. Allerdings hat das GridBagLayout eine
    recht steile Lernkurve. Dafür ist es aber auch mächtig.

    So auf den ersten Blick müßte das Layout aber auch unter Verwendung
    des BorderLayouts realisierbar sein, wobei zwei Layouts ineinander
    verschachtelt werden müssten.

    Im äußeren Layout packst du den Browser-Bereich in den CENTER. In den
    NORTH-Bereich setzt du einen Container, z.B. JPanel, in dem sich
    wiederum das Textfield und der Button befinden. Das JPanel erhält
    auch BorderLayout als LayoutManager. Im JPanel kommt das Textfield
    an die CENTER-Position und der Button an die EAST-Position.
    (Letzteres hat allerdings den Nachteil, daß der Button dieselbe Höhe
    wie das Textfield erhalten wird.)

    Aber, wie gesagt, das GridBagLayout ist hier wohl sinnvoller.

    Möglicherweise lassen sich auch andere LayoutManager auf die beschriebene
    Weise so kombinieren, daß ein besseres Ergebnis herauskommt.

    (Ich habe meine Angaben nicht getestet. Es ist durchaus möglich, daß
    sie fehlerhaft sind und nicht das gewünschte Ergebnis erzielen.)

    Ansonsten kann ich dir noch die JavaDocs und Tutorials zu den Java-
    LayoutManager ans Herz legen.

    Wie kann ich für ein JPanel (Ist das für mein Vorhaben das richtige?), das das TextField und den Button enthält, eine feste Höhe angeben? Von mir aus 100px o.ä.?

    Wenn du LayoutManager verwendest, je nach LayoutManager gar nicht.
    Aber das willst du auch nicht. Sonst würdest du ja keine LayoutManager
    verwenden...

    Gruß
    Slyh

    1. Hallo!

      ich kümmere mich jetzt nur mal um dein erstes Problem.

      Danke!

      Das glaube ich dir nicht...
      Geringer als bei JavaScript, vielleicht. Aber man findet wirklich
      massenhaft Code und Beispiele.

      Könntest du mir bitte einen Link posten? Ich habe schon viel geggogelt, bin aber auf keinen grünen Zweig gekommen. Eine solche Seite würde mir sehr helfen.

      Aber, wie gesagt, das GridBagLayout ist hier wohl sinnvoller.

      Ooh... der ist kompliziert :) Ich werde mich mal einarbeiten.
      Ich habe es jetzt erstmal mit BorderLayout hinbekommen. Danke für die Beschreibung. Irgendwie fehlt(e) mir (noch) das Verständnis für soetwas. Wie damals beim Umstieg von Tabellen auf CSS-Layouts ;)

      Ansonsten kann ich dir noch die JavaDocs und Tutorials zu den Java-
      LayoutManager ans Herz legen.

      Werde ich mir auf jeden Fall vornehmen!

      Vielen Dank für deine Hilfe. Zumindest das mit dem Layout hätte sich geklärt. Vielen vielen Dank dafür.

      ciao, ww

      PS: Der jetzige Code sieht so aus:

        
      package test;  
        
      import javax.swing.*;  
      import javax.swing.event.*;  
      import java.io.*;  
      import java.net.*;  
      import java.awt.event.*;  
      import java.awt.*;  
      import java.awt.BorderLayout.*;  
        
        
      class Test{  
          String neueSeite;  
      }  
        
      class Adresse{  
          static void SetzeURL(Test nS){  
              nS.neueSeite = adresse.getText();  
          }  
      }  
        
      public class JBrowserTextField extends JEditorPane implements HyperlinkListener {  
        JBrowserTextField( String url )  
        {  
          setEditable( false );  
          addHyperlinkListener( this );  
        
          try  
          {  
            setPage( new URL(url) );  
          }  
          catch ( IOException e ) { e.printStackTrace(); }  
        }  
        public void hyperlinkUpdate( HyperlinkEvent event )  
        {  
          HyperlinkEvent.EventType typ = event.getEventType();  
        
          if ( typ == HyperlinkEvent.EventType.ACTIVATED )  
          {  
            try  
            {  
              setPage( event.getURL() );  
            }  
            catch( IOException e ) {  
              JOptionPane.showMessageDialog( this,  
                                            "Can't follow link to "  
                                              + event.getURL().toExternalForm(),  
                                            "Error",  
                                            JOptionPane.ERROR_MESSAGE);  
            }  
          }  
        }  
        
          public static void main(String[] args){  
              String startseite = "http://www.selfhtml.org";  
        
              JFrame f = new JFrame();  
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
              f.setLayout(new BorderLayout());  
        
              JPanel eingabe = new JPanel();  
                  eingabe.setLayout(new BorderLayout());  
        
              final JTextField adresse = new JTextField(startseite);  
              final JButton ok = new JButton("OK");  
        
              eingabe.add(adresse, BorderLayout.CENTER);  
              eingabe.add(ok, BorderLayout.EAST);  
              f.add(eingabe, BorderLayout.NORTH);  
        
              ActionListener al = new ActionListener(){  
                  public void actionPerformed(ActionEvent e){  
                      Adresse neueURL = new Adresse();  
                      JBrowserTextField( neueURL );  
                  }  
              };  
        
        
              f.setSize(600,500);  
              f.add(new JScrollPane(new JBrowserTextField(startseite)));  
              f.setVisible(true);  
          }  
      }  
      
      

      Java meckert immer noch an den gleichen Stellen wie vorher, was das Verändern der URL betrifft.

      --
      Yet it seems that some have succeeded in finding a way which instead of leading you to a dead end offers you a way out - a way to freedom. Apparently, developing your physical abilities is like pressing harder against the wall of natural limits. And the harder you press the farther you are from true freedom which logically thinking is the direction opposite to the wall.
      1. Hallo!

        Könntest du mir bitte einen Link posten? Ich habe schon viel geggogelt, bin aber auf keinen grünen Zweig gekommen. Eine solche Seite würde mir sehr helfen.

        Ich weiß nicht, mit welchen Stichwörtern ich vor einiger Zeit gesucht habe, aber Google spuckt bei "Java Code" und "Java Sourcecode" einiges aus.

        ciao, ww

        --
        Yet it seems that some have succeeded in finding a way which instead of leading you to a dead end offers you a way out - a way to freedom. Apparently, developing your physical abilities is like pressing harder against the wall of natural limits. And the harder you press the farther you are from true freedom which logically thinking is the direction opposite to the wall.
      2. Hallo,

        Könntest du mir bitte einen Link posten? Ich habe schon viel geggogelt, bin aber auf keinen grünen Zweig gekommen. Eine solche Seite würde mir sehr helfen.

        Naja, eine Seite, die allgemein Code bereitstellt, kenne ich nicht.
        Wobei, doch, Google Code Search soll wohl so etwas sein.
        Ich bilde mir außerdem ein, irgendwann mal auf eine Seite gestoßen zu
        sein, die freien Code (sortiert nach Programmiersprache) zur Verfügung
        stellt. Die Adresse weiß ich aber leider nicht mehr.

        Ich dachte jedenfalls eher an Code für spezielle Probleme, wie eben
        z.B. LayoutManager. Google hilft hier meistens weiter.

        Für Code-Schnipsel ist allgemein der Java Almanac sehr zu empfehlen.

        Da wird man für viele grundlegende Problemstellungen häufig schon
        fündig.

        Aber, wie gesagt, das GridBagLayout ist hier wohl sinnvoller.

        Ooh... der ist kompliziert :) Ich werde mich mal einarbeiten.

        Man gewöhnt sich recht schnell dran, nachdem man ein paar Beispiele
        gemacht wird. Vom Prinzip her ist das GridBagLayout gar nicht so arg
        weit von HTML-Tabellen weg...

        Gruß
        Slyh

  2. Hallo,

    Jetzt zu meinem zweiten Problem:
    Wie schon klar geworden ist möchte ich ein JTextfield, in das der Anwender eine Adresse angeben kann. Diese Adresse soll dann per Klick auf den OK-Button angezeigt werden. Doch ich habe starke Probleme das Verändern der URL zu erreichen. Wie muss ich es schreiben, dass es klappt?

    Ich gehe jetzt allgemein mal über deinen Code und sage etwas dazu, ohne
    auf dein Problem einzugehen. Um den Code genauer zu verstehen, bin ich
    jetzt ehrlich gesagt zu müde. Vielleicht kannst du meine Kommentare
    soweit schonmal zur Kenntnis nehmen, ggf. den Code anpassen, nochmal
    posten und so Hilfe erhalten.

    Hier der Quelltext mit Kommentaren:

    [code lang=java]
    package test;

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

    Verwendest du eine IDE? Das solltest du ggf. langsam mal. Die kann dir
    bei vielen Dingen schon weiterhelfen. Wie man von Hand kompiliert, hast
    du vermutlich jetzt ja gelernt.

    class Test{
        String neueSeite;
    }

    Was macht das da?

    class Adresse{
        static void SetzeURL(Test nS){

    Du solltest Methodennamen auf jeden Fall mit kleinem Anfangsbuchstaben
    schreiben. Das ist eine Konvention in Java. Wenn ich auf Code stoße,
    der großgeschrieben ist, denke ich sofort an eine Klasse und bin
    verwirrt, wenn es doch keine ist. Den meisten anderen Entwicklern
    wird das auch so gehen.

    "nS" ist außerdem kein wirklich sprechender Name...

    Wieso hat "nS" nicht gleich den Typ "String"? Ich nehme stark an, daß
    du eine URL übergibst?! Du brauchst dafür keine eigene Klasse "Test"
    bauen. Verwende als Datentyp einfach String.

    nS.neueSeite = adresse.getText();
            //Hier meckert Java, weil es adresse nicht kennt. Ich weiß aber nicht, wie ich es schreiben muss, damit Java weiß was ich damit mein?!

    Wo kommt "adresse" her? Das sieht aus wie eine Instanzvariable von der
    Klasse "Adresse". Ich sehe dort aber keine Instanzvariable die so
    heißt. Was willst du hier tun?

    }
    }

    public class JBrowserTextField extends JEditorPane implements HyperlinkListener {
      JBrowserTextField( String url )
      {
        setEditable( false );
        addHyperlinkListener( this );

    try
        {
          setPage( new URL(url) );
        }
        catch ( IOException e ) { e.printStackTrace(); }
      }
      public void hyperlinkUpdate( HyperlinkEvent event )
      {
        HyperlinkEvent.EventType typ = event.getEventType();

    if ( typ == HyperlinkEvent.EventType.ACTIVATED )
        {
          try
          {
            setPage( event.getURL() );
          }
          catch( IOException e ) {
            JOptionPane.showMessageDialog( this,
                                          "Can't follow link to "
                                            + event.getURL().toExternalForm(),
                                          "Error",
                                          JOptionPane.ERROR_MESSAGE);
          }
        }
      }

    Den obenstehenden Code habe ich mir jetzt nicht näher angeschaut.

    public static void main(String[] args){
            String startseite = "http://www.selfhtml.org";

    JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setLayout(new GridLayout(2,0));

    JPanel eingabe = new JPanel();

    Der Name "eingabe" ist irgendwie nicht so toll. :)

    final JTextField adresse = new JTextField(startseite);
            final JButton ok = new JButton("OK");

    eingabe.add(adresse);
            eingabe.add(ok);
            f.add(eingabe);

    ActionListener al = new ActionListener(){

    Du machst mit "a1" (schlechter Name) gar nichts. Du solltest ihn noch
    als ActionListener für den Button setzen...

    public void actionPerformed(ActionEvent e){
                    Adresse neueURL = new Adresse();
                    JBrowserTextField( neueURL );
                    //Hier meckert Java wegen dem Fehler weiter oben (siehe erster Kommentar).

    Das ist auch kein Wunder, weil das kein gültiger Code ist. (Außer ich
    übersehe etwas.) Ich weiß auch nicht genau, was du da machen willst.
    Es ist auch nicht "ansatzweise" richtig, nein. :)

    Allgemein solltest du dir überlegen, ob das Befüllen des JFrame wirklich
    in main() passieren sollte. Möglicherweise wäre ein Konstruktor oder
    eine init()-Methode sinnvoller hierfür geeignet.

    Dann solltest du dir ohnehin überlegen, ob es nicht klüger wäre, eine
    Applikationsklasse (z.B. "MyBrowser") zu erstellen, die von JFrame
    ableitet. So wird das oftmals in Java gelöst.

    public class MyBrowser extends JFrame

    In main() machst du im Prinzip nur noch folgendes:

    MyBrowser myBrowser = new MyBrowser();
      myBrowser.setSize(600, 500);
      myBrowser.setVisible(true);

    Das Code, der das Frame mit den Komponenten befüllt, würde sich dann
    ab sofort im Konstruktor von MyBrowser befinden.

    Die aktuelle Adresse könntest du in einer Instanzvariable(!) "adresse"
    von MyBrowser speichern. Somit kannst du aus jeder Methode von MyBrower
    auf die aktuelle Adresse zugreifen.

    Im Konstruktor würdest du außerdem das ActionPerformed-Handling einrichten.

    Entweder indem du das über eine anynome Inner-Klasse löst, so wie das
    jetzt ansatzweise in deinem Code vorhanden ist, oder indem du MyBrowser
    außerdem noch ActionListener implementieren läßt, so daß deine Klassen-
    Deklaration so aussieht:
      public class MyBrowser extends JFrame implements ActionListener

    Du mußt dann natürlich die Methode "actionPerformed" implementieren.
    Diese könnte dann durch den Aufruf von setPage() auf das JBrowserTextField-
    Objekt die Seite wechseln.

    Der Code könnte in etwa so aussehen:
      adresse = adressTextfield.getText();
      browserTextField.setPage(adresse);

    Die Instanzvariable(!) "browserTextField" wäre also ein Objekt vom Typ
    "JBrowserTextField", das du während der Initialisierung im Konstruktor
    befüllst.

    Aus JBrowserTextField machst du eine eigene Klasse in einer eigenen
    .java-Datei.

    So, mal sehen, ob du damit was anfangen kannst. Meine Beschreibung
    ist möglicherweise ein bißchen durcheinander. Versuch dich mal ein
    bißchen damit auseinanderzusetzen. Möglicherweise kommst du dann
    schon drauf.

    Falls du Fragen hast, weil ich zu wirr geschrieben habe oder falls
    du sonst nicht weiterkommst, frag bitte einfach nach.

    Ich gebe dir auf jeden Fall als Ratschlag, den Code vollständig von
    vorne zu beginnen. Der bestehende Code ist nämlich stellenweise mehr
    als falsch -- und zwar nicht nur syntaktisch -- und verwirrt dich in
    seinem jetzigen Zustand sicherlich nur.

    Insgesamt möchte ich dir noch folgende "Ratschläge" auf den Weg geben:
    Du solltest dir klar werden, was eine lokale Variable und was eine
    Instanzvariable ist. Das sind Grundlagen der Objektorientierung,
    ohne die es nicht geht. Du solltest außerdem wissen, was Klassen sind
    und wofür sie gut sind. Und wenn du das weißt, solltest du mit Übungen
    anfangen, die einfachere Komponenten als die Browser-Komponente von
    Java enthalten. :)

    Gruß
    Slyh

    1. Hallo!

      Vielen Dank für deine ausführliche Antwort! Jetzt gehe ich erst mal 8 Stunden lang in die Schule :'( und dann hoffe ich, dass ich Zeit habe deine ausführliche Antwort umzusetzen :) Vielen vielen Dank für dein Bemühen!

      ciao, ww

      --
      Yet it seems that some have succeeded in finding a way which instead of leading you to a dead end offers you a way out - a way to freedom. Apparently, developing your physical abilities is like pressing harder against the wall of natural limits. And the harder you press the farther you are from true freedom which logically thinking is the direction opposite to the wall.