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