Avatar billede nielsbrinch Nybegynder
15. marts 2002 - 12:33 Der er 11 kommentarer og
1 løsning

Bedre indbygget browser

Jeg bruger lige nu et HTMLEditorKit af en art, på en JEditorPane. Den viser ganske rigtigt html - eller rettere, den viser html, men ikke ganske rigtigt.

Den opfører sig simpelthen som Netscape 3.0 ville gøre. Den har intet begreb om farver på tabelrammer, intet begreb om f.eks. indstillinger af linjer. Dens opfattelse af dimensioner er også helt hen i vejret.

Jeg ved godt jeg ikke kan forvente en indbygget Internet Explorer i en java-klasse, men der må da findes noget bedre end det gamle skidt der!
Avatar billede disky Nybegynder
15. marts 2002 - 13:26 #1
Læs API'en den forklarer det hele:
The Swing JEditorPane text component supports different kinds of content via a plug-in mechanism called an EditorKit. Because HTML is a very popular format of content, some support is provided by default. The default support is provided by this class, which supports HTML version 3.2 (with some extensions), and is migrating toward version 4.0. The <applet> tag is not supported, but some support is provided for the <object> tag.


Husk IE følger IKKE standarden helt korrekt.
Avatar billede nielsbrinch Nybegynder
15. marts 2002 - 13:45 #2
...og hvordan ændrer jeg så til 4.0?
Avatar billede carstenknudsen Nybegynder
15. marts 2002 - 13:50 #3
disky: er er ikke tale om IE, det er Netscape der nævnes,
så API'en forklarer INTET. Måske man skulle læse
spørgsmålene før man svarer?
nielsbrinch: Det du referere til som værende problemet
er det ren html eller er det diverse avancerede plugins?
Prøv denne version har lavet der er en primitiv browser:
SimpleBrowser.java
//package Janet;

//import Janet.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import java.io.*;
import java.net.*;
import java.awt.print.*;

/**
* Class SimpleBrowser is an extension of {@link JFrame}
* that works as a simple browser.
* The functionality is as described here:
* <UL>
* <LI>Buttons
* <UL>
* <LI><B>Back</B> will move one page back in the history.
* <LI><B>Forward</B> will move one page forward in the history.
* <LI><B>Reload</B> will reload the current page.
* <LI><B>Save</B> will save the contents of the current page
* (unless the address has been modified in which case it will
* attempt to save the page associated with this new address).
* <LI>The tilde button adds a tilde to the address in the
* text field and has been included because some systems
* have problems entering the character from the keyboard.
* </UL>
* <LI>The text field is used to enter a URL pointing to
* a document.  Pressing the enter key in the text field
* leads to the page being loaded into the text area.
* <LI>Text area functionality
* <UL>
* <LI>Clicking on a hyperlink will lead to a new page
* being displayed if it represents a valid hyperlink
* with an accessible page.
* <LI>Pressing the shift key and cliking the mouse away from
* a hyperlink leads to a popup menu appearing.
* In the popup menu is a list of all hyperlinks in the
* currently displayed page, and they can be followed
* by clicking on the desired one.
* Clicking elsewhere will dismiss the list.
* </UL>
* </UL>
* <BR><B>Note:</B><BR>
* <UL>
* <LI>The class uses a JEditorPane which may throw exceptions that
* cannot be caught, hence disturbing messages may be printed
* to the console, but does not always impair the functionality.
* <LI>Frames are not fully supported, especially with respect
* to the history.
* </UL>
* <BR><B>Example of use:</B><BR>
* SimpleBrowser browser = new SimpleBrowser( "SimpleBrowser" );
* browser.show();
* @author Carsten Knudsen
* @author Martin Egholm Nielsen
* @version 1.0
**/
public class SimpleBrowser extends JFrame implements Serializable {
    private final static String initialGreeting = "<HTML><CENTER><B>Welcome to the SimpleBrowser</B></CENTER></HTML>";
    private final static String initialWebAddress = "http://www.fys.dtu.dk/~janet";
    private JTextField address;
    private boolean standAlone;
    private final JEditorPane pane;
    private final JPopupMenu menu;
    private java.util.List history = new java.util.ArrayList();
    private int historyPointer = -1;
    private Listener listener;
    private final ActionListener buttonListener;
    private JButton back;
    private JButton forward;
    private JButton reload;
    private JButton save;
    private JButton tilde;

    /**
    * Constructor for SimpleBrowser class taking as argument
    * a title.
    **/
    public SimpleBrowser( String title ) {
    this( title, false );
    }

    /**
    * Constructor for SimpleBrowser class taking as argument
    * a title and a boolean indicating whether the SimpleBrowser
    * should run as a stand-alone application.
    **/
    private SimpleBrowser( String title, boolean standAlone ) {
    super( title );
    this.standAlone = standAlone;
    JFrame frame = this;
    JLabel messageField = new JLabel( " " );
    pane = new JEditorPane();
    //pane = new FormattedPane();
    pane.setEditable( false );
    pane.setContentType( "text/html" );
    pane.setFont( new Font( "Monospaced", Font.BOLD, 16 ) );
    pane.setText( initialGreeting );
    pane.setCaretPosition( 0 );
    Box box = Box.createHorizontalBox();
    back = new JButton( "Back" );
    back.setToolTipText( "Move one step back in the history." );
    forward = new JButton( "Forward" );
    forward.setToolTipText( "Move one step forward in the history." );
    reload = new JButton( "Reload" );
    reload.setToolTipText( "Reload the current page." );
    save = new JButton( "Save" );
    save.setToolTipText( "Save the referenced contents in a file." );
    Insets insets = new Insets( 0, 0, 0, 0 );
    back.setMargin( insets );
    forward.setMargin( insets );
    reload.setMargin( insets );
    save.setMargin( insets );
    box.add( back );
    box.add( forward );
    box.add( reload );
    box.add( save );
    JLabel spaces = new JLabel( "        " );
    address = new JTextField( initialWebAddress );
    tilde = new JButton( "~" );
    tilde.setMargin( insets );
    tilde.setToolTipText( "Press button to append a ~(tilde) to address." );
    box.add( spaces );
    box.add( address );
    box.add( tilde );
    listener = new Listener( frame, pane,
                forward, back, reload, save,
                messageField, address, tilde );
    forward.addActionListener( listener );
    back.addActionListener( listener );
    reload.addActionListener( listener );
    save.addActionListener( listener );
    pane.addHyperlinkListener( listener );
    address.addActionListener( listener );
    tilde.addActionListener( listener );
    JPanel panel = new JPanel();
    panel.setLayout( new BorderLayout() );
    panel.add( box, BorderLayout.NORTH );
    panel.add( new JScrollPane( pane ), BorderLayout.CENTER );
    panel.add( messageField, BorderLayout.SOUTH );
    getContentPane().add( panel );
    setSize( 600, 600 );
    addWindowListener( new CloseWindow() );
    menu = new JPopupMenu();
    buttonListener = new ActionListener() {
        public void actionPerformed( ActionEvent ae ) {
            menu.setVisible( false );
            addPage( ae.getActionCommand() );
        } // actionPerformed
        } ;
    pane.addMouseListener( new MouseAdapter() {
        public void mouseReleased( MouseEvent me ) {
            int x = me.getX();
            int y = me.getY();
            if ( me.isPopupTrigger() || me.isShiftDown() ) {
            setupPopupMenu();
            try {
                Object o = menu.getComponent( 0 );
                menu.show( pane, x, y );
            } // try
            catch ( ArrayIndexOutOfBoundsException aioobe ) {
            } // catch
            } // if
            else if ( me.isControlDown() ) {
            setupImgSrcMenu();
            try {
                Object o = menu.getComponent( 0 );
                menu.show( pane, x, y );
            } // try
            catch ( ArrayIndexOutOfBoundsException aioobe ) {
            } // catch
            } // if
        } // mouseDragged
        } // MouseAdapter
                  );
    //ComponentPrinter.makePrintable( pane );
    } // constructor

    private void clearPopupMenu() {
    boolean more = true;
    while ( more ) {
        try {
        menu.remove( 0 );
        } // try
        catch ( IllegalArgumentException iae ) {
        more = false;
        } //catch
    } // more
    } // clearPopupMenu
   
    private void setupPopupMenu() {
    clearPopupMenu();
    Document document = pane.getDocument();
    if ( document instanceof HTMLDocument ) {
        HTMLDocument htmldoc = (HTMLDocument)document;
        HTMLDocument.Iterator iterator = htmldoc.getIterator( HTML.Tag.A );
        iterator.next();
        while ( iterator.isValid() ) {
        AttributeSet attr = iterator.getAttributes();
        boolean found = false;
        Enumeration enum = attr.getAttributeNames();
        while ( enum.hasMoreElements() && ! found ) {
            Object name = enum.nextElement();
            if ( name.equals( HTML.Attribute.HREF ) ) {
            found = true;
            Object value = attr.getAttribute( name );
            boolean problem = false;
            URL url = null;
            try {
                url = new URL( (String)value );
            } // try
            catch ( MalformedURLException murle ) {
                problem = true;
            } // catch
            if ( ! problem ) {
                JButton button = new JButton( (String)value );
                menu.add( button );
                button.addActionListener( buttonListener );
            } // if
            } // if
        } // while
        iterator.next();
        } // while
    } // if
    } // setupPopupMenu
   
    private void setupImgSrcMenu() {
    clearPopupMenu();
    Document document = pane.getDocument();
    if ( document instanceof HTMLDocument ) {
        HTMLDocument htmldoc = (HTMLDocument)document;
        HTMLDocument.Iterator iterator = htmldoc.getIterator( HTML.Tag.IMG );
        iterator.next();
        while ( iterator.isValid() ) {
        AttributeSet attr = iterator.getAttributes();
        boolean found = false;
        Enumeration enum = attr.getAttributeNames();
        while ( enum.hasMoreElements() && ! found ) {
            Object name = enum.nextElement();
            if ( name.equals( HTML.Attribute.SRC ) ) {
            found = true;
            Object value = attr.getAttribute( name );
            boolean problem = false;
            URL url = null;
            try {
                url = new URL( (String)value );
            } // try
            catch ( MalformedURLException murle ) {
                problem = true;
            } // catch
            if ( ! problem ) {
                JButton button = new JButton( (String)value );
                menu.add( button );
                button.addActionListener( buttonListener );
            } // if
            } // if
        } // while
        iterator.next();
        } // while
    } // if
    } // setupImgSrcMenu
   
    /**
    * The class Listener handles all events related to displaying
    * information in the SimpleBrowser.
    * It handles buttons being pressed and hyperlinks being activated.
    **/
    private class Listener
    implements ActionListener, HyperlinkListener {
    private JFrame frame;
    private JEditorPane pane;
    private JButton forward, back, reload, save;
    private JLabel messageField;
    private JTextField address;
    private JButton tilde;
    /**
    * Public constructor for class Listener.
    **/
    public Listener( JFrame frame,
            JEditorPane pane,
            JButton forward,
            JButton back,
            JButton reload,
            JButton save,
            JLabel messageField,
            JTextField address,
            JButton tilde ) {
        this.frame = frame;
        this.pane = pane;
        this.forward = forward;
        this.back = back;
        this.reload = reload;
        this.save = save;
        this.messageField = messageField;
        this.address = address;
        this.tilde = tilde;
        this.forward.setEnabled( false );
        this.back.setEnabled( false );
        this.reload.setEnabled( false );
        this.save.setEnabled( false );
    } // constructor
   
    // handles button events
    public void actionPerformed( ActionEvent ae ) {
        try {
        Object source = ae.getSource();
        if ( source.equals( forward ) ) {
            if ( historyPointer < history.size() - 1 ) {
            Cursor oldCursor = frame.getCursor();
            frame.setCursor( new Cursor( Cursor.WAIT_CURSOR ) ); 
            URL url = (URL)history.get( ++historyPointer );
            try {
                pane.setPage( url );
                address.setText( url.toString() );
            } // try
            catch ( Exception e ) {
            } // catch
            frame.setCursor( oldCursor );
            updateButtons();
            }
        } // if, forward
        else if ( ae.getActionCommand().equals( "Back" ) ) {
            if ( historyPointer > 0 ) {
            Cursor oldCursor = frame.getCursor();
            frame.setCursor( new Cursor( Cursor.WAIT_CURSOR ) ); 
            URL url = (URL)history.get( --historyPointer );
            try {
                pane.setPage( url );
                address.setText( url.toString() );
            } // try
            catch ( Exception e ) {
            } // catch
            frame.setCursor( oldCursor );
            updateButtons();
            }
        } // else if, back
        else if ( ae.getActionCommand().equals( "Reload" ) ) {
            if ( historyPointer > 0 ) {
            Cursor oldCursor = frame.getCursor();
            frame.setCursor( new Cursor( Cursor.WAIT_CURSOR ) ); 
            URL url = (URL)history.get( historyPointer );
            try {
                pane.setPage( url );
                address.setText( url.toString() );
            } // try
            catch ( Exception e ) {
            } // catch
            frame.setCursor( oldCursor );
            updateButtons();
            }
        } // else if, back
        else if ( source.equals( tilde ) ) {
            address.setText( address.getText() + "~" );
        } // else if, tilde
        // the user have pressed enter in the address field
        else if ( source.equals( address ) ) {
            try {
            URL url = new URL( ae.getActionCommand() );
            pane.setPage( url );
            address.setText( url.toString() );
            if ( historyPointer > -1 ) {
                while ( history.size() - 1 > historyPointer ) {
                history.remove( history.size() - 1 );
                } // while
                history.add( url );
                historyPointer++;
                updateButtons();
            } // if
            else {
                history.add( url );
                historyPointer++;
                updateButtons();
            } // else
            } // try
            catch ( MalformedURLException murle ) {
            showErrorMessage( "" +  murle );
            redisplayCurrentPage();
            } // catch
            catch ( IOException ioe ) {
            showErrorMessage( "" +  ioe );
            redisplayCurrentPage();
            } // catch
            catch ( NullPointerException npe ) {
            showErrorMessage( "" +  npe );
            redisplayCurrentPage();
            } // catch
        } // else if, address
        else if ( source.equals( save ) ) {
            JFileChooser fileChooser = new JFileChooser( new File( System.getProperty( "user.dir" ) ) );
            fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY );
            fileChooser.setApproveButtonText( "Save" );
            fileChooser.setApproveButtonToolTipText( "Click to save to file." );
            int result = fileChooser.showOpenDialog( null );
            if ( result == JFileChooser.APPROVE_OPTION ) {
                try {
                File file = fileChooser.getSelectedFile();
                FileOutputStream fos = new FileOutputStream( file );
                URL url = new URL( address.getText() );
                URLConnection connection = url.openConnection();
                InputStream is = connection.getInputStream();
                byte[] buffer = new byte[ 8192 ];
                int bytes_read;
                while( ( bytes_read = is.read( buffer ) ) > 0 ) {
                    fos.write( buffer, 0, bytes_read );
                } // while
                fos.close();
                is.close();
                } // try
                catch ( IOException ioe ) {
                JOptionPane.showMessageDialog( null,
                                  "IO exception: " + ioe.getMessage(),
                                  "Error",
                                  JOptionPane.ERROR_MESSAGE );
                } // catch
            } // try
        } // else if, save
        } // try
        // mysterious exceptions are somtimes thrown hence the try-catch CK
        catch( Exception q ) {
        } // catch
    } // actionPerformed
   
    // handles hyperlink events
    public void hyperlinkUpdate( HyperlinkEvent e ) {
        HyperlinkEvent.EventType type = e.getEventType();
        if ( type == HyperlinkEvent.EventType.ACTIVATED ) {
        JEditorPane pane = (JEditorPane) e.getSource();
        if ( e instanceof HTMLFrameHyperlinkEvent ) {
            HTMLFrameHyperlinkEvent  evt = (HTMLFrameHyperlinkEvent)e;
            HTMLDocument doc = (HTMLDocument)pane.getDocument();
            doc.processHTMLFrameHyperlinkEvent(evt);
        } // if
        else {
            try {
            URL url = e.getURL();
            pane.setPage( url );
            address.setText( url.toString() );
            updateHistory( url );
            updateButtons();
            } // try
            catch ( MalformedURLException murle ) {
            showErrorMessage( "" +  murle );
            } // catch
            catch ( IOException ioe ) {
            showErrorMessage( "" + ioe );
            } // catch
            catch ( NullPointerException npe ) {
            showErrorMessage( "" + npe );
            } // catch
        } // else
        } // if
        else if ( type == HyperlinkEvent.EventType.ENTERED ) {
        messageField.setText( e.getDescription() );
        } // else if
        else if ( type == HyperlinkEvent.EventType.EXITED ) {
        messageField.setText( " " );
        } // else if
    } // hyperlinkUpdate

    } // class Listener
   
    /**
    * This methods enables or disables the forward and back buttons
    * depending on the historyPointer and history list.
    **/
    private void updateButtons() {
    if ( historyPointer < 0 ) {
        forward.setEnabled( false );
        back.setEnabled( false );
        reload.setEnabled( false );
        save.setEnabled( false );
    } // if
    else {
        if ( historyPointer >= 0 ) {
        reload.setEnabled( true );
        save.setEnabled( true );
        } // if
        else {
        reload.setEnabled( false );
        save.setEnabled( false );
        } // else
        if ( historyPointer > 0 ) {
        back.setEnabled( true );
        } // if
        else {
        back.setEnabled( false );
        } // else
        if ( historyPointer < history.size() - 1 ) {
        forward.setEnabled( true );
        } // if
        else {
        forward.setEnabled( false );
        } // else
    } // else
    } // updateButtons
   
    /**
    * This method updates the history function with the given URL.
    **/
    private void updateHistory( URL url ) {
    if ( historyPointer > -1 ) {
        while ( history.size() - 1 > historyPointer ) {
        history.remove( history.size() - 1 );
        }
        history.add( url );
        historyPointer++;
        updateButtons();
    }
    else {
        history.add( url );
        historyPointer++;
        updateButtons();
    }
    } // updateHistory
   
    private void redisplayCurrentPage() {
    URL url = (URL)history.get( historyPointer );
    try {
        pane.setPage( url );
    } // try
    catch ( Exception e ) {
    } // catch
    } // redisplayCurrentPage
   
    /**
    * Adds a URL referenced by the text to the browser,
    * and updates the history, as well as the button state.
    **/
    public void addPage( String text ) {
    try {
        URL url = new URL( text );
        pane.setPage( url );
        address.setText( url.toString() );
        if ( historyPointer > -1 ) {
        while ( history.size() - 1 > historyPointer ) {
            history.remove( history.size() - 1 );
        } // while
        history.add( url );
        historyPointer++;
        updateButtons();
        } // if
        else {
        history.add( url );
        historyPointer++;
        updateButtons();
        } // else
    } // try
    catch ( MalformedURLException murle ) {
        showErrorMessage( "" +  murle );
    } // catch
    catch ( IOException ioe ) {
        showErrorMessage( "" +  ioe );
    } // catch
    catch ( NullPointerException npe ) {
        showErrorMessage( "" +  npe );
    } // catch
    } // addPage
   
    /**
    * Display en error message passed as argument.
    **/
    private static void showErrorMessage( String message ) {
    JOptionPane.showMessageDialog( null,
                      message,
                      "Error",
                      JOptionPane.ERROR_MESSAGE );
    } // showErrorMessage

    /**
    * The public method setWebAddress sets the web address that
    * appears in the SimpleBrowser.
    **/
    public void setInitialWebAddress( String webAddress ) {
    address.setText( webAddress );
    } // setInitialWebAddress

    /**
    * The class CloseWindow makes it possible for the browser
    * to be shut down by clicking in the right hand corner.
    **/
    private class CloseWindow extends WindowAdapter implements Serializable {
    public void windowClosing( WindowEvent e ) {
        if ( standAlone )
        System.exit( 0 );
        else
        dispose();
    } // windowClosing
    } // CloseWindow

    /**
    * Method main allows SimpleBrowser to work as a stand-alone application.
    **/
    public static void main( String[] args ) {
    SimpleBrowser browser = new SimpleBrowser( "SimpleBrowser", true );
    browser.setVisible( true );
  } // main   

} // SimpleBrowser
Avatar billede nielsbrinch Nybegynder
15. marts 2002 - 14:05 #4
Carsten, det ser meget spændende ud. Jeg har ikke prøvet programmet, men efter hvad jeg kan se er det blot en JEditorPane med text/html - så langt har jeg også tænkt, og det er den visning jeg ikke er tilfreds med, fordi der er mange mangler.

Nu vil jeg lige prøve browseren.
Avatar billede nielsbrinch Nybegynder
15. marts 2002 - 14:11 #5
Jeg har nu prøvet den, og den virker ligesom min. Det jeg har brug for er bare en bedre fortolker af ren html. Jeg giver html til den med simpel setText på pane og så skal den bare vise det. Men må meget gerne forstå mere end en almindelig JEditorPane med text/html ContentType.

(men jeg er vild med jeres "tilføj tilde"-funktion :-)
Avatar billede carstenknudsen Nybegynder
15. marts 2002 - 14:12 #6
ja, naturligvis, men husker du at bruge setPage
eller bruger du setText, der kan være stor
forskel på resultatet.
Avatar billede carstenknudsen Nybegynder
15. marts 2002 - 14:15 #7
jeg kan ikke få lov at skrive tilde normalt !#@£@%&
hvis du vil have en bedre html fortolker tror jeg du
står med et uoverskueligt problem, det er et kæmpe
arbejde at lave en sådan en, jeg skal ihvertfald ikke
pvøve at rode med den slags. Jeg må ellers sige
at JEditorPane og JTextPane som regel giver mig
fint resultat når der ikke er plugins,men det er ingen
trøst.
Avatar billede nielsbrinch Nybegynder
15. marts 2002 - 14:42 #8
Sagen er den at jeg har to EditorPanes. I den første pane har jeg noget tekst. Den anden pane opdateres hver gang jeg rører ved den første EditorPane, og viser HTML'en i den første pane, som det skulle se ud i en browser. Det gør den også, men en browser fra 80'erne.

Hvilken forskel skulle setPage gøre?
Avatar billede nielsbrinch Nybegynder
15. marts 2002 - 14:52 #9
Jeg kan se der bliver rettet nogle bittesmå fejl ved at bruge setPage i stedet for setText. Hvorfor, forstår jeg naturligvis ikke. Jeg må også ærgre mig over at skulle gemme i en fil hver gang jeg vil se html'en ... Er der ikke en bedre måde?
Avatar billede disky Nybegynder
15. marts 2002 - 15:58 #10
carsten:

Sikke da et dårligt humør du er i idag.

Sure mokke.

Netscape 3.0 fulgte HELLER ikke w3c standarden !!!!

Niels: læs igen api'en der står højt og tydeligt hvad den understøtter, mere understøttelse fra API'en må du bare vente på. Eller lav din egen browser.
Avatar billede carstenknudsen Nybegynder
16. marts 2002 - 12:07 #11
nielsbrinch: setPage metoder sørger for
at loade billeder etc med lokal reference,
det kan setText ikke gøre. Der bliver ikke
gemt noget i en fil? Jeg forstår ikke helt
hvad du mener med det? Den loader en url
men gemmer den ikke nogen steder.

disky: Ja, men jeg kan læse og gør det.
Avatar billede nielsbrinch Nybegynder
16. marts 2002 - 13:53 #12
Jeg mener at det som den indbyggede browser skal vise, netop er noget tekst som er i en anden EditorPane i det samme program. setPage loader jo netop en url, men der er vel ingen url til noget løs tekst ... så skal den løse tekst først gemmes i en fil, og derefter vises gennem en url-reference.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester