Java swing简易浏览器(其二)前进后退与收藏夹实现
【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
存前进时的链接
- 访问新页面:将frowQueue清空,backQueue塞入当前页面,当前页面跳转到目标页面
- 后退:forwQueue塞入当前页面,backQueue弹出一个页面作为新当前页面
- 前进: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());
}
下面给出addCurPageToFavorites
和deleteFavorite
方法的实现,都比较简单粗暴,就是直接将收藏读取进来,然后加入新内容(或者删除一些条目),再写入。
需要注意的是,使用同样的编码,比如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简易浏览器(其二)前进后退与收藏夹实现相关推荐
- Java swing简易浏览器(其一)页面显示,超链接跳转与手动输入URL跳转
[Java swing简易浏览器(其一)页面显示,超链接跳转与手动输入URL跳转] [Java swing简易浏览器(其二)前进后退与收藏夹实现] [java swing 简易浏览器(其三)下载器,智 ...
- 基于JxBrowser的浏览器控件封装实现Java Swing的浏览器集成
基于JxBrowser的浏览器控件封装实现Java Swing的浏览器集成 背景 实现目标 实现代码 运行效果 完整的代码及依赖jar文件下载 背景 进期客户提出在一个Java Swing项目要集成另 ...
- Java swing 简易文本编辑器
1.介绍几个相关的网址 精通Java Swing程序设计 BeautyEye社区 2.主要功能 tab页能够关闭(快捷键:ctrl+w,鼠标点击x) JMuneItem和Button快键键的几种绑定 ...
- 必学技术Java Swing之改变咖啡默认图标(建议收藏)
Java Swing之改变咖啡默认图标 引言:在这里我展示一下改变默认咖啡图标的代码,具体步骤我一一列出来了,有什么疑问的可以联系我哦.(编程软件是Intellij idea) 注:这里介绍一下ide ...
- google浏览器chrome无法导入IE收藏夹的问题
今天费了近2个小时down下chrome,安装后第一感觉就是简洁,速度快,还没有再深入研究,考虑先把收藏夹导过来方便浏览网页,在安装过程中已经选了从IE导入收藏夹,结果发现没有一个网页出现,又在工具栏 ...
- 2345浏览器卸载之后如何找回收藏夹中的内容?
2345真的是流氓软件吗?只看到网上各种喷2345浏览器是流氓软件,自己真的没有体会,因为我一直都认为2345浏览器和IE浏览器是一种东东,今天上网一查,搜嘎,我就明白了,这两者可真不是一种东西. 首 ...
- edge如何导入html文件收藏夹,edge浏览器收藏夹如何导入?edge浏览器收藏夹导入方法...
在使用浏览器的时候需要用户进行多方便的导入和使用,这样在数据共享和传递的时候才会更加的方便,那么这款软件要如何操作使用呢,有兴趣的用户可以使用手机快速申请使用,帮助用户的生活,让用户的生活更加的便捷, ...
- 360浏览器收藏夹_换了一台电脑,浏览器收藏的网站不见了,咋办?
导语:大家知道,用浏览器上网时,重要的网站要及时收藏,方便下次打开.但如果换电脑以后,收藏的网站就不见了.下面以360浏览器为例来说明一下 工具:网络收藏夹.360浏览器 说明:360的收藏夹就是网络 ...
- edge如何导入html文件收藏夹,win10浏览器 edge浏览器收藏夹怎么导入?
MWin10正式版Edge浏览器如何导入其它浏览器收藏夹内容呢?icrosoft edge浏览器现在也可以导入其他浏览器的收藏夹内的链接到Microsoft edge收藏夹中去.不过需要把太统升级到1 ...
最新文章
- ASP.NET中的页面指示标识
- Python - 列表与字符串的互相转换
- highcharts如何把图多余的空白页面_零基础如何快速学会WORD基础操作?有秘籍了.........
- ps自定义形状工具_PS教程——用PS绘制虚线的三种方法
- IOS Unit test
- iphone电池怎么保养_手机电池不耐用怎么办啊?平时要怎么保养呢?我来告诉你...
- P1969 积木大赛
- 英文标题大写格式化 在线网站
- 7-8 mmh学长的Excel表格 (20分)
- python中不包不包括_Python文件部分(不包括数据)
- html5家谱制作模板,Word如何做家谱世系图?
- 计算机设置调整吃鸡,绝地求生韦神托马斯主播的电脑画面设置灵敏度_绝地求生主播的电脑画面设置和灵敏度介绍_游戏吧...
- 它来了,任务调度框架 Quartz保姆级教程奉上
- 制作一个浪漫的表白网页
- 时间转换数字与日期互转
- 高学历就意味着高薪资?低学历转行3D建模,游戏建模成为首选!
- Tarjan模板 人工栈版Tarjan
- 测试进阶Mockserver之Moco框架搭建使用
- 小程序今日头条demo
- Linux高级运维 第八章 部署docker容器虚拟化平台