Java课程设计
1. 题目及要求
基于学校的搜索引擎
- 负责部分:Java GUI设计
2.界面调查
1)调查界面:百度
2)思考:
根据我的调查,我认为我需要完成三个界面的设计:
-
第一个是调查主界面,里面有一个集美大学的logo,一个搜索框用文本字段,因为需要在里面写入搜索内容,一个搜索按钮用button,这个按钮完成的功能就是输入搜索内容后,点击搜索按钮,可以跳转到下一个界面,并且返回结果。
-
第二个界面是搜索结果界面:需要的是一个再次搜索框,用文本字段;一个再次搜索按钮,用button;一个面板JPanel,用来盛放我搜索到的结果;在界面的最底下还有三个按钮,一个文本框,分别是:上一页,下一页,跳转,和相应页面表示,当数据量过大需要分页时,就是用来实现页面的跳转的。
-
第三个就是结果展示界面:一个jLabel,展示标题;一个文本区域展示内容;一个按钮,点击能够跳转到原网页浏览。
3.我的代码
1.EsGuiSearch.java
package edu.net.itsearch.gui;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import crawler.SearchResultEntry;
import edu.net.itsearch.elasticsearch.EsClient;
import io.searchbox.client.JestClient;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
/**
*
* @author xingkyh
*/
public class EsGuiSearch {
private JestClient jestClient;
public EsGuiSearch() {
this.jestClient=EsClient.getJestClient();
}
/**
* 全文检索
*
* @param queryString 搜索字符串
* @return 检索结果
*/
public List<SearchResultEntry> fullTextSerch(String queryString) {
// 声明一个搜索请求体
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.queryStringQuery(queryString));
searchSourceBuilder.query(boolQueryBuilder);
// 设置分页
searchSourceBuilder.from(0);
searchSourceBuilder.size(800);
// 构建Search对象
Search search = new Search.Builder(searchSourceBuilder.toString()).addIndex(EsClient.indexName)
.addType(EsClient.typeName).build();
SearchResult searchResult = null;
try {
searchResult = jestClient.execute(search);
} catch (IOException e) {
e.printStackTrace();
}
List<SearchResultEntry> list=new ArrayList<SearchResultEntry>();
List<SearchResult.Hit<SearchResultEntry, Void>> hits = searchResult.getHits(SearchResultEntry.class);
for (SearchResult.Hit<SearchResultEntry, Void> hit : hits) {
list.add(hit.source);
}
return list;
}
public void close() throws IOException {
EsClient.closeJestClient();
}
}
2.SearchMainPage.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package edu.net.itsearch.gui;
import java.util.List;
import javax.swing.JOptionPane;
import crawler.SearchResultEntry;
/**
*
* @author 格格
*/
public class SearchMainPage extends javax.swing.JFrame {
/**
* Creates new form searchMainPage
*/
public SearchMainPage() {
initComponents();
esGuiSearch=new EsGuiSearch();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
private void initComponents() {
searchBox = new javax.swing.JTextField();
searchButton = new javax.swing.JButton();
picture = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
searchButton.setText("搜索");
searchButton.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
searchButtonActionPerformed(evt);
}
});
picture.setIcon(new javax.swing.ImageIcon(getClass().getResource("jmu.png")));
picture.setText("jLabel2");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(68, 68, 68)
.addComponent(searchBox, javax.swing.GroupLayout.PREFERRED_SIZE, 516, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(searchButton, javax.swing.GroupLayout.DEFAULT_SIZE, 78, Short.MAX_VALUE)
.addContainerGap())
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(picture, javax.swing.GroupLayout.PREFERRED_SIZE, 168, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(256, 256, 256))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(46, 46, 46)
.addComponent(picture)
.addGap(36, 36, 36)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(searchBox, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(searchButton, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(140, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {
String queryString=searchBox.getText();
List<SearchResultEntry> list = esGuiSearch.fullTextSerch(queryString);
if(list.isEmpty()) {
JOptionPane.showMessageDialog(null, "未搜索到相关内容!");
}else {
SearchResult searchResult = new SearchResult(list);
searchResult.setVisible(true);
dispose();
}
}
private EsGuiSearch esGuiSearch;
private javax.swing.JLabel picture;
private javax.swing.JTextField searchBox;
private javax.swing.JButton searchButton;
// End of variables declaration
}
3.SearchResult.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package edu.net.itsearch.gui;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import crawler.SearchResultEntry;
/**
*
* @author 格格
*/
public class SearchResult extends javax.swing.JFrame {
/**
* Creates new form searchResult
*/
public SearchResult() {
initComponents();
}
public SearchResult(List<SearchResultEntry> list){
initComponents();
esGuiSearch=new EsGuiSearch();
resultList = getJpanelList(list);
resultNum = list.size();
pageNum = (resultList.size()+1)/2;
currentPage = 1;
displayResult();
}
private void displayResult(){
resultJpanel.removeAll();
resultJpanel.setLayout(new GridLayout(2, 1));
resultJpanel.add(resultList.get(currentPage*2-2));
if(currentPage+currentPage <= resultNum){
resultJpanel.add(resultList.get(currentPage*2-1));
}
resultJpanel.revalidate();
resultJpanel.repaint();
page.setText(currentPage+"/"+pageNum);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
private void initComponents() {
searchAgainButton = new javax.swing.JButton();
resultJpanel = new javax.swing.JPanel();
jumpLastPage = new javax.swing.JButton();
jumpNextPage = new javax.swing.JButton();
jumpChoosePage = new javax.swing.JButton();
searchAgainBox = new javax.swing.JTextField();
page = new javax.swing.JTextField();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
searchAgainButton.setText("搜索");
searchAgainButton.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
searchAgainButtonPerformed(evt);
}
});
javax.swing.GroupLayout resultJpanelLayout = new javax.swing.GroupLayout(resultJpanel);
resultJpanel.setLayout(resultJpanelLayout);
resultJpanelLayout.setHorizontalGroup(
resultJpanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
resultJpanelLayout.setVerticalGroup(
resultJpanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 276, Short.MAX_VALUE)
);
jumpLastPage.setText("上一页");
jumpLastPage.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
jumpLastPageActionPerformed(evt);
}
});
jumpNextPage.setText("下一页");
jumpNextPage.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
jumpNextPageActionPerformed(evt);
}
});
jumpChoosePage.setText("页数跳转");
jumpChoosePage.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
jumpChoosePageActionPerformed(evt);
}
});
searchAgainBox.setText("");
page.setText("1");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(page, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jumpLastPage)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jumpNextPage)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jumpChoosePage)
.addGap(12, 12, 12))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(resultJpanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(searchAgainBox, javax.swing.GroupLayout.PREFERRED_SIZE, 584, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(searchAgainButton, javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 26, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(searchAgainBox, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(searchAgainButton, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE))
.addGap(27, 27, 27)
.addComponent(resultJpanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 33, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jumpLastPage)
.addComponent(jumpNextPage)
.addComponent(jumpChoosePage)
.addComponent(page, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
pack();
}// </editor-fold>
private void searchAgainButtonPerformed(java.awt.event.ActionEvent evt) {
String queryString=searchAgainBox.getText();
List<SearchResultEntry> list=esGuiSearch.fullTextSerch(queryString);
if(list.isEmpty()) {
JOptionPane.showMessageDialog(null, "未搜索到相关内容!");
}else {
resultList = getJpanelList(list);
resultNum = list.size();
pageNum = (resultList.size()+1)/2;
currentPage = 1;
displayResult();
}
}
private void jumpLastPageActionPerformed(java.awt.event.ActionEvent evt) {
if(currentPage == 1){
JOptionPane.showMessageDialog(null, "当前已为第一页,无法进入上一页!");
}else{
currentPage--;
displayResult();
}
}
private void jumpNextPageActionPerformed(java.awt.event.ActionEvent evt) {
if(currentPage == pageNum){
JOptionPane.showMessageDialog(null, "当前已为最后一页,无法进入下一页!");
}else{
currentPage++;
displayResult();
}
}
private void jumpChoosePageActionPerformed(java.awt.event.ActionEvent evt) {
int jumpPage = Integer.valueOf(page.getText());
if(jumpPage >= 1 && jumpPage <= pageNum){
currentPage = jumpPage;
displayResult();
}else{
JOptionPane.showMessageDialog(null, "输入页数不合法,请输入1-"+pageNum+"中的数字");
}
}
private List<JPanel> getJpanelList(List<SearchResultEntry> list) {
List<JPanel> resultList = new ArrayList<>();
for(SearchResultEntry e:list){
JPanel jPanel=new SearchLook(e);
resultList.add(jPanel);
}
return resultList;
}
private List<JPanel> resultList;
private int pageNum;
private int currentPage;
private int resultNum;
private EsGuiSearch esGuiSearch;
private javax.swing.JButton jumpChoosePage;
private javax.swing.JButton jumpLastPage;
private javax.swing.JButton jumpNextPage;
private javax.swing.JTextField page;
private javax.swing.JPanel resultJpanel;
private javax.swing.JTextField searchAgainBox;
private javax.swing.JButton searchAgainButton;
// End of variables declaration
}
4.SearchLook.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package edu.net.itsearch.gui;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URI;
import crawler.SearchResultEntry;
/**
*
* @author 格格
*/
public class SearchLook extends javax.swing.JPanel {
/**
* Creates new form SearchLook
*/
public SearchLook() {
initComponents();
}
public SearchLook(SearchResultEntry result) {
initComponents();
titleJlabel.setText(result.getTitle());
textArea.setText(result.getText());
url = result.getUrl();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
/** <editor-fold defaultstate="collapsed" desc="Generated Code"> */
private void initComponents() {
titleJlabel = new javax.swing.JLabel();
jumpJbutton = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
textArea = new javax.swing.JTextArea();
titleJlabel.setText("jLabel1");
jumpJbutton.setText("跳转");
jumpJbutton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(Desktop.isDesktopSupported()){
try {
URI uri=URI.create(url);
Desktop dp=Desktop.getDesktop();
if(dp.isSupported(Desktop.Action.BROWSE)){
dp.browse(uri);
}
} catch (Exception o) {
o.printStackTrace();
}
}
}
});
textArea.setColumns(20);
textArea.setRows(5);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
jScrollPane1.setViewportView(textArea);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap(36, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(titleJlabel, javax.swing.GroupLayout.PREFERRED_SIZE, 522, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(30, 30, 30)
.addComponent(jumpJbutton)
.addContainerGap())
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 633, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(31, 31, 31))))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(titleJlabel, javax.swing.GroupLayout.PREFERRED_SIZE, 29, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jumpJbutton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
.addContainerGap())
);
}// </editor-fold>
private String url;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JButton jumpJbutton;
private javax.swing.JTextArea textArea;
private javax.swing.JLabel titleJlabel;
// End of variables declaration
}
关键代码
4.运行结果截图
1.
2.
3.
4.
5.
5.遇到的问题
1)在SearchLook.java类中,用来放文本和标题的容器不知道用JLabel还是Jframe,最终经过百度查询资料,选择的JLabel,原因如下:JFrame是一个顶层的框架类,好比一个窗户的框子。也是一个容器类,这个框子可以嵌入几个玻璃窗,就是说Jframe可以将标签文本和按钮安放并处理,而且能实现最小化/最大化、改变大小、移动等功能特性。而JPanel是一个容器类,相当于一大玻璃窗,可以放置文本框按钮等非容器组件。在结果展示中,我只需要一个JLabel和一个文本区域和一个按钮,所以我选择JPanel。
2)第一次从net beans转到eclipse上编写时发现错误,后来经过检查发现是因为照片文件的问题,获取照片文件的相对路径为当前包,第一开始我单独放在别的包里,移到gui包后就可以正常运行了。
6.git提交记录
7.我的感想
我本身的代码基础不是很扎实,所以课设中很多部分都无法完成,只能实现Gui界面的设计与部分代码的编写。通过这次Java课设,从队友的指导,百度的搜索还有书本上的知识等等地方学到了好多关于Gui的知识,从容器插件还有监听器等等。虽然功能简单,但是我也遇到了不少的问题,比如说第一次写监听器是无法运行,原因就是我调用的类不对。还有就是跳转到网页时遇到了很多困难,研究了很久才解决。我设计的Gui界面有一些不足,但是我还是从中学到了很多,这次课设我受益匪浅。