精简版web浏览器

import javax.swing.JFrame;
import javax.swing.JEditorPane;
import javax.swing.event.HyperlinkListener;
import java.beans.PropertyChangeListener;
import javax.swing.event.HyperlinkEvent;
import java.beans.PropertyChangeEvent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JFileChooser;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import java.util.ArrayList;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.filechooser.FileFilter;
import java.io.File;
import javax.swing.JOptionPane;
import javax.swing.JMenuBar;
import javax.swing.text.html.HTMLDocument;
import javax.swing.JToolBar;
import java.io.IOException;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.util.Date;
import java.text.SimpleDateFormat;
/*
【问题1】:点击"主页"按钮后,再次点击,下面文本提示一直在加载,没有返回结果,也没有返回超时
【问题2】:"打开"菜单功能未实现--is ok!
【问题3】:页面链接的 输入类型(HyperlinkEvent.EventType.ENTERED)不起作用--可以支持http://www.baidu.com、http://www.hao123.com
【问题4】:菜单中的快捷键如何使用?--先使用Alt+快捷键进入菜单,接着使用菜单项快捷键打开菜单项
【问题5】:存放打开页面的队列满了是什么情况?
*/

/**
JFrame:顶级容器
JPanel:普通容器
JFrame的结构从里到外(按照图层的叠加顺序)依次为:frame->rootpane->layeredpane->contentpane->menuBar(optional)->glasspane
    frame
        rootpane
            layeredpane
                contentpane:默认是JPanel,一般的组件都放在JPanel
                menuBar
            glasspane:默认是透明的
*/
public class WebBrowser extends JFrame implements HyperlinkListener,PropertyChangeListener{
    /**
    JEditorPane的最主要功能在于展现不同类型的文件格式内容
    第一种是纯文本类型,其类型的表示法为"text/plain",这种类型的文件就是我们最常使用的txt文件,这类型的文件可以用记事本或WordPad等文书编辑软件来编辑;
    第二种是RTF类型,其表示法为"text/rtf",这种类型的文件特色是能对文字内容做字体缩放、变形、上色等特殊效果;
    第三类是HTML类型,也就是我们在网络上所浏览的网页类型,其表示法为"text/html",这类文件的特色相信大家都非常的清楚,除了在对字体效果的表现之外还具有在文件
    内加入图片、超级链接等相关功能。但是JEditorPane并不是一个全功能的Web Browser,它仅能支持简单的HTML语法.JEditorPane支持HTML类型的文件最主要的用途是用来制作在线辅助说明文件。
    */

    /*javax.swing组件*/
    JEditorPane textPane;
    JLabel messageLable;        //contentPane的SOUTH
    JTextField urlField;        //URL单行输入框
    JFileChooser fileChooser;     //文件选择器

    /*前进和后退,在Button初始化要用到,在监听事件也要用到,所以作为成员变量*/
    JButton backButton;
    JButton farwardButton;

    java.util.List history = new ArrayList();        //保存历史记录的列表
    int currentHistoryPage = -1;                                //当前页面在历史记录列表中的位置
    //属于类仅有一个且为常量,类初始化时已经在内存中生成不可变,不管新建多少个浏览器对象实例,所有浏览器对象打开窗口的总数仅保留最新MAX_HISTORY条
    public static final int MAX_HISTORY = 50;        //历史记录列表超出该值时,按顺序清除多余的历史记录
    //属于类仅有一个,所有类对象实例共用同一个该静态变量
    static int numBrowserWindows = 0;                        //当前已经打开的浏览器窗口数

    //标识当所有浏览器窗口都关闭,是否退出程序
    private static boolean exitWhenLastWindowClosed = false ;
    String home = "http://www.google.cn/";            //默认的主页

    //构造函数
    public WebBrowser(){
        //super的调用必须是构造器中的第一个语句
        super("WebBrowser");        //构造一个具有指定标题的,默认最初不可见的Frame对象
        textPane = new JEditorPane();        //设置显示HTML的面板,并设置为不可编辑
        textPane.setEditable(false);
        textPane.addHyperlinkListener(this);                    //注册事件处理器,用于超链接事件
        textPane.addPropertyChangeListener(this);            //注册事件处理器,用于处理属性改变事件。当页面加载完成时,触发该事件

        this.getContentPane().add(new JScrollPane(textPane), BorderLayout.CENTER);
        messageLable = new JLabel();
        this.getContentPane().add(messageLable, BorderLayout.SOUTH);
        this.initMenu();
        this.initToolBar();
        //浏览器窗口加1
        //numBrowserWindows是属于类的,在创建WebBrowser对象实例前已经在内存中生成
        WebBrowser.numBrowserWindows++;
        //当关闭窗口时,调用close方法处理(Y)
        this.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e){
                close();
                }
            });
        }

    //初始化菜单栏,只允许子类继承和重写
    public  void initMenu(){
        JMenu fileMenu = new JMenu("文件");
        //Alt+F
        fileMenu.setMnemonic(‘F‘);
        JMenuItem newMenuItem = new JMenuItem("新建");
        //先Alt+F,再N/Alt+N,快捷键有分层级,子菜单的快捷键不能直接使用
        newMenuItem.setMnemonic(‘N‘);
        //匿名内部类继承一个父类或者实现一个接口,ActionListener为接口(Y)
        newMenuItem.addActionListener(new ActionListener(){
            //实现该接口的抽象方法
                public void actionPerformed(ActionEvent e){
                    newBrowser();
                    }
            });

        JMenuItem openMenuItem = new JMenuItem("打开");
        //先Alt+F,再O/Alt+O,快捷键有分层级,子菜单的快捷键不能直接使用
//        openMenuItem.setMnemonic(‘O‘);
        openMenuItem.setMnemonic(KeyEvent.VK_O);
        //匿名内部类继承一个父类或者实现一个接口,ActionListener为接口(Y)
        openMenuItem.addActionListener(new ActionListener(){
            //实现该接口的抽象方法
                public void actionPerformed(ActionEvent e){
                    openLocalPage();
                    }
            });

        JMenuItem closeMenuItem = new JMenuItem("关闭");
        //先Alt+F,再C/Alt+C,快捷键有分层级,子菜单的快捷键不能直接使用
        closeMenuItem.setMnemonic(‘C‘);
        //匿名内部类继承一个父类或者实现一个接口,ActionListener为接口(Y)
        closeMenuItem.addActionListener(new ActionListener(){
            //实现该接口的抽象方法
                public void actionPerformed(ActionEvent e){
                    close();
                    }
            });

        JMenuItem exitMenuItem = new JMenuItem("退出");
        //先Alt+F,再E/Alt+E,快捷键有分层级,子菜单的快捷键不能直接使用
        exitMenuItem.setMnemonic(‘E‘);
        //匿名内部类继承一个父类或者实现一个接口,ActionListener为接口(Y)
        exitMenuItem.addActionListener(new ActionListener(){
            //实现该接口的抽象方法
                public void actionPerformed(ActionEvent e){
                    exit();
                    }
            });
        fileMenu.add(newMenuItem);
        fileMenu.add(openMenuItem);
        fileMenu.add(closeMenuItem);
        fileMenu.add(exitMenuItem);

        JMenu helpMenu = new JMenu("帮助");
        helpMenu.setMnemonic(‘H‘);
        JMenuItem aboutMenuItem = new JMenuItem("关于");
        aboutMenuItem.setMnemonic(‘A‘);

        helpMenu.add(aboutMenuItem);

        JMenuBar menuBar = new JMenuBar();
        menuBar.add(fileMenu);
        menuBar.add(helpMenu);

        this.setJMenuBar(menuBar);
        }

    private void exit(){
        if(JOptionPane.    showConfirmDialog(this, "你确定退出Web浏览器?", "退出",     JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION){
            System.exit(0);
            }
        }

    @SuppressWarnings("deprecation")
    private void openLocalPage(){
        if(fileChooser==null){
            fileChooser = new JFileChooser();
            //FileFilter为抽象类,使用内部类创建一个子类实例,实现FileFilter类的抽象方法(Y)
            FileFilter fileFilter = new FileFilter(){
                //File参数是文件过滤器对应类型的文件
                public  boolean    accept(File f){
                    String fileName = f.getName();
                    if((fileName.endsWith("html"))||(fileName.endsWith("htm"))){
                        return true;
                        }else{return false;}
                    }
                public String    getDescription(){
                    return "HTML Files";
                    }
                };
            //设置当前页面默认的文件筛选器
            fileChooser.setFileFilter(fileFilter);
            //当前页面的默认文件筛选器为系统默认的,仅表示把指定的文件筛选器添加到文件筛选器列表中
            fileChooser.addChoosableFileFilter(fileFilter);
            }
        //Pops up an "Open File" file chooser dialog,在"文件"选择器界面,如果点击"打开"按钮则返回0,如果点击"取消"或"X"按钮则返回1,其他异常返回-1
        int openResult = fileChooser.showOpenDialog(null);    //返回值为0
        System.out.println("openResult: "+openResult);
        if(openResult==JFileChooser.APPROVE_OPTION){
            //仅支持选择单个文件,支持选择多个文件使用getSelectedFiles()
            File selectFile = fileChooser.getSelectedFile();
            System.out.println(selectFile.toString());
            try{
                //选择的本地文件向网页文件一样打开
                displayPage(selectFile.toURL());
            }catch(MalformedURLException e){
                e.printStackTrace();
                }
            }
        }
    public void setHome(String home){
        this.home = home;
        }    

    public String getHome(){
//        return this.home;
        return home;
        }    

    //打开多个浏览器窗口,是否一个窗口最后一个页面关闭,所有窗口都会一并关闭??
//    public static void setExitWhenLastWindowClosed(boolean b){
//        exitWhenLastWindowClosed = b;
//        }
    private void newBrowser(){
        //构造函数递归调用
        WebBrowser b = new WebBrowser();
        //this指外层构造函数生成的对象实例
        b.setSize(this.getWidth(),this.getHeight());
        b.setVisible(true);
        }    

    //初始化工具栏,只允许子类继承和重写
    protected void initToolBar(){
        backButton = new JButton("后退");
        backButton.setEnabled(true);
        //匿名内部类为接口(Y)
        backButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                back();
                }
            });

        farwardButton = new JButton("前进");
        farwardButton.setEnabled(true);
        //(Y)
        farwardButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                forward();
                }
            });

        JButton refresh = new JButton("刷新");
        refresh.setEnabled(true);
        //(Y)
        refresh.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                refresh();
                }
            });

        JButton home = new JButton("主页");
        home.setEnabled(true);
        //(Y)
        home.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                home();
                }
            });

        urlField = new JTextField();
        //(Y)
        urlField.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                displayPage(urlField.getText());
                }
            });

        JToolBar toolBar = new     JToolBar();
        toolBar.add(backButton);
        toolBar.add(farwardButton);
        toolBar.add(refresh);
        toolBar.add(home);
        toolBar.add(new JLabel("   地址:"));
        toolBar.add(urlField);
        this.getContentPane().add(toolBar,BorderLayout.NORTH);
        }

    private void home(){
        displayPage(getHome());
        }

    private void refresh(){
        if(currentHistoryPage != -1){
            //先展示一个默认的HTMLDocument页面
            textPane.setDocument(new HTMLDocument());
            }
        visit((URL)history.get(currentHistoryPage));
        }    

    private void forward(){
        if(currentHistoryPage < (history.size()-1)){
            visit((URL)history.get(++currentHistoryPage));
            }
        backButton.setEnabled((currentHistoryPage > 0));
        farwardButton.setEnabled((currentHistoryPage < (history.size()-1)));
        }    

    private void back(){
        if(currentHistoryPage > 0){
            visit((URL)history.get(--currentHistoryPage));
        }
        backButton.setEnabled((currentHistoryPage > 0));
        farwardButton.setEnabled((currentHistoryPage < (history.size()-1)));
        }

    private boolean visit(URL url){
        try{
            String href = url.toString();
            startAnimation("加载" + href + "...");
            textPane.setPage(href);        //Sets the current URL being displayed,加载完毕后触发addPropertyChangeListener事件
            this.setTitle(href);
            urlField.setText(href);
            return true;
        }catch(IOException e){
            stopAnimation();
            messageLable.setText("不能打开页面" + e.getMessage());
            return false;
            }
        }

    @SuppressWarnings("unchecked")
    private void displayPage(URL url){
        if(visit(url)){
            this.history.add(url);
            int numentries = history.size();
            System.out.println("numentries:" + numentries);
            for(int i=0;i<numentries;i++){
                System.out.println("history["+i+"] : " + history.get(i));
                }
            if(numentries > (MAX_HISTORY + 10)){
                history = history.subList((numentries - MAX_HISTORY), numentries);
                currentHistoryPage = MAX_HISTORY;
                }
            currentHistoryPage =     (numentries - 1);
            //当前打开的页面会是最后一个吗?
            if(currentHistoryPage > 0){
                backButton.setEnabled(true);
                }
            }
        }    

    public void displayPage(String href){
        try{
            if(!href.startsWith("http://")){
            href = "http://"+href;
            }
            displayPage(new URL(href));
        }catch(MalformedURLException e){
            messageLable.setText("错误的网址:" + href);
            }
        }

    public void close(){
        //隐藏当前窗口
        this.setVisible(false);
        //销毁当前窗口的所有组件
        this.dispose();
        synchronized (WebBrowser.class){
            //浏览器窗口减1
            WebBrowser.numBrowserWindows--;
            //当Window监听器监听到关闭窗口事件,exitWhenLastWindowClosed标识默认为false,如果希望符合下面条件时关闭,则要提前通过setter设置
            if((numBrowserWindows==0) && (exitWhenLastWindowClosed==true)){
                System.exit(0);
                }
            }
        }
    //动画消息,显示在最底下的状态栏标签上,用于反馈浏览器状态
    String animationMessage;
    //动画当前帧的索引
    int ainimationFrame = 0;
    //动画用到的帧,是一些字符
    String[] animationFrames = new String[]{"-", "\\", "|", "/", "-", "\\", "|", "/",",", ".", "o", "0", "O", "#", "*", "+"};
    //新建一个Swing的定时器,每125ms更新一次状态栏标签的文本(Y)
    javax.swing.Timer animator = new javax.swing.Timer(125,new ActionListener(){
        public void actionPerformed(ActionEvent e){
            animate();
            }
        });
    //定时器启动后就一直不间断的执行任务
    private void animate(){
        String frame = animationFrames[ainimationFrame++];
        messageLable.setText(animationMessage + " "+ frame);
        //循环遍历动画用到的所有帧
        ainimationFrame = ainimationFrame % animationFrames.length;
        }
    private void startAnimation(String message){
        animationMessage = message;
        ainimationFrame = 0;
        animator.start();
        }    

    private void stopAnimation(){
        System.out.println("信息标签停止播放动画!");
        animator.stop();
        messageLable.setText(" ");
        }

    public static void setExitWhenLastWindowClosed(boolean exitWhenLastWindowClosed){
        WebBrowser.exitWhenLastWindowClosed = exitWhenLastWindowClosed;
        }

    //实现HyperlinkListener接口的hyperlinkUpdate方法
    public void hyperlinkUpdate(HyperlinkEvent e){
        System.out.println("HyperlinkEvent.getURL(): " + e.getURL());
        HyperlinkEvent.EventType type = e.getEventType();
//        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
//        System.out.println(df.format(new Date())+" type: " + type);
        //激活类型--光标点击超链接位置
        if(type==HyperlinkEvent.EventType.ACTIVATED){
            displayPage(e.getURL());
            }
        //输入类型--光标放到超链接位置
        else if(type==HyperlinkEvent.EventType.ENTERED){
            messageLable.setText(e.getURL().toString());
            }
        //退出的类型--光标移出超链接位置
        else if(type==HyperlinkEvent.EventType.EXITED){
            messageLable.setText(" ");
            }
        }

    //实现PropertyChangeListener接口的propertyChange方法
    public void propertyChange(PropertyChangeEvent evt){
        System.out.println("PropertyName: "+evt.getPropertyName());
        //直到页面加载成功,之前都是对页面展示的准备,所有页面属性都是由JEditorPane完成,由PropertyChangeListener监听
        if(evt.getPropertyName().equals("page")){
            stopAnimation();
            }
        }

    public static void main(String[] args){
        WebBrowser.setExitWhenLastWindowClosed(true);
        WebBrowser browser = new WebBrowser();
        //获取屏幕分辨率,
//        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
//        browser.setSize(screenSize);
        browser.setSize(800,700);
        browser.setVisible(true);
        browser.displayPage(browser.getHome());
        }
    }

加载页面:

原文地址:https://www.cnblogs.com/celine/p/9905268.html

时间: 2024-11-10 14:30:49

精简版web浏览器的相关文章

图片跟随鼠标移动(精简版跨浏览器实现)

网上看到许多让图片跟随鼠标移动,感觉代码很复杂,还不兼容,其实可以很简单的实现: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="

利用HTML5技术在Web上实现对图形图像的处理——WebPhotoshop精简版

WebPhotoshop精简版是利用HTML5技术在Web上实现对图形图像的处理,构建易维护.易共享.易于拓展.实时性的Web图形图像处理平台. 精简版功能包括:图形绘制.图像处理.图像操作.完整版包括多人协作操作图像.实时交流.图片搜索,同时实现实时的多人协作处理图形图像技术.(完整版后续上传)一.功能说明:1.图形绘制 实现铅笔.画笔(书法画笔.喷枪.蜡笔.记号笔.水彩画笔)的绘制效果.实现直线.曲线.椭圆(圆).矩形(圆角矩形).三角形(直角三角形.等边三角形.任意三角形).多边形的绘制.

让 Chrome 57 支持迅雷精简版

感觉下面步骤麻烦的,可以翻到文章最后,提供了全部文件打包,Chrome 扩展最好还是去 Chrome 商店安装 详细步骤 1. 安装迅雷精简版 迅雷精简版 1.5.3.288 最终更新官网下载 http://down.sandai.net/mini/ThunderMini_dl1.5.3.288.exe 2. 下载迅雷 Chrome 扩展额外支持包 http://plugin.xl7.xunlei.com/7.9/func/xl_ext_chrome_setup.exe 3. 使用 7zip 解

[终极精简版][图解]Nginx搭建flv mp4流媒体服务器

[终极精简版][图解]Nginx搭建flv mp4流媒体服务器 卧槽,就是被新版的jwplayer坑了,用了博主的 startparam: "start",primary: "flash" 最终搞定了,特意注册一个账号顶一下!谢谢. 花了我接近3周,历经了重重问题,今日终于把流媒体服务器搞定,赶紧的写个博文以免忘记... 起初是跟着网上的一些教程来的,但是说的很不全面,一些东西也过时不用了(比如jwplayer老版本).我这次是用的最新版jwplayer6.8,在配

份额24% IE11成全球最受欢迎Web浏览器

用电脑浏览网页少不了使用Web浏览器,那么哪款浏览器最受欢迎呢?分析公司Net Applications公布了10月份浏览器市场份额统计数据,其中微软Internet Explorer 11成为目前最流行的Web浏览器. Internet Explorer一直保持浏览器市场份额头把交椅.其中Internet Explorer 8是Windows 7中的默认浏览器,其今年九月市场份额是22.2%,但随着Windows 10技术预览版的发布和部分Windows 7的停售,今年十月份额已经降低到17.

雨林木风 Windows Vista ULTIMATE With SP1 精简版 Y2.1

软件大小:2.66G   软件语言:简体中文   软件类别:国外软件/操作系统   运行环境:Win2003, WinXP, Win2000, NT, WinME,winvista,win7   授权方式:免费软件 软件评级: 雨林木风 Windows Vista ULTIMATE With SP1 精简版,基于 Windows Vista Ultimate SP1 X86 MSDN 官方简体中文版精简优化而成,无人值守安装,免激活,免序列号,安装方便快捷! 雨林木风 Vista 2.1 精简版

精简版LINUX系统---wdOS

wdOS是一个基于CentOS版本精简优化过的Linux服务器系统,网站服务器系统并集成nginx,apache,php,mysql等web应用环境及wdcp管理系统,安装完系统,所有的都安装完成装好系统,就可以通后台管理服务器和创建网站,增加FTP用户,创建数据库等使用方便,操作简单,安全,稳定,易用lamp,lnmp,lnamp三个应用环境可在wdcp后台里自由切换使用,通常情况下,只要其中一个就可以 官方网站:http://www.wdos.net/ 精简版LINUX系统---wdOS

小韦XPSP3 V10.0_Ghost精简版

小韦XPSP3 V10.0_Ghost精简版 小韦XPSP3 V10.0_Ghost精简版该版本基于小韦XPSP3 V10.0,用EasySysprep_4.1进行重新封装,最大程度保持原版极度精简的理念.C盘为NTFS格式,安装后C盘只占用260M(关闭虚拟内存)!改进如下:1.修复了快速启动栏,增加了显示桌面按钮.2.附件中增加了计算器.3.增加了语言栏显示,便于手工安装输入法.4.增加vbscript支持.5.恢复xcopy.find命令到system32目录.6.修复右击磁盘格式化的命令

关于极限精简版系统(RAMOS专用)的说明(FAQ)

关于极限精简版系统(RAMOS专用)的说明(FAQ) 对RAMOS-er来说,系统精简唯一的目的就是RAMOS,精简只为RAMOS而存在.我更喜欢听到大家把精简系统用于RAMOS,这里才应该是他的主战场.渣机请用完整版!1.为什么不集成USB3.0驱动?NVME驱动是通用的吗?答:如果集成了USB3.0驱动,有些主板可能会出现蓝屏的问题,为了稳定,还是不集成了,否则一旦蓝屏,这个安装包就废了,不集成还有其他方案.WIN7原生不包括USB3.0驱动,不是我精简的原因.解决方法任选其一:①进BIOS