JAVA简易网页浏览器
2021-09-13
代码:
package WebBrowser;
import javax.swing.*;//提供按钮类
//
import java.awt.*;//提供用户界面原件
import java.net.*;//提供支持联网的类
import java.io.*;//提供输入输出流
import java.awt.event.*;
import javax.swing.event.*;
import java.util.*;//提供实用方法和数据结构
public class Browser extends JFrame implements HyperlinkListener,ActionListener{//HyperlinkListener,
JFrame jf = new JFrame("网页浏览器");
//总体布局分为两个部分,两个盒子,垂直分布
Box root = Box.createVerticalBox();//创建一个从上到下显示其组件的Box
JFileChooser chooser = new JFileChooser();//文件选择器,提供了一种文件选择机制
//菜单条,菜单,菜单项
JMenuBar bar = new JMenuBar();//创建菜单条
JMenu menu1 = new JMenu("文件(F)");//创建菜单
JMenu menu2 = new JMenu("编辑(E)");
JMenu menu3 = new JMenu("视图(V)");
JMenuItem item1 = new JMenuItem("另存为(A)");//创建菜单项
JMenuItem item2 = new JMenuItem("退出(I)"); //快捷键后续添加
JMenuItem item3 = new JMenuItem("前进");
JMenuItem item4 = new JMenuItem("后退");
JMenuItem item5 = new JMenuItem("全屏");
JMenuItem item6 = new JMenuItem("源代码(C)");
JMenuItem item7 = new JMenuItem("刷新");
Box line1 = Box.createHorizontalBox();//创建一个从左到右显示其组件的Box
JToolBar tb = new JToolBar();//工具栏
JButton b1 = new JButton("另存为");//为工具栏增加按钮
JButton b2 = new JButton("后退");
JButton b3 = new JButton("前进");
JButton b4 = new JButton("查看源代码");
JButton b5 = new JButton("退出");
Box line2 = Box.createHorizontalBox();
//第二个工具栏(包括地址,文本框,按钮转向)
JToolBar tb1 = new JToolBar();
JTextField jt = new JTextField();//创建一个文本框
JLabel label = new JLabel("地址");
JButton b6 = new JButton("转向");
Box line3 = Box.createHorizontalBox();
//网页显示界面 滚动条
JEditorPane jp1 = new JEditorPane();//JEditorPane最主要功能在于展现不同类型的文件格式内容
//JTextField jt2 = new JTextField(50);//文本框
JScrollPane sp = new JScrollPane(jp1);//滚动条
//private ArrayList history = new ArrayList(); //Arraylist对象,用来存放历史地址
//private int historyindex;// 整型变量,表示历史地址的访问顺序
//前进后退的栈 用双端队列实现
Deque<String> backQueue = new LinkedList<String>();
Deque<String> forwQueue = new LinkedList<String>();
//构造函数
public Browser() {
jf.setSize(1200,700); //组件大小(窗口的大小)
jf.setLocation(300,200);//组件显示位置
jf.setContentPane(root);
bar.add(menu1);//将菜单添加到菜单栏中
bar.add(menu2);
bar.add(menu3);
menu1.setMnemonic('F');
menu2.setMnemonic('E');
menu3.setMnemonic('V');
item1.setMnemonic('A');//设置热键
item1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_MASK));//快捷键
item2.setMnemonic('I');
item2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E,InputEvent.CTRL_MASK));
item4.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z,InputEvent.CTRL_MASK));
item3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D,InputEvent.CTRL_MASK));
item5.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U,InputEvent.CTRL_MASK));
item6.setMnemonic('C');
item6.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,InputEvent.CTRL_MASK));
item7.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,InputEvent.CTRL_MASK));
menu1.add(item1);//将菜单项添加到对应菜单中
menu1.add(item2);
menu2.add(item3);
menu2.add(item4);
menu3.add(item5);
menu3.add(item6);
menu3.add(item7);
line1.add(bar);
line1.setMaximumSize(new Dimension(9999,20));//dimension是java的一个类,封装了一个构件的高度和宽度
line1.setPreferredSize(new Dimension(9999,18));
tb.add(b1);//工具栏中添加按钮
tb.add(b2);
tb.add(b3);
tb.add(b4);
tb.add(b5);
line2.add(Box.createHorizontalStrut(0));//createHorizontalStrut(int width)左右部件之间的中间间隔就可以用这个方法来控制
line2.add(tb);
tb.setMaximumSize(new Dimension(9999,30));
line2.setMaximumSize(new Dimension(9999,30));
line2.setPreferredSize(new Dimension(9999,30));
jt.setColumns(50);//设置文本框长度,50个字符
tb1.add(label);
tb1.add(jt);
tb1.add(b6);
line3.add(Box.createHorizontalStrut(0));
line3.add(tb1);
jt.setMaximumSize(new Dimension(9999,30));
line3.setMaximumSize(new Dimension(9999,30));
line3.setPreferredSize(new Dimension(9999,30));
root.add(line1);
root.add(line2);
root.add(line3);
sp.setBounds(13,10,350,340);//设置矩形大小.参数依次为(矩形左上角横坐标x,矩形左上角纵坐标y,矩形长度,矩形宽度)
//默认的设置是超过文本框才会显示滚动条,以下设置让滚动条一直显示
sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jf.getContentPane().add(sp);
//为组件添加事件监听
item1.addActionListener(this);
item2.addActionListener(this);
item3.addActionListener(this);
item4.addActionListener(this);
item5.addActionListener(this);
item6.addActionListener(this);
item7.addActionListener(this);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
b4.addActionListener(this);
b5.addActionListener(this);
b6.addActionListener(this);
jt.addActionListener(this);
jp1.addHyperlinkListener(this);//添加事件监听(超链接)
jf.setVisible(true); //设置组件可见,false为不可见
}
//实现接口ActionListener的抽象函数
public void actionPerformed(ActionEvent e) {
String ur1 = " ";
//点击转向按钮
if(e.getSource()==b6) { //getSource()获得事件源
ur1 = jt.getText(); //获取地址栏的内容
//1.ur1不为空,且以http://开头
if(ur1.length()>0&&ur1.startsWith("http://")) {
try {
jp1.setPage(ur1);//JEditorpane组件显示ur1的链接内容
backQueue.offer(ur1);
forwQueue.clear();
jp1.setPage(ur1);
jp1.setEditable(false);//JEditorpane显示的页面禁止编辑
jp1.revalidate();//revalidate()方法会重新计算容器内所有组件的大小,并重新布局
}
catch(Exception ex) {//Exception是我们所使用的异常类的父类
//如果链接显示失败,则弹出选择对话框‘无法打开该搜索页’
JOptionPane.showMessageDialog(Browser.this, "无法打开该搜索页","网页浏览器",JOptionPane.ERROR_MESSAGE);
}
}
//2.ur1不为空,不以http:开头
else if(ur1.length()>0&&!ur1.startsWith("http://")) {
ur1 = "http://"+ur1;
try {
jp1.setPage(ur1);
//history.add(ur1);
//historyindex = history.size()-1;
backQueue.offer(ur1);
forwQueue.clear();
jp1.setPage(ur1);
jp1.setEditable(false);
jp1.revalidate();
}
catch(Exception ex) {
JOptionPane.showMessageDialog(Browser.this, "无法打开该搜索页","网页浏览器",JOptionPane.ERROR_MESSAGE);
}
}
//3.ur1为空
else if(ur1==" ") { //(ur1.length() == 0)
JOptionPane.showMessageDialog(Browser.this, "无法打开该搜索页","网页浏览器",JOptionPane.ERROR_MESSAGE);
}
}
//输入地址后点击回车
//另存为
else if(e.getSource()==item1||e.getSource()==b1) {
ur1 = jt.getText().trim();//去掉字符串头和尾的空格
if(ur1.length()>0&&!ur1.startsWith("http://")) {
ur1="http://" + ur1;
}
if(!ur1.equals("")) {
// 保存文件
saveFile(ur1);
}
else {
JOptionPane.showMessageDialog(Browser.this, "请输入链接地址 ", "网页浏览器", JOptionPane.ERROR_MESSAGE);
}
}
//退出
else if(e.getSource()==item2||e.getSource()==b5) {
System.exit(0);
}
//全屏
else if(e.getSource()==item5) {
jf.setExtendedState(JFrame.MAXIMIZED_BOTH);//窗口最大化函数
}
//后退 forwQueue塞入当前页面,backQueue弹出一个页面作为新页面
else if(e.getSource()==item4||e.getSource()==b2) {
if(backQueue.size()==0) return;
ur1 = jt.getText();
forwQueue.offer(ur1);
@SuppressWarnings("unused")
String ur2 = backQueue.pollLast();
jt.setText(ur2);
try {
jp1.setPage(ur2);
}
catch(Exception ex){
JOptionPane.showMessageDialog(Browser.this, "无法打开该搜索页","网页浏览器",JOptionPane.ERROR_MESSAGE);
}
/*if(backQueue.size()==0) { //如果backQueue为空,设置后退按钮为不可选择
item4.setEnabled(false);
b2.setEnabled(false);
}
item3.setEnabled(true);*/
}
//前进 backQueue塞入当前页面,forwQueue弹出一个页面作为新当前页面
else if(e.getSource()==item3||e.getSource()==b3) {
//if(backQueue.size()==0) return;
ur1 = jt.getText();
backQueue.offer(ur1);//offerFirst()向栈顶插入元素
@SuppressWarnings("unused")
String ur2 = forwQueue.pollLast();//获取并删除栈尾元素
jt.setText(ur2);
try {
jp1.setPage(ur2);
}
catch(Exception ex){
JOptionPane.showMessageDialog(Browser.this, "无法打开该搜索页","网页浏览器",JOptionPane.ERROR_MESSAGE);
}
/*if(forwQueue.size()==0) {//设置按钮不可选择
item3.setEnabled(false);
b3.setEnabled(false);
}
item4.setEnabled(true);*/
}
//刷新
else if(e.getSource()==item7) {
ur1 = jt.getText();
if(ur1.length()>0&&ur1.startsWith("http://")) {
try {
jp1.setPage(ur1);
}
catch(Exception ex) {
JOptionPane.showMessageDialog(Browser.this, "无法打开该搜索页","网页浏览器",JOptionPane.ERROR_MESSAGE);
}}
else if(ur1.length()>0&&!ur1.startsWith("http://")) {
ur1 = "http://"+ur1;
try {
jp1.setPage(ur1);
}
catch(Exception ex) {
JOptionPane.showMessageDialog(Browser.this, "无法打开该搜索页","网页浏览器",JOptionPane.ERROR_MESSAGE);
}}
}
//源代码
if(e.getSource()==item6||e.getSource()==b4) {
String ur=jt.getText();
JFrame Frame2=new JFrame("源代码");
Frame2.setBounds(600,90,600,200);
JToolBar toolbar=new JToolBar();
JButton toolSave,toolQuit;
toolSave=new JButton("保存");
toolQuit=new JButton("退出");
toolbar.add(toolSave);
toolbar.add(toolQuit);
//创建JEditorPane(单元窗格)对象和JScrollPane(滚动面板)对象
JEditorPane ed1 = new JEditorPane();;
JScrollPane jsp1 = new JScrollPane(ed1);;
//将JEditorPane(单元窗格)加入JScrollPane(滚动面板)中
Frame2.add(jsp1);
Frame2.add(toolbar,BorderLayout.SOUTH);
try {
URL url2 = new URL(ur);
InputStream inStream =url2.openStream();//opemStream将网页转化为流
BufferedReader in =new BufferedReader(new InputStreamReader(inStream,"utf-8"));
String line;
while((line=in.readLine())!=null) {
ed1.setText(line);
}
Frame2.setVisible(true);
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
//退出按钮设置
toolQuit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource()==toolQuit) {
Frame2.dispose();
}
}
});
//保存按钮设置
toolSave.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource()==toolSave) {
File source = new File("D://index.html");//创建txt文本
try {
FileWriter fw = new FileWriter(source);//字符输出流
String read = ed1.getText();//获取源代码区域内容
fw.write(read);
//弹出提示框
JOptionPane.showInputDialog(this, "源代码保存成功!");
fw.close();//关闭流
} catch (IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
}
});
}
}
//保存文件
void saveFile(final String ur1) {
final String linesep=System.getProperty("line.separator");//获得指定键指示的系统属性
chooser.setCurrentDirectory(new File("."));//设置当前目录
chooser.setDialogType(JFileChooser.SAVE_DIALOG);//设置此对话框的类型,指示JFileChooser支持Save文件操作的类型值
chooser.setDialogTitle("另存为");//设置显示在JFileChooser窗口标题栏的字符串
if(chooser.showSaveDialog(this)!=JFileChooser.APPROVE_OPTION)//弹出一个SaveFile文件选择器对话框,选择确认(yes,ok)后返回该值
return;
this.repaint();//重绘
Thread thread=new Thread() {
public void run(){
try {
java.net.URL source=new URL(ur1);//将字符串形式的URL地址可以打包成java.net.URL实例
InputStream in=new BufferedInputStream(source.openStream());//
BufferedReader br=new BufferedReader(new InputStreamReader(in));//起到缓存作用
File fileName=chooser.getSelectedFile();//返回选中的文件
FileWriter out=new FileWriter(fileName);
BufferedWriter bw=new BufferedWriter(out);//起到缓存作用
String line;
while((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();//写入一个分隔符
}
bw.flush();
bw.close();
out.close();
String dMessage=ur1+"已经被保存至"+linesep+fileName.getAbsolutePath();//返回抽象路径名的绝对路径名字符串
String dTitle="另存为";
int dType=JOptionPane.INFORMATION_MESSAGE;//用户选择项目
JOptionPane.showMessageDialog((Component)null,dMessage,dTitle,dType);//显示MessageDialog
}
catch(java.net.MalformedURLException muex) {
JOptionPane.showMessageDialog((Component)null,muex.toString(),"网页浏览器",JOptionPane.ERROR_MESSAGE);
}
catch(Exception ex) {
JOptionPane.showMessageDialog((Component)null,ex.toString(),"网页浏览器",JOptionPane.ERROR_MESSAGE);
}
}
};
thread.start();
}
public void hyperlinkUpdate(HyperlinkEvent e)//超链接事件
{
try {
if(e.getEventType()==HyperlinkEvent.EventType.ACTIVATED)
jp1.setPage(e.getURL());
jt.setText(e.getURL().toString());
//historyindex=history.size()-1;
//backQueue.offer(e.getURL().toString());
//forwQueue.clear();
//jp1.setPage(e.getURL());
}
catch(Exception ex) {
ex.printStackTrace(System.err);
}
}
public static void main(String[] args) {
try { UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());//使用LookAndFeel对象设置当前的默认外设
}
catch(Exception e)
{
}
Browser p2=new Browser();
p2.pack();
p2.setVisible(true);
}
}
运行结果: