结对编程-WordCount(Java)

说明

合作者

201631062221,201631062514

项目码云链接

https://gitee.com/kong1987/wc

作业链接

https://edu.cnblogs.com/campus/xnsy/2018Systemanalysisanddesign/homework/2188
https://edu.cnblogs.com/campus/xnsy/2018Systemanalysisanddesign/homework/2120

正文

结对编程PSP表格

PSP2.1 PSP阶段 预估耗时 实际耗时
(分钟) (分钟)
Planning 计划  60  40
· Estimate · 估计这个任务需要多少时间  60  40
Development 开发 480  720
· Analysis · 需求分析 (包括学习新技术) 60 250
· Design Spec · 生成设计文档 30 60
· Design Review · 设计复审 (和同事审核设计文档)  30 30
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 20 20
· Design · 具体设计 30  10
· Coding · 具体编码  360  600
· Code Review · 代码复审  30 30
· Test · 测试(自我测试,修改代码,提交修改)  120 240
Reporting 报告 30  60
· Test Report · 测试报告  30  10
· Size Measurement · 计算工作量  10  10
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划  60  60
合计 1410 2170

代码复审情况

代码复审中发现一些问题,他的代码在实现基础功能的时候没有考虑到新需求的加入,将所有的逻辑都放在了主类中来处理,造成各种flag一起存在,逻辑比较混乱,如果要添加新的需求,则需要对整个逻辑过程进行修改,要看懂他写的代码已经是很难受的了,如果还要对之进行修改,那是一个更加痛苦的过程。不仅 如此,在最初的结构中,他的一个类会去负责好几个功能,不符合单一职责原则。不过在后来的扩展的时候,我们对之前的代码进行了较大的改造,从结构上来看,有了一定的条理性!

设计过程

这次项目结对部分比较少,结对的大部分时间都花在了基础功能的代码复审上,拓展功能和高级功能才是比较花时间的地方,我和小组另一名成员分工合作,我负责高级功能界面的编写和给他后台的参数传递,设计过程我主要关注自己的界面设计,少部分关注点在与另一名小组成员的后台处理数据的交互。
对于高级功能的设计主要采用Java Swing设计,设计一个主面板,上面放置各个控件,几个checkbox用于用户多选勾选命令,几个button,对应的点击事件使用filechooser控件寻找文件或文件夹,有一个textfile文本框用于用户输入批量处理的文件类型,最后一个提交按钮,传递一个命令集合到后台小组成员的类中,实现界面和后台的交互。

代码

TableTest类

这个类是界面类,主要生成各种控件和控件点击事件以及文件过滤器的编写

import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseWheelEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import javax.print.attribute.standard.RequestingUserName;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.filechooser.FileFilter;

import org.omg.CORBA.PUBLIC_MEMBER;

public class TableTest {
	public static void main(String[] args) {
       
         /*主界面*/    
	JFrame frame=new JFrame("WordCount");//软件左上角名称,新建一个界面
	frame.setSize(400, 300);//500为长,300为宽
       frame.setLocation(400, 300);//为出现在屏幕上位置
       frame.setLayout(null);
       
       /*面板一*/
       JPanel j1=new JPanel();//新建一个面板
       j1.setBounds(50, 50, 300, 60);//一二参数:位置,三四参数:填充大小
       j1.setBackground(Color.white); // 设置面板背景颜色 
//     j1.setLayout(null);// 这一句可以没有,因为JPanel默认就是采用的FlowLayout
       j1.setLayout(new FlowLayout());
       
       /*组件:复选框*/
       JLabel jfunctionView=new JLabel("     程序功能");
       JCheckBox jcb1=new JCheckBox("行数统计");
       JCheckBox jcb2=new JCheckBox("字符统计");
       JCheckBox jcb3=new JCheckBox("单词统计");
       JCheckBox jcb4=new JCheckBox("代码行/注释行/空行");
       JCheckBox jcb5=new JCheckBox("批量操作");
       jcb1.setSelected(false);
       jcb2.setSelected(false);
       jcb3.setSelected(false);
       jcb4.setSelected(false);
       jcb5.setSelected(false);
       j1.add(jfunctionView);
       j1.add(jcb1);
       j1.add(jcb2);
       j1.add(jcb3);
       j1.add(jcb4);
       j1.add(jcb5);
       
       /**
        * 面板二***********************************************
        * 
        * */
       JPanel j2=new JPanel();
       j2.setBounds(10, 150, 300, 60);
       j2.setBackground(Color.lightGray);
       
       /*组件:文件选择器*/
       final JFileChooser fc=new JFileChooser();//文件选择器,用于基础功能实现
       final JFileChooser pc=new JFileChooser();//目录选择器,用于批量操作实现
       final JFileChooser sc=new JFileChooser();//文件选择器,用于保存文件实现
       pc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);//设置只能选择目录
       /*文件类型过滤器*/
       fc.setFileFilter(new FileFilter() {
		
    	   /*要求只接受.java文件*/
		@Override
		public String getDescription() {
			return ".java";
		}
		
		@Override
		public boolean accept(File f) {
			return f.getName().toLowerCase().endsWith(".java");
		}
	});
       
       JButton bOpen=new JButton("选择源码文件");
       JButton bSave=new JButton("选择输出文件");
       JButton bStop=new JButton("选择停止词文件");
       JTextField jFileType=new JTextField("");
       jFileType.addFocusListener(new JTextFieldHintListener(jFileType,"请输入文件类型,如\"*.java\""));
       jFileType.setPreferredSize(new Dimension(150, 30));
      
       JButton bPath=new JButton("选择文件目录");
       JButton jsbumit=new JButton("提交");
       jsbumit.setPreferredSize(new Dimension(120, 30));
       
       // 把按钮加入面板
       j2.add(bOpen);
       j2.add(bSave);
       j2.add(bStop);
       j2.add(jFileType);
       j2.add(bPath);
       j2.add(jsbumit);
       
       CommandSet tempcs=new CommandSet();
       
       /*为打开文件按钮添加点击事件*/
       bOpen.addActionListener(new ActionListener() {
    	public String filePath;
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			int retVal=fc.showOpenDialog(frame);
			File file=fc.getSelectedFile();
			if(retVal==JFileChooser.APPROVE_OPTION){
				JOptionPane.showMessageDialog(frame, "你选择了文件:"+file.getAbsolutePath());
				filePath=file.getAbsolutePath();
				tempcs.setSourceFile(filePath);
			}
		}
	});
       
       /*为打开文件目录按钮添加点击事件*/
       bPath.addActionListener(new ActionListener() {
    	public String filePath;
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			int retVal=pc.showOpenDialog(frame);
			File file=pc.getSelectedFile();
			if(retVal==JFileChooser.APPROVE_OPTION)
			{
				JOptionPane.showMessageDialog(frame, "你选择了文件夹:"+file.getAbsolutePath());
				filePath=file.getAbsolutePath();
				tempcs.setFilePath(filePath);
			}
		}
	});

       bSave.addActionListener(new ActionListener() {
		
		@Override
		public void actionPerformed(ActionEvent arg0) {
			// TODO Auto-generated method stub
			int option=sc.showSaveDialog(null);
			if(option==JFileChooser.APPROVE_OPTION)
			{
				File file=sc.getSelectedFile();
				FileOutputStream fos;
				JOptionPane.showMessageDialog(frame, "保存文件路径为:"+file.getAbsolutePath());
				tempcs.setOutFile(file.getAbsolutePath());
				tempcs.setComO("-o");
				try {
					fos = new FileOutputStream(file);
					fos.close();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	});
       /*为选择停止词文件添加点击事件*/
       bStop.addActionListener(new ActionListener() {
    	   public String filePath;
   		@Override
   		public void actionPerformed(ActionEvent e) {
   			// TODO Auto-generated method stub
   			int retVal=fc.showOpenDialog(frame);
   			File file=fc.getSelectedFile();
   			if(retVal==JFileChooser.APPROVE_OPTION)
   			{
   				tempcs.setComE("-e");
   				JOptionPane.showMessageDialog(frame, "停止文件为:"+file.getAbsolutePath());
   				filePath=file.getAbsolutePath();
   				tempcs.setStopFile(filePath);
   			}
   		}
   	});
       
       /*为提交按钮添加点击事件*/
       jsbumit.addActionListener(new ActionListener() {
    	CommandSet cSet=new CommandSet();
		@Override
		public void actionPerformed(ActionEvent e) {
                        /*判断checkbox是否选中*/
			if(jcb1.isSelected()){
				cSet.setComLine("-l");
			}
			if(jcb2.isSelected()){
				cSet.setComChar("-c");
			}
			if(jcb3.isSelected()){
				cSet.setComWord("-w");
			}
			if(jcb4.isSelected()){
				cSet.setComAdva("-a");
			}
			if(jcb5.isSelected()){
				cSet.setComBatch("-s");
				//bPath.setEnabled(true);
			}
			
			/*获得输入框文件类型*/
			String fileType=jFileType.getText();
			
			if(fileType.startsWith("*")){
				cSet.setFileType(fileType);
			}
			else{
		        	JOptionPane.showMessageDialog(frame, "对不起,你输入的不是一个合法的文件类型,请以\"*\"开始");
			}
			cSet.setSourceFile(tempcs.getSourceFile());
			cSet.setOutFile(tempcs.getOutFile());
			cSet.setFilePath(tempcs.getFilePath());
			cSet.setStopFile(tempcs.getStopFile());
			cSet.setComE(tempcs.getComE());
			cSet.setComO(tempcs.getComO());
			for(String s:cSet.getCommand())
			{
				System.out.println(s);
			}
			JOptionPane.showMessageDialog(frame, "恭喜你,操作成功");
                        //这里还有小组成员的调用代码,未整合到我的代码上,将在小组成员的链接中给出
		}
	});
   
       /*设置双界面格式*/
       JSplitPane sp=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,j1,j2);
       sp.setDividerLocation(150);
       frame.setContentPane(sp);
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.setVisible(true);//设置可见度显示
	}
}

JTextFiledHintListener类

该类为输入焦点框提供逻辑,实现默认提示信息的显示和用户点击输入框时自动清除默认内容

/*为输入框焦点事件添加逻辑*/
class JTextFieldHintListener implements FocusListener {
	private String hintText;
	private JTextField textField;
	public JTextFieldHintListener(JTextField jTextField,String hintText) {
		this.textField = jTextField;
		this.hintText = hintText;
		jTextField.setText(hintText);  //默认直接显示
		jTextField.setForeground(Color.GRAY);
	}
	@Override
	public void focusGained(FocusEvent e) {
		//获取焦点时,清空提示内容
		String temp = textField.getText();
		if(temp.equals(hintText)) {
			textField.setText("");
			textField.setForeground(Color.BLACK);
		}
	}
	@Override
	public void focusLost(FocusEvent e) {	
		//失去焦点时,没有输入内容,显示提示内容
		String temp = textField.getText();
		if(temp.equals("")) {
			textField.setForeground(Color.GRAY);
			textField.setText(hintText);
		}
	}
}

CommandSet类

该类集合了小组成员后台需要的命令,通过面向对象的思想抽象出来,在节目中读取到用户命令成功后传递给后台小组成员类中

import java.util.ArrayList;
import java.util.List;
public class CommandSet {
	private String comLine;//行数命令 -l
	private String comChar;//字符数命令 -c
	private String comWord;//单词数命令 -w
	private String comAdva;//扩展功能,空行/注释行/代码行 -a
 	private String comBatch;//批量操作命令 -s
 	private String comO;//输出文件命令-o
 	private String comE;//停用词命令-e
	private String sourceFile;//源文件目录
	private String filePath;//选择批量操作文件主目录
	private String outFile;//输出文件目录
	private String stopFile;//停止文件目录 
	private String fileType;//文件类型 *.java   *.c    *.txt
	
        private List<String> commandSet=new ArrayList<String>();
	private void setCommand() {
		commandSet.add(comLine);
		commandSet.add(comChar);
		commandSet.add(comWord);
		commandSet.add(comAdva);
		commandSet.add(comBatch);
		commandSet.add(filePath);//写入时固定将目录路径写在-s后面
		commandSet.add(fileType);
		commandSet.add(sourceFile);
		
		commandSet.add(comE);
		commandSet.add(stopFile);
		commandSet.add(comO);
		commandSet.add(outFile);
	}
	public String[] getCommand()
	{
		setCommand();
		return (String[])commandSet.toArray(new String[0]);
		
	}
	public String getComO() {
		return comO;
	}
	public void setComO(String comO) {
		this.comO = comO;
	}
	public String getComE() {
		return comE;
	}
	public void setComE(String comE) {
		this.comE = comE;
	}
	public String getComLine() {
		return comLine;
	}
	public void setComLine(String comLine) {
		this.comLine = comLine;
	}
	public String getComChar() {
		return comChar;
	}
	public void setComChar(String comChar) {
		this.comChar = comChar;
	}
	public String getComWord() {
		return comWord;
	}
	public void setComWord(String comWord) {
		this.comWord = comWord;
	}
	public String getComAdva() {
		return comAdva;
	}
	public void setComAdva(String comAdva) {
		this.comAdva = comAdva;
	}
	public String getComBatch() {
		return comBatch;
	}
	public void setComBatch(String comBatch) {
		this.comBatch = comBatch;
	}
	public String getSourceFile() {
		return sourceFile;
	}
	public void setSourceFile(String sourceFile) {
		this.sourceFile = sourceFile;
	}
	public String getFilePath() {
		return filePath;
	}
	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}
	public String getOutFile() {
		return outFile;
	}
	public void setOutFile(String outFile) {
		this.outFile = outFile;
	}
	public String getStopFile() {
		return stopFile;
	}
	public void setStopFile(String stopFile) {
		this.stopFile = stopFile;
	}
	public String getFileType() {
		return fileType;
	}
	public void setFileType(String fileType) {
		this.fileType = fileType;
	}
}

成果

界面展示

主界面

文件选择器

提示框

完整运行结果
https://www.cnblogs.com/kong1987/p/pairing.html

总结

这次结对编程让我意识到有些时候还是1+1>2的,就是把很多复杂的工作分离成小工作,分工合作完成的时候,效率很快,但是在完整的开发过程中有时候是1+1<2的,那就是沟通不流畅的时候,这里的沟通指的是有时候不能坐在一起沟通,只能通过沟通工具沟通的时候,能够很明显感觉到需求说不出,或者是说出了对方理解不了的情况,这也是这个项目拖延得比较久的原因,今天大部分功能完成的时候,大家坐到一起时马上就解决了之前几天遗留的问题,项目运行也完成了,还有一些逻辑的优化、界面的友好度和一些小bug可以优化,但是不影响功能的完整运行。
个人开发时遇到的问题大部分都通过查找CSDN,博客园得到了解决,也在边查找边开发的过程中学习到了Java Swing的一些用法,可惜在我界面开发完成后才发现了JavaFX这种技术,界面更美观,也更体现了面向对象的抽象封装特性,代码简洁,没有swing那么冗杂,swing简单的一个界面就有几百行代码,我看到其他同学们也有使用FX技术的,值得学习学习。

致谢

淡漠一生,何欲何求 的博客 https://www.cnblogs.com/mrdz/p/7716643.html
yongchaocsdn的博客 https://blog.csdn.net/yongchaocsdn/article/details/53355296
u010181717的博客 https://blog.csdn.net/u010181717/article/details/13000759
yanjingtp的博客 https://blog.csdn.net/yanjingtp/article/details/79282365
百度知道 https://zhidao.baidu.com/question/545174029.html
树叶子hza的博客 https://blog.csdn.net/hza419763578/article/details/80669128

以上博主的博客对我学习和使用javaSwing的帮助很大,在此衷心的感谢。

posted @ 2018-10-16 22:35  BirdofSorrow  阅读(164)  评论(0编辑  收藏  举报