【Java swing简易浏览器(其一)页面显示,超链接跳转与手动输入URL跳转】

【Java swing简易浏览器(其二)前进后退与收藏夹实现】

【java swing 简易浏览器(其三)下载器,智能搜索栏与邮件发送】

目录

  • 前言
    • 关于封装
  • 要用到的swing组件
    • JMenuItem
    • JPopupMenu
    • JMenu
  • 思路
    • 收藏夹布局与存储
    • 前进后退
    • 刷新
  • 具体实现
    • 前进后退刷新
    • 收藏夹
  • 完整代码
  • 演示

前言

继续做互联网java大作业。。。。
上次的进度是【Java swing简易浏览器(其一)页面显示,超链接跳转与手动输入URL跳转】
老师要求太多了,只好一步一步来 。今天实现前进后退与收藏夹功能

关于封装

这次的功能是基于上一篇文章的代码来增加的

因为上次写的太散了,很多组件比如输入框,后面的应用都要用到它的内容,需要调用get方法
所以我 懒 索性建立一个MyHtmlBrowser类,将所有组件设成类的共有成员了,直接调用就好了不用final修饰半天。。。其他代码不变。

要用到的swing组件

JMenuItem

一个菜单的组件,可以拥有点击事件,配置它的点击事件也很简单

JMenuItem item = new JMenuItem("这是菜单选项1");
item .addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {// 做些什么}
});

JPopupMenu

弹出菜单,可以在指定位置弹出一个菜单栏,拥有成员方法.show

show 方法参数:(invoker对象,x坐标,y坐标)

我们需要传入一个鼠标点击事件MouseEvent对象,然后调用MouseEvent对象的getComponent()方法来取得invoker对象,xy坐标则是MouseEvent对象的getxy方法取得

public void showFavorites(MouseEvent e) throws Exception {JPopupMenu jpm = new JPopupMenu();jpm.show(e.getComponent(), e.getX(), e.getY());
}

不过因为我们没有添加【菜单选项】,即JMenuItem对象,所以显示不了。

JMenu

也是菜单,不过不是弹出菜单,而是静态菜单。

你可能会说:不是已经有JPopupMenu了吗,在里面添加JMenuItem对象不就好了吗,但是这样子比较难实现多级菜单

思路

收藏夹布局与存储

因为咱收藏夹需要两个选项,访问和删除,所以一个菜单条目需要几个选项

所以要通过在JPopupMenu组件里面套多个JMenu组件,每个JMenu里面套两个JMenuItem组件,分别是【访问这个收藏夹条目】和【删除这个收藏夹条目】

如何存储收藏夹?
可以使用一个txt文档来存收藏条目,用空格分割(当然也可以用其他的东西分割),然后我们每次从里面读取数据

前进后退

用两个栈来模拟访问即可,相信大家数据结构都写过这个题。。。 一共就实现三个操作即可。

我们用一个栈backQueue存后退时的链接的URL(字符串形式),另一个栈forwQueue存前进时的链接

  1. 访问新页面:将frowQueue清空,backQueue塞入当前页面,当前页面跳转到目标页面
  2. 后退:forwQueue塞入当前页面,backQueue弹出一个页面作为新当前页面
  3. 前进:backQueue塞入当前页面,forwQueue弹出一个页面作为新当前页面

刷新

JEditorPane对象调用setPage方法,传入当前页面即可。

具体实现

前进后退刷新

我们先实现一个函数叫updatePage,作用是把当前全局变量curPage的值,传给JEditorPane的setPage方法,同时改变浏览器输入框内的网址值。

然后实现其他三个函数

backwordPage : 后退
forwordPage : 前进
newPage : 创建新页面

方法和上面思路提到的一样。值得注意的是有些操作,比如回退,如果BackQueue里面空了,要将按钮设置为不可选择。

这里先给出函数的实现,因为网址栏的内容也要随着改变,所以我们先实现一个函数叫updatePage,作用是把当前全局变量curPage的值,传给JEditorPane的setPage方法,同时改变浏览器输入框内的网址值。

/** @function updatePage : 将页面设置为当前curPage指向的页面*/
public void updatePage() {jtf.setText(curPage);try {jep.setPage(curPage);} catch (IOException e) {jep.setText("<html><h1>连接错误或者超时!</h1><br><h1>您可以尝试刷新页面</h1></html>");}
}/** @function backwordPage : 回退*/
public void backwordPage() {if(backQueue.size()==0) return;forwQueue.offer(new String(curPage));curPage = backQueue.pollLast();updatePage();if(backQueue.size()==0) backBtn.setEnabled(false);forwBtn.setEnabled(true);
}/** @function forwordPage : 前进*/
public void forwordPage() {if(forwQueue.size()==0) return;backQueue.offer(new String(curPage));curPage = forwQueue.pollLast();updatePage();if(forwQueue.size()==0) forwBtn.setEnabled(false);backBtn.setEnabled(true);
}/** @function : newPage* @param np : 新页面的URL*/
public void newPage(String np) {backQueue.offer(new String(curPage));forwQueue.clear();curPage = new String(np);updatePage();backBtn.setEnabled(true);forwBtn.setEnabled(false);
}/** @function refreshPage : 刷新当前页面*/
public void refreshPage() {try {jep.setPage(curPage);} catch (IOException e) {jep.setText("<html><h1>连接错误或者超时!</h1><br><h1>您可以尝试刷新页面</h1></html>");}
}

因为还有刷新按钮,我们再写一个刷新的方法就行了。

/** @function refreshPage : 刷新当前页面*/
public void refreshPage() {try {jep.setPage(curPage);} catch (IOException e) {jep.setText("<html><h1>连接错误或者超时!</h1><br><h1>您可以尝试刷新页面</h1></html>");}
}

然后我们需要为菜单栏组件里面添加几个按钮,并且为这些按钮注册事件,事件内执行我们刚刚准备好的函数。

backBtn = new JButton("<—后退");
backBtn.setEnabled(false);
backBtn.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {backwordPage();}
});forwBtn = new JButton("前进—>");
forwBtn.setEnabled(false);
forwBtn.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {forwordPage();}
});refreshBtn = new JButton("刷新页面");
refreshBtn.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {refreshPage();}
});

还记得我们的全局变量

JPanel menuBox;      // 上方菜单栏box 装有很多按钮和输入框

我们调用menuBox的add方法,添加这些按钮即可。

收藏夹

收藏夹需要由一个按钮唤起,所以需要有一个按钮,我们为其注册鼠标点击事件,我们希望通过MouseEvent对象来唤起我们的收藏夹JPopupMenu组件

favoBtn = new JButton("收藏夹");
favoBtn.addMouseListener(new MouseListener() {public void mouseClicked(MouseEvent e) {try {showFavorites(e);} catch (Exception e1) {e1.printStackTrace();}}// 必须实现这些接口public void mousePressed(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseEntered(MouseEvent e) {}public void mouseExited(MouseEvent e) {}
});

你可能会问为啥我要用JPopupMenu,因为收藏夹的内容是动态更新的,使用JPopupMenu弹出菜单,每一次都从文件里面加载收藏夹条目,可以动态的显示。

这里面有一个showFavorites函数,正是我们唤起收藏夹的函数。我们调用这个方法来在鼠标点击的地方唤起一个JPopupMenu组件。

showFavorites方法中,我们读取本地txt文件获取收藏夹信息,然后按照信息添加对应的JMenu 组件和JMenuItem组件,布局规则见上文【思路】中提到的思路

除此之外我们还要添加一个JMenuItem,用于实现将当前页面加入收藏夹。

注意:以下两个方法的实现,下面会给出,现在先专注于收藏夹布局的实现

addCurPageToFavorites()  方法将当前页面加入收藏夹
deleteFavorite()        方法删除指定的收藏条目

布局效果:

/** @function showFavorites : 显示当前收藏夹* @param e                   : 【收藏夹】按钮被点击时传入的鼠标事件MouseEvent对象*/
public void showFavorites(MouseEvent e) throws Exception {JPopupMenu jpm = new JPopupMenu();JMenuItem addItem = new JMenuItem("添加当前网址到收藏夹");addItem.setForeground(new Color(110,148,252));addItem.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {addCurPageToFavorites();//System.out.println("12313dadw");}});jpm.add(addItem);// 打开文件流读取收藏夹本地信息FileInputStream is = new FileInputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));String line;while((line=reader.readLine())!=null) {// System.out.println(line);final String key = line.split(" ")[0]; // 键final String val = line.split(" ")[1];   // 值 即网址// 创建删除收藏按钮并添加事件JMenu item = new JMenu(key);JMenuItem delItem = new JMenuItem("取消收藏");delItem.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {deleteFavorite(key+" "+val);}});// 创建访问网址按钮并添加事件JMenuItem goItem = new JMenuItem("访问");goItem.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {newPage(val);}});item.add(goItem);item.add(delItem);jpm.add(item);}jpm.show(e.getComponent(), e.getX(), e.getY());
}

下面给出addCurPageToFavoritesdeleteFavorite方法的实现,都比较简单粗暴,就是直接将收藏读取进来,然后加入新内容(或者删除一些条目),再写入。

需要注意的是,使用同样的编码,比如utf-8

/** @function deleteFavorite : 删除指定的收藏夹条目* @param delLine          : 收藏夹完整条目即 【键 空格 值】的字符串*/
public void deleteFavorite(String delLine) {try {// 读取 但是不读取要删除的行FileInputStream is = new FileInputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));String line;LinkedList<String> lines = new LinkedList<String>();while((line=reader.readLine())!=null) {if(!delLine.equals(line)) {lines.offer(line);}}is.close();// 写入读取的内容FileOutputStream os = new FileOutputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "utf-8"));for(String l : lines) {writer.write(l+"\r\n");}writer.flush();writer.close();os.close();} catch(Exception e) {e.printStackTrace();}
}/** @function addCurPageToFavorites : 将当前页面添加到收藏夹*/
public void addCurPageToFavorites() {try {// 正则表达式找<tile>标签作为标题Pattern r = Pattern.compile("(<title>)(.*?)(<)");Matcher m = r.matcher(jep.getText());String title = "新标签页";if(m.find()) {// System.out.println(m.group(2));title = m.group(2);}// 读取FileInputStream is = new FileInputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));String line;LinkedList<String> lines = new LinkedList<String>();while((line=reader.readLine())!=null) {lines.offer(line);}is.close();// 写入读取的内容FileOutputStream os = new FileOutputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "utf-8"));for(String l : lines) {writer.write(l+"\r\n");}writer.write(title+" "+curPage+"\r\n");  // 在末尾写入新条目writer.flush();writer.close();os.close();} catch(Exception e) {e.printStackTrace();}
}

完整代码

/*
author : 李若龙 2018171028
*/
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.*;
import java.util.regex.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.html.*;public class MyHtmlBrowser {String curPage = "http://www.szulrl.cn/browserTest"; JEditorPane jep; // html显示组件JPanel menuBox;      // 上方菜单栏box 装有很多按钮和输入框JButton goBtn;        // 【点我访问】按钮JButton backBtn; // 回退按钮JButton forwBtn; // 前进按钮JButton refreshBtn;  // 刷新按钮JButton favoBtn; // 收藏夹按钮 点击调出收藏夹JTextField jtf;     // 输入框// 前进后退的栈 用双端队列实现Deque<String> backQueue = new LinkedList<String>();Deque<String> forwQueue = new LinkedList<String>();MyHtmlBrowser() {}MyHtmlBrowser(String cp) {curPage = cp;}/** @function updatePage : 将页面设置为当前curPage指向的页面*/public void updatePage() {jtf.setText(curPage);try {jep.setPage(curPage);} catch (IOException e) {jep.setText("<html><h1>连接错误或者超时!</h1><br><h1>您可以尝试刷新页面</h1></html>");}  }/** @function backwordPage : 回退*/public void backwordPage() {if(backQueue.size()==0) return;forwQueue.offer(new String(curPage));curPage = backQueue.pollLast();updatePage();if(backQueue.size()==0) backBtn.setEnabled(false);forwBtn.setEnabled(true);}/** @function forwordPage : 前进*/public void forwordPage() {if(forwQueue.size()==0) return;backQueue.offer(new String(curPage));curPage = forwQueue.pollLast();updatePage();if(forwQueue.size()==0) forwBtn.setEnabled(false);backBtn.setEnabled(true);}/** @function : newPage* @param np : 新页面的URL*/public void newPage(String np) {backQueue.offer(new String(curPage));forwQueue.clear();curPage = new String(np);updatePage();backBtn.setEnabled(true);forwBtn.setEnabled(false);}/** @function refreshPage : 刷新当前页面*/public void refreshPage() {try {jep.setPage(curPage);} catch (IOException e) {jep.setText("<html><h1>连接错误或者超时!</h1><br><h1>您可以尝试刷新页面</h1></html>");}}/** @function deleteFavorite : 删除指定的收藏夹条目* @param delLine            : 收藏夹完整条目即 【键 空格 值】的字符串*/public void deleteFavorite(String delLine) {try {// 读取 但是不读取要删除的行FileInputStream is = new FileInputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));String line;LinkedList<String> lines = new LinkedList<String>();while((line=reader.readLine())!=null) {if(!delLine.equals(line)) {lines.offer(line);}}is.close();// 写入读取的内容FileOutputStream os = new FileOutputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "utf-8"));for(String l : lines) {writer.write(l+"\r\n");}writer.flush();writer.close();os.close();} catch(Exception e) {e.printStackTrace();}}/** @function addCurPageToFavorites : 将当前页面添加到收藏夹*/public void addCurPageToFavorites() {try {Pattern r = Pattern.compile("(<title>)(.*?)(<)");Matcher m = r.matcher(jep.getText());String title = "新标签页";if(m.find()) {// System.out.println(m.group(2));title = m.group(2);}// 读取FileInputStream is = new FileInputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));String line;LinkedList<String> lines = new LinkedList<String>();while((line=reader.readLine())!=null) {lines.offer(line);}is.close();// 写入读取的内容FileOutputStream os = new FileOutputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "utf-8"));for(String l : lines) {writer.write(l+"\r\n");}writer.write(title+" "+curPage+"\r\n");writer.flush();writer.close();os.close();} catch(Exception e) {e.printStackTrace();}}/** @function showFavorites : 显示当前收藏夹* @param e                  : 【收藏夹】按钮被点击时传入的鼠标事件MouseEvent对象*/public void showFavorites(MouseEvent e) throws Exception {JPopupMenu jpm = new JPopupMenu();JMenuItem addItem = new JMenuItem("添加当前网址到收藏夹");addItem.setForeground(new Color(110,148,252));addItem.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {addCurPageToFavorites();//System.out.println("12313dadw");}});jpm.add(addItem);// 打开文件流读取收藏夹本地信息FileInputStream is = new FileInputStream("E:/MyEclipse/WorkSpace/Hello/src/homework/favorites.txt");BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));String line;while((line=reader.readLine())!=null) {// System.out.println(line);final String key = line.split(" ")[0];    // 键final String val = line.split(" ")[1];   // 值 即网址// 创建删除收藏按钮并添加事件JMenu item = new JMenu(key);JMenuItem delItem = new JMenuItem("取消收藏");delItem.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {deleteFavorite(key+" "+val);}});// 创建访问网址按钮并添加事件JMenuItem goItem = new JMenuItem("访问");goItem.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {newPage(val);}});item.add(goItem);item.add(delItem);jpm.add(item);}jpm.show(e.getComponent(), e.getX(), e.getY());}/** @function start : 浏览器初始化,然后开始运作*/public void start() throws Exception {jep = new JEditorPane();jep.setEditable(false);// 添加超链接点击事件回调函数 并将JEditorPane的页面改为超链接的页面jep.addHyperlinkListener(new HyperlinkListener() {public void hyperlinkUpdate(HyperlinkEvent event) {if(event.getEventType()==HyperlinkEvent.EventType.ACTIVATED) {newPage(event.getURL().toString());}}});// 设置主页jep.setContentType("text/html;charset=utf-8");try {jep.setPage(curPage);} catch (IOException e) {jep.setText("<html><h1>连接错误或者超时!</h1><br><h1>您可以尝试刷新页面</h1></html>");}// 带滑动条的组件 用于存放显示html的jep组件JScrollPane scrollpane = new JScrollPane(jep);// 访问按钮 绑定访问按钮点击事件 从JTextField输入框获取URL并且访问goBtn = new JButton("点我访问网页");goBtn.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {// jep.setPage(jtf.getText());String input = jtf.getText();if(input.equals(curPage)) {refreshPage();} else if(input.length()>4 && input.substring(0, 4).equals("http")){newPage(jtf.getText());} else {newPage("https://cn.bing.com/search?q=" + jtf.getText());}}});// 输入框 输入URLjtf = new JTextField(40);jtf.setText(curPage);// 绑定回车按键事件jtf.addKeyListener(new KeyAdapter() {public void keyPressed(KeyEvent event) {if(event.getKeyChar()==KeyEvent.VK_ENTER) {goBtn.doClick();   // 按下回车等于点击按钮}}});backBtn = new JButton("<—后退");backBtn.setEnabled(false);backBtn.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {backwordPage();}});forwBtn = new JButton("前进—>");forwBtn.setEnabled(false);forwBtn.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {forwordPage();}});refreshBtn = new JButton("刷新页面");refreshBtn.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {refreshPage();}});favoBtn = new JButton("收藏夹");favoBtn.addMouseListener(new MouseListener() {public void mouseClicked(MouseEvent e) {try {showFavorites(e);} catch (Exception e1) {e1.printStackTrace();}}// 必须实现这些接口public void mousePressed(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseEntered(MouseEvent e) {}public void mouseExited(MouseEvent e) {}});// 上方菜单盒子JPanel menuBox = new JPanel();menuBox.add(backBtn);menuBox.add(forwBtn);menuBox.add(refreshBtn);menuBox.add(jtf);menuBox.add(goBtn);menuBox.add(favoBtn);// 主窗体JFrameJFrame jf = new JFrame("369危险浏览器");jf.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);jf.setSize(1024,768);// 添加组件jf.add(menuBox, BorderLayout.NORTH);jf.add(scrollpane, BorderLayout.CENTER);// 添加组件jf.show();}public static void main(String[] args) throws Exception {MyHtmlBrowser browser = new MyHtmlBrowser();browser.start();}}

演示

Java swing简易浏览器(其二)前进后退与收藏夹实现相关推荐

  1. Java swing简易浏览器(其一)页面显示,超链接跳转与手动输入URL跳转

    [Java swing简易浏览器(其一)页面显示,超链接跳转与手动输入URL跳转] [Java swing简易浏览器(其二)前进后退与收藏夹实现] [java swing 简易浏览器(其三)下载器,智 ...

  2. 基于JxBrowser的浏览器控件封装实现Java Swing的浏览器集成

    基于JxBrowser的浏览器控件封装实现Java Swing的浏览器集成 背景 实现目标 实现代码 运行效果 完整的代码及依赖jar文件下载 背景 进期客户提出在一个Java Swing项目要集成另 ...

  3. Java swing 简易文本编辑器

    1.介绍几个相关的网址 精通Java Swing程序设计 BeautyEye社区 2.主要功能 tab页能够关闭(快捷键:ctrl+w,鼠标点击x) JMuneItem和Button快键键的几种绑定 ...

  4. 必学技术Java Swing之改变咖啡默认图标(建议收藏)

    Java Swing之改变咖啡默认图标 引言:在这里我展示一下改变默认咖啡图标的代码,具体步骤我一一列出来了,有什么疑问的可以联系我哦.(编程软件是Intellij idea) 注:这里介绍一下ide ...

  5. google浏览器chrome无法导入IE收藏夹的问题

    今天费了近2个小时down下chrome,安装后第一感觉就是简洁,速度快,还没有再深入研究,考虑先把收藏夹导过来方便浏览网页,在安装过程中已经选了从IE导入收藏夹,结果发现没有一个网页出现,又在工具栏 ...

  6. 2345浏览器卸载之后如何找回收藏夹中的内容?

    2345真的是流氓软件吗?只看到网上各种喷2345浏览器是流氓软件,自己真的没有体会,因为我一直都认为2345浏览器和IE浏览器是一种东东,今天上网一查,搜嘎,我就明白了,这两者可真不是一种东西. 首 ...

  7. edge如何导入html文件收藏夹,edge浏览器收藏夹如何导入?edge浏览器收藏夹导入方法...

    在使用浏览器的时候需要用户进行多方便的导入和使用,这样在数据共享和传递的时候才会更加的方便,那么这款软件要如何操作使用呢,有兴趣的用户可以使用手机快速申请使用,帮助用户的生活,让用户的生活更加的便捷, ...

  8. 360浏览器收藏夹_换了一台电脑,浏览器收藏的网站不见了,咋办?

    导语:大家知道,用浏览器上网时,重要的网站要及时收藏,方便下次打开.但如果换电脑以后,收藏的网站就不见了.下面以360浏览器为例来说明一下 工具:网络收藏夹.360浏览器 说明:360的收藏夹就是网络 ...

  9. edge如何导入html文件收藏夹,win10浏览器 edge浏览器收藏夹怎么导入?

    MWin10正式版Edge浏览器如何导入其它浏览器收藏夹内容呢?icrosoft edge浏览器现在也可以导入其他浏览器的收藏夹内的链接到Microsoft edge收藏夹中去.不过需要把太统升级到1 ...

最新文章

  1. ASP.NET中的页面指示标识
  2. Python - 列表与字符串的互相转换
  3. highcharts如何把图多余的空白页面_零基础如何快速学会WORD基础操作?有秘籍了.........
  4. ps自定义形状工具_PS教程——用PS绘制虚线的三种方法
  5. IOS Unit test
  6. iphone电池怎么保养_手机电池不耐用怎么办啊?平时要怎么保养呢?我来告诉你...
  7. P1969 积木大赛
  8. 英文标题大写格式化 在线网站
  9. 7-8 mmh学长的Excel表格 (20分)
  10. python中不包不包括_Python文件部分(不包括数据)
  11. html5家谱制作模板,Word如何做家谱世系图?
  12. 计算机设置调整吃鸡,绝地求生韦神托马斯主播的电脑画面设置灵敏度_绝地求生主播的电脑画面设置和灵敏度介绍_游戏吧...
  13. 它来了,任务调度框架 Quartz保姆级教程奉上
  14. 制作一个浪漫的表白网页
  15. 时间转换数字与日期互转
  16. 高学历就意味着高薪资?低学历转行3D建模,游戏建模成为首选!
  17. Tarjan模板 人工栈版Tarjan
  18. 测试进阶Mockserver之Moco框架搭建使用
  19. 小程序今日头条demo
  20. Linux高级运维 第八章 部署docker容器虚拟化平台

热门文章

  1. Vue computed自动计算对象中的属性
  2. python数据挖掘-oneR算法
  3. 使用OneR算法进行分类(Python实现)
  4. Linux下固态硬盘坏块修复,固态硬盘如果发现坏块就完蛋了
  5. python爬虫爬妹子图_【爬虫】直接上干货-爬取妹子图整站图片
  6. 深入Flutter(四) Infinite scrolling -- 无限滚动
  7. 漫谈微信libco协程设计及实现(万字长文)
  8. 程序猿必备福利之二上篇!!!简易使用Nodejs实现从美图网爬取清晰脱俗的美图???
  9. IO流---基础 (附相对路径)
  10. 黑色曼陀罗的宿命,无尽的结束,留下伤痛与悲残