1. 程式人生 > >精簡版web瀏覽器

精簡版web瀏覽器

title edate checked url args 工具欄 menubar 其他 trac

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()); } }

加載頁面:

技術分享圖片

精簡版web瀏覽器