软工III经验总结

前篇:本文和Random的由来

话说软工III做完已经有这么多天了,自己浑浑噩噩的想着要写点什么东西来纪念下自己Random小组的成果,虽然只有一点点小小的心得,不过还是想记录下在大学时自己第一次当组长带队的感觉。

先从这个小组的组成开始说起,我,zfx,tz,sjl,dp共5个人,可以说是别的组挑剩下的,话说我当初是真心想随机的,可是后面考虑到某些因素,所以还是在老师发布的没有组队的那些人中挑选了4个比较有可能会做事的人,鉴于自己不能Random,所以队伍取名叫做Random。

Random的组员我一开始比较熟悉的是t(tz)和z(zfx),他们两个是我比较早认识的两个人,Random组第一次开会是在图书馆的研讨室3204,第一次讨论的是大家的长处,t懂得代码架构,z和d(dp)精通文档编写,s(sjl)会数据库管理,所以其实第一次开会完成之后,我心里大概就有了一个底子,谁该干什么,谁会干什么我大都已经清楚了,不过我还是在幻想,幻想着每个人能在自己不熟悉的领域上面能够发挥下自己的作用,尽量在项目实践期间能够参与到每个环节中来。后来我发现,我错了……

正文一:作为组长的心得感悟

其实组长真的不是那么好当的,自以为看了本《人月神话》就能很好规划团队的我,最后只剩下傻傻的笑。也许是理论付诸于实践方面的错误,是我的方法不对。

首先,我们听从老师的安排写下的那些条条框框显然不适用,到后来迟到的迟到,缺席的缺席。记得s的缺席原因告诉我说是因为自己洗澡没时间来开会。开会时定在每周二、四晚和周六下午,这可是定死的啊,就因为要洗澡就不来是什么样的荒唐逻辑!我只能呵呵了。

关于团队决策方面,我觉得我根本就没有起到什么作用,关于代码架构,只要t一句话,他就可以根据自己的思维随心所欲的改动代码,而我,只能每次都因为理由不足而被他驳回,实际上我是骨子里面有股惰性的人,我懒得和你去争论,因为我知道,你这样可以,知道你的代码架构的很好,但是我的方案有我的优点,我知道就行,因为你,只会一味的执着于自己的意见,丝毫不顾及他人对此代码架构的理解。这次的项目经历了两次架构上的大变革,有些真是使我手足无措,我只能说“文档很重要,架构需谨慎,改动尽量小”,像我们这种架构,两次大幅度的更改已经是我的最高忍耐限度了。

关于团队的分工。一开始是想大家既然在做一个项目,就应该体验一下真实的流程,大家应该尽可能的参与到项目开发中来,所以一开始还是鼓励大家做多点自己不太擅长的事情,后来发现,也许是因为人的惰性,大家还是倾向于做自己擅长的方面。这点以后的项目实践中我会很重视的。还有就是在计划之下的任务分工,这次项目基本上是deadline驱动,所以计划驱动在Random看来只不过是浮云,这点是我不满意的地方,因为在计划日来临时给组员的动力远远比不上deadline。我很是懊恼这个问题。

关于项目的进度,这点也是我的另一个决策大失误,每一次都是deadline来临了,大家才有动力去做事情,没有一个人是真正投身到项目中来的,或许是不太抱希望到这个项目里面,或许因为我们是半Random的缘故,他们没有激情。给他们能在两天之内做好的事情,两个礼拜还没做好,最后交给我的还是完成度70%的半成品,我真的绝望了。似乎认识到靠别人不如靠自己。这个团队整体上都没有积极性,都太过依赖于我,以为我会把所有的事情做完,因为Random是我组织的。所以我在5月30日检查的时候给了他们一个警示,告诉他们我们项目离做完还差得远呢,希望能够提起他们的积极性。当时助教检查的时候我就给他看了login界面和数据库,其他的都以没做为由告诉助教,这时候的团队危机感似乎就有了,我以为这下子团队应该能够接手下一步的任务了,所以当他们问我是否想要将任务分解出来的时候,我只是委婉地说了一句:“不用,我做得完。”然后可能就是因为这句话,团队到了懒散到崩溃的状态。于是我找了个时间——端午3天,把项目的客户端代码写完了,服务器也完善好了,单元测试和集成测试也粗略的过了一遍。当我告知他们我写完这些的时候,团队崩溃的一发不可收拾了。z,他后期帮我完善了界面的美化和测试;d,最后一晚进行了测试。其他人,没有任何测试的欲望,仿佛没了他们什么事情。总之项目进度该如何调整才能使的队员们有紧张感愿意去做事情,我还是有点经验不足,希望在下次的项目中能有体会吧。

关于团队交流和规则的实施,这点我真是不知道要怎么讲才好,也许是我太心软了,开会时候迟到,缺席,开会时候玩游戏,听音乐,心不在焉,大家的一系列行为我都不好意思开口去说,以为他们知道错误会去改,我又错了。所以我还是要坚信,规则是铁一般的原则,任何一个人违反都应该毫不犹豫的告知并且制止。

关于团队组员的闪光点,t对代码架构有着自己独到的见解,UML图使用的非常的顺,RMI大数据传输算法的改进方面都做得很好。s的数据库管理技术比我好多了,界面雏形结构也做的比较好。d的文档编写能力实在是很强。z的代码编写,图片处理技术,界面美化以及代码规范化方面做的也是很好的。

正文二,JAVA使用中的一点小技术

这次我们写的是一个旅行者系统,主要还是有一些功能点要实现的,下面简要介绍下,我在这个项目里面设计时想到的几个亮点。

1. (伪)新手指引

所谓伪新手指引,其实是这么设计的,将一个jDialog的背景设为透明,然后在全屏幕上贴一张全屏大小的图片,客户端的界面正好和全屏幕上图片界面重合,达到是是而非的效果。具体代码:有人工和自动播放两种模式。

package helper;

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;

public class NewComerHelper extends JDialog{
	public static final int WIDTH=(int)Toolkit.getDefaultToolkit().getScreenSize().getWidth() ;
	public static final int HEIGHT=(int)Toolkit.getDefaultToolkit().getScreenSize().getHeight() ;
	public static final int BUTTONWIDTH=80;		//定义确认和取消键宽
	public static final int BUTTONHEIGHT=25;	//定义确认和取消键高
	public static final int SIZE=40;	//拥有的新手指南图片张数
	JLabel picturelabel;
	JButton okButton,button;
	int index=0;
	JFrame parents;
	public NewComerHelper(final JFrame parents,int type){
		this.parents=parents;
		parents.setEnabled(false);
		if(type==0){
			
			helpByUser();
		}else {
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					helpByRobot();
					
				}
			}).start();
		}
	}
	public void helpByUser(){
		final JDialog dialog = new JDialog();    //以下3行目的是设置jDialog背景透明。
		dialog.setUndecorated(true);
		dialog.setBackground(new Color(255,255,255,1));
		dialog.getContentPane().setLayout(null);
		picturelabel = new JLabel(new ImageIcon("./helperPicture/0.png"));
		index=0;
		picturelabel.setBounds(0, 0, WIDTH, HEIGHT);
		picturelabel.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent event){
				if(index<=SIZE){
				index++;
				picturelabel.setIcon(new ImageIcon("./helperPicture/"+index+".png"));
				if(index==SIZE){
					okButton.setVisible(false);
					button.setText("close");
				}
				}
			}
		});

		
		okButton = new JButton("next");
		okButton.setBounds(WIDTH-250, HEIGHT-100, BUTTONWIDTH, BUTTONHEIGHT);
		okButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(index<=SIZE){
				index++;
				picturelabel.setIcon(new ImageIcon("./helperPicture/"+index+".png"));
				if(index==SIZE){
					okButton.setVisible(false);
					button.setText("close");
				}
				
				}
			}
		});
		dialog.getContentPane().add(okButton);
		
		button = new JButton("cancel");
		button.setBounds(WIDTH-150, HEIGHT-100, BUTTONWIDTH, BUTTONHEIGHT);
		button.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {		
				parents.setEnabled(true);
				dialog.dispose();
				
			}
		});
		dialog.getContentPane().add(button);
		dialog.getContentPane().add(picturelabel);
		dialog.setSize(WIDTH,HEIGHT);
		dialog.setVisible(true);
	}
	
	
	public void helpByRobot(){
		final JDialog dialog = new JDialog();
		dialog.setUndecorated(true);
		dialog.setBackground(new Color(255,255,255,1));
		dialog.getContentPane().setLayout(null);
		picturelabel = new JLabel(new ImageIcon("./helperPicture/0.png"));
		index=0;
		picturelabel.setBounds(0, 0, WIDTH, HEIGHT);
		button = new JButton("cancel");
		button.setBounds(WIDTH-150, HEIGHT-100, BUTTONWIDTH, BUTTONHEIGHT);
		button.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {		
				parents.setEnabled(true);
				dialog.dispose();
			}
		});
		dialog.getContentPane().add(button);
		dialog.getContentPane().add(picturelabel);
		dialog.setSize(WIDTH,HEIGHT);
		dialog.setVisible(true);
		picturelabel.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent event){
				if(index<=SIZE){				
				index++;
				picturelabel.setIcon(new ImageIcon("./helperPicture/"+index+".png"));
				if(index==SIZE){
					button.setText("close");
				}
				}else {
					JOptionPane.showMessageDialog(null, "您已经学习完了,退出吧,亲!");
				}
			}
		});		
		display();
		
	}
	
	public void display(){
		for(index=0;index<=SIZE;index++){
			picturelabel.setIcon(new ImageIcon("./helperPicture/"+index+".png"));
			try {
				Thread.sleep(2013);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
//		new NewComerHelper(1);
	}

}

2. 验证码的BufferImage实现序列化

刚开始让我头疼的验证码是用label上面的数字实现的,后来组员反应太低级,所以在服务器序列化BufferedImage可以实现图片在客户端和服务器之间的传输,简单许多。原理,服务器随机生成数字,然后生成一张图片,再然后传到客户端识别。序列化代码如下:(源代码来源于网络)

package po;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SerializedImage implements Serializable {
  /**
   * A BufferedImage to serialized.
   * @serial bimage A BufferedImage to serialized.
   */
  private BufferedImage bimage;

  /**
   * Create a SerializedImage with a BufferedImage (<I>Can be use with RMI</I>).
   * @param bufferedImage Initial BufferedImage.
   */
  public SerializedImage(BufferedImage bufferedImage) {
    bimage=bufferedImage;
  }

  /**
   * Create a SerializedImage (<I>Can be use with RMI</I>).
   * @param image Initial Image.
   * @param width Width of this image.
   * @param Height height of this image.
   */
  public SerializedImage(Image image,int width,int height) {
    boolean errorFlag=false;

    PixelGrabber pg = new PixelGrabber(image,0,0,width,height,true);
    try {
      pg.grabPixels();
    } catch (InterruptedException e) {
      System.out.println("* Error while creating SerializedImage from Image");
      errorFlag=true;
    }
    bimage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
    if (!errorFlag) {
      bimage.setRGB(0,0,width,height,(int[])pg.getPixels(),0,width);
    }
  }

  /**
   * Get an BufferedImage of this SerializedImage.
   */
  public BufferedImage getBImage() {
    return bimage;
  }

  /**
   * Get the width of this SerializedImage.
   * @return Width in pixels.
   */
  public int getWidth() {
    return bimage.getWidth();
  }

  /**
   * Get the height of this SerializedImage.
   * @return Height in pixels.
   */
  public int getHeight() {
    return bimage.getHeight();
  }

  /**
   * Returns a string representation of the object.
   * Like this : SerializedImage[w=bimageWidth,h=bimageHeight].
   */
  public String toString() {
    return new String("SerializedImage[w=" + bimage.getWidth() + ",h=" + bimage.getHeight() + "]");
  }

  // Serialization of the BufferedImage 
  private void writeObject(ObjectOutputStream s) throws IOException {
    s.writeInt(bimage.getWidth());
    s.writeInt(bimage.getHeight());
    s.writeInt(bimage.getType());

    for(int i=0;i<bimage.getWidth();i++) {
      for(int j=0;j<bimage.getHeight();j++) {
 s.writeInt(bimage.getRGB(i,j));
      }
    }
    s.flush();
  }

  private void readObject(ObjectInputStream s) throws IOException,ClassNotFoundException  {
    bimage = new BufferedImage(s.readInt(),s.readInt(),s.readInt());
    for(int i=0;i<bimage.getWidth();i++) {
      for(int j=0;j<bimage.getHeight();j++) {
 bimage.setRGB(i,j,s.readInt());
      }
    }

  }

}

验证码的生成以及验证(有点小BUG,原因是static池里面只能存一个验证码,所以你懂得!)

	public SerializedImage getVCode() throws RemoteException {
		return new SerializedImage(getValidateCode());
	}
	 private static BufferedImage getValidateCode() {
	      int width = 80;
	      int height = 23;

	      BufferedImage image =
	         new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	      Graphics2D g = image.createGraphics();

	      g.setColor(new Color(
	            getRandom(200, 250),
	            getRandom(200, 250),
	            getRandom(200, 250)));
	      g.fillRect(0, 0, width, height);
	      int number = 4;
	      code="";
	      for(int i = 1; i <= number; i++) {
	         g.setColor(new Color(
	            getRandom(0,100),
	            getRandom(0,100),
	            getRandom(0,100)));
	         g.setFont(new Font(getFontName(), getStyle(), 16));
		      g.drawString(""+getChar(),
			            width * i / (number + 3), (int) (height / 1.5));
	      }
	      code=code.trim();
	      BasicStroke stroke = new BasicStroke(getRandom(1, 3),
	         BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
	      g.setStroke(stroke);
	      g.drawLine(getRandom(0, 10), height / getRandom(1, 10),
	         width, height / getRandom(1, 2));
	      g.drawLine(getRandom(0, 10), height / getRandom(3, 10),
	         width, height / getRandom(1, 3));
	      g.drawLine(getRandom(0, 10), height / getRandom(3, 10),
	 	         width, height / getRandom(1, 2));
	      return image;
	   }

	   private static char getChar() {
		   		char c;

				int random = (int) (Math.random() * 62);
				if (random < 10) {
					c= (char)(random + 48);
					code += random;
				} else if (random < 36) {
					random = random - 10 + 65;
					 c = (char) random;
					code += c;
				} else {
					random = random - 36 + 97;
					 c= (char) random;
					code += c;
				}
			
			return c;
	   }

	   private static String getFontName() {
	      String[] names =
	         {"楷体","SimSun", "Times New Roman", "Arial", "Courier New"};

	      return names[getRandom(0, names.length)];
	   }

	   private static int getStyle() {
	      int[] styles =
	         {Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD | Font.ITALIC};

	      return styles[getRandom(0, styles.length)];
	   }

	   private static int getRandom(int start, int end) {
	      int index = -1;

	      while(!(index >= start && index <= end)) {
	         index = (int) (Math.random() * end);
	      }

	      return index;
	   }

	@Override
	public boolean isVCodeAvaliable(String string) throws RemoteException {

		return code.toLowerCase().equals(string.toLowerCase());
	}

3.只能输入数字和限制长度的JTextField的实现
功能如标题,代码如下:

只能输入数字:

package UI;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public class NumOnlyDocument extends PlainDocument {
	public void insertString(int offset, String s, AttributeSet attrSet)
			throws BadLocationException {
		try {
			Integer.parseInt(s);
		} catch (NumberFormatException ex) {
			return;
		}
		
		 if (this.getLength() >= 24){
	    	 return;
	     }
	    
		super.insertString(offset, s, attrSet);
	}
}

限制长度:
package UI;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public  class ShortInputDocument extends PlainDocument{
	public static final int max_size=24;
	public void insertString(int offs,String str,AttributeSet a)throws BadLocationException{
		
	     if (this.getLength() >= max_size){
	    	 return;
	     }
	    
	    super.insertString(offs,str,a);
	    
	    
	     }
	   }

拓展:限制Ctrl+C(复制) 和 Ctrl+V(粘贴 的JTextArea 有效地防止老师的暴力测试,嘿嘿。

JTextArea textArea = new JTextArea(){
			@Override public void copy(){}
            @Override public void paste(){}
		};

4. (伪)傻瓜式拖拽的实现

所谓伪就是指仿照windows下的拖拽方式来实现在一个界面上面对“某种对象”的拖拽操作。其实就是通过一个隐藏的JDialog实现参数的传递。具体的代码如下:

设定指定拖拽区域:

		tipsLabel= new JLabel("拖至此处转载该计划");
		tipsLabel.setFont(new Font("楷体", Font.PLAIN, 26));
		tipsLabel.setForeground(Color.YELLOW);
		tipsLabel.setBounds(6, 375, 250, 50);
		tipsLabel.setVisible(true);
		tipsLabel.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseExited(MouseEvent arg0) {
				tipsLabel.setForeground(Color.YELLOW);
				
			}
			
			@Override
			public void mouseEntered(MouseEvent arg0) {
				tipsLabel.setForeground(Color.BLACK);
				
			}
		});
		panel.add(tipsLabel);

设定拖拽显示小框

	public OtherPlanSmallUI(String planName,String userName) {
		this.planName=planName;
		this.userName=userName;
		setBounds(100, 100, 155, 85);
		setUndecorated(true);
		setBackground(new Color(255,255,255,1));
		getContentPane().setLayout(new BorderLayout(0, 0));
		contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
		getContentPane().add(contentPanel);
		contentPanel.setLayout(null);
		
		JLabel label = new JLabel("计划:");
		label.setBounds(10, 10, 36, 15);
		contentPanel.add(label);
		
		JLabel label_1 = new JLabel("作者:");
		label_1.setBounds(10, 55, 36, 15);
		contentPanel.add(label_1);
		
		lblNewLabel = new JLabel("");
		lblNewLabel.setText(planName);
		lblNewLabel.setBounds(54, 10, 91, 15);
		contentPanel.add(lblNewLabel);
		
		lblNewLabel_1 = new JLabel("");
		lblNewLabel_1.setText(userName);
		lblNewLabel_1.setBounds(54, 55, 91, 15);
		contentPanel.add(lblNewLabel_1);
		
		setVisible(true);
	}
	
	public void setLabel(String planName,String userName){
		lblNewLabel.setText(planName);
		lblNewLabel_1.setText(userName);
		this.planName=planName;
		this.userName=userName;
	}

设定拖拽中小框显示:

public void mouseDragged(MouseEvent e) {
				String nameString = list.getModel().getElementAt(selectedIndex);
				String part[] = nameString.split(" BY ");
				String info[] = part[0].split(" ");
				String type = info[0];
				if(type.equals("[日志]")){
					JOptionPane.showMessageDialog(null, "日志不支持拖拽!");
					return;
				}else{
					myDialog.setBounds(e.getXOnScreen(), e.getYOnScreen(),155, 85);
					myDialog.setVisible(true);
					tipsLabel.setVisible(true);
				}
				
				
			}

设定按下和释放条件:release的时候必须进入指定区域

			public void mousePressed(MouseEvent e){
				
				selectedIndex=list.getSelectedIndex();
				String nameString = list.getModel().getElementAt(selectedIndex);
				String part[] = nameString.split(" BY ");
				String info[] = part[0].split(" ");
				String type = info[0];
				String name = info[1];
				String travellerName = part[1];
				if(type.equals("[计划]")){
				myDialog.setLabel(name, travellerName);
				myDialog.setBounds(e.getXOnScreen(), e.getYOnScreen(),155, 85);
				myDialog.setVisible(false);
				}
			}
			
			public void mouseReleased(MouseEvent e){
				
				int mouseX=e.getLocationOnScreen().x;
				int mouseY=e.getLocationOnScreen().y;
				int labelX=tipsLabel.getLocationOnScreen().x;
				int labelY=tipsLabel.getLocationOnScreen().y;
				int width = tipsLabel.getWidth();
				int height = tipsLabel.getHeight();
				myDialog.setVisible(false);
				if(mouseX>labelX&&mouseX<labelX+width&&mouseY>labelY&&mouseY<labelY+height){
					int selection = JOptionPane.showConfirmDialog(null,
							"你确定转载该计划?", null, 2);
					if (selection == JOptionPane.CANCEL_OPTION) {
						// Do NoThing
					} else if (selection == JOptionPane.YES_OPTION) {
						try {
							Plan plan =IServiceFactory.getPlanService().findMyPlan(myDialog.getUserName(),myDialog.getPlanName());
							String beforUserName = plan.getUserName();
							String beforePlanName = plan.getPlanName();
							if(beforePlanName.length()>=5&&beforePlanName.substring(0, 4).equals("[转载]")){
								JOptionPane.showMessageDialog(null, "请转载原作者文章,该篇计划已经被转载过");
								return;
							}
							if(beforUserName.equals(userName)){
								JOptionPane.showMessageDialog(null, "别闹!转载自己计划干嘛!");
								return;
							}
							plan.setUserName(userName);
							plan.setPlanName("[转载]" + plan.getPlanName());
							if (IServiceFactory.getPlanService().addPlan(plan)) {
								JOptionPane.showMessageDialog(null, "转载成功");
							} else {
								JOptionPane.showMessageDialog(null, "您已经转载该计划");
							}
							plan.setUserName(beforUserName);
							plan.setPlanName(beforePlanName);
						} catch (RemoteException e111) {
							JOptionPane.showMessageDialog(null, "网络连接错误!");
						}
					}
				}
				
				
			}

5. SubstanceLookAndFeel的使用

简单易懂,下个Substance.jar然后加上下面的代码:这是我的偏好。。。。。。

 try {
			 
			 JFrame.setDefaultLookAndFeelDecorated(true);
			 
             UIManager.setLookAndFeel(new SubstanceLookAndFeel());
             UIManager.put("swing.boldMetal", false);
             System.setProperty("sun.awt.noerasebackground", "true");
             //设置当前的主题风格,同样我 们还可以设置当前的按钮形状,水印风格等等 
             SubstanceLookAndFeel.setCurrentTheme(new SubstanceLightAquaTheme());
//           SubstanceLookAndFeel.setCurrentButtonShaper(new ClassicButtonShaper());
             SubstanceLookAndFeel.setCurrentWatermark(new SubstanceBinaryWatermark());
             SubstanceLookAndFeel.setCurrentBorderPainter(new StandardBorderPainter());  
             //设置渐变渲染  
             SubstanceLookAndFeel.setCurrentGradientPainter(new StandardGradientPainter());  
             //设置标题  
             SubstanceLookAndFeel.setCurrentTitlePainter(new FlatTitlePainter());  
             
     } catch (Exception e) {
             System.err.println("Oops!  Something went wrong!");
     }

6. 日期下拉框的实现:

简单的日期下拉框,可以方便的选择如期,不过关于Combox的使用还请参照我的另一篇博文。谢谢,代码如下:源代码来源于网络

package UI;

import java.awt.FlowLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Calendar;
import java.util.GregorianCalendar;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class DateCombox implements ItemListener {
	JComboBox comYear;
	JComboBox comMonth;
	JComboBox comDate;
	int count = 0;// 此属性用来存贮天数
	GregorianCalendar calend = new GregorianCalendar();// 用来获取系统的当前日期
	GregorianCalendar calend1;// 此日期对象用来表示用户所选择的日期

	/*
	 * 构造方法
	 */
	public DateCombox(JComboBox comYear, JComboBox comMonth, JComboBox comDate) {
		this.comYear = comYear;
		this.comMonth = comMonth;
		this.comDate = comDate;
	}

	public void load() {
		loadJcom();
		// 默认显示当前年份
		comYear.setSelectedItem(calend.get(Calendar.YEAR) + "");
		// 默认显示当前月份
		comMonth.setSelectedItem((calend.get(Calendar.MONTH) + 1) + "");
		loadComDate();
		comDate.setSelectedItem(calend.get(Calendar.DATE) + "");
		comYear.addItemListener(this);
		comMonth.addItemListener(this);
	}

	public void load(String year, String month, String day) {
		// 默认显示当前年份
		comYear.setSelectedItem(Integer.parseInt(year) + "");
		// 默认显示当前月份
		comMonth.setSelectedItem(Integer.parseInt(month) + "");

		comDate.setSelectedItem(Integer.parseInt(day) + "");
	}

	private void loadJcom() {
		// 年份从1970到2020年
		// comYear.removeAllItems();
		// comMonth.removeAllItems();
		for (int i = 1970; i <= 2020; i++) {
			comYear.addItem(i + "");// 加上双引号变成字符串
		}
		for (int i = 1; i <= 12; i++) {
			comMonth.addItem(i + "");
		}
	}

	private void loadComDate() {
		// 从comYear中或取用户选择的年份
		int year = Integer.parseInt((String) comYear.getSelectedItem());
		// 从comMonth中获取用户选择的月份
		int month = Integer.parseInt((String) comMonth.getSelectedItem());
		// 用用户选择的年份和月份重新实例化一个日期对象
		calend1 = new GregorianCalendar(year, month, 1);
		// 从一月到十二月每个月的天数
		int[] dateCount = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		// 根据用户选择的月份下拉列表的选择下标获取这个月所对应的天数
		count = dateCount[comMonth.getSelectedIndex()];
		// 判断是否闰年如果是闰年并且是二月的话则将存贮天数的变量count加1
		if (calend1.isLeapYear(year) && comMonth.getSelectedIndex() == 1) {
			count++;
		}
		for (int i = 1; i <= count; i++) {
			comDate.addItem(i + "");
		}
	}

	public static void main(String args[]) {
		JFrame f = new JFrame("测试");
		f.setLayout(new FlowLayout());
		JComboBox year = new JComboBox();
		JComboBox month = new JComboBox();
		JComboBox date = new JComboBox();
		DateCombox com = new DateCombox(year, month, date);
		com.load();
		f.add(new JLabel("开始时间"));
		f.add(year);
		f.add(month);
		f.add(date);
		f.setSize(450, 200);
		f.setVisible(true);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	@Override
	public void itemStateChanged(ItemEvent e) {
		// TODO 自动生成的方法存根
		comDate.removeAllItems();// 将comDate中的选项全部清空
		loadComDate();// 重新加载天数
	}
}

7. 最小化到托盘的实现

点击下就到托盘里面去了,boss什么的就看不到了,方便快捷,代码如下:源代码来源于网络

	 private  void miniTray() {  //窗口最小化到任务栏托盘

		  ImageIcon trayImg = new ImageIcon("./picture/myicon.png");//托盘图标
		  PopupMenu pop = new PopupMenu();  //增加托盘右击菜单
		  MenuItem show = new MenuItem("还原");
		  MenuItem exit = new MenuItem("退出");
		  final TrayIcon trayIcon = new TrayIcon(trayImg.getImage(), "Traveller系统",pop);
		  show.addActionListener(new ActionListener() {

		   public void actionPerformed(ActionEvent e) { // 按下还原键

		    tray.remove(trayIcon);
		    mainFrame.setVisible(true);
		    mainFrame.setExtendedState(JFrame.NORMAL);
		    mainFrame.toFront();
		   }

		  });

		  exit.addActionListener(new ActionListener() { // 按下退出键

		     public void actionPerformed(ActionEvent e) {

		    	 try {
					IServiceFactory.getLogInService().logout(userName);
				      tray.remove(trayIcon);
				      System.exit(0);
				} catch (RemoteException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}


		     }

		    });

		  pop.add(show);
		  pop.add(exit);

		  trayIcon.setImageAutoSize(true);

		  trayIcon.addMouseListener(new MouseAdapter() {

			   public void mouseClicked(MouseEvent e) { // 鼠标器双击事件

			    if (e.getClickCount() == 2) {

			     tray.remove(trayIcon); // 移去托盘图标
			     mainFrame.setVisible(true);
			     mainFrame.setExtendedState(JFrame.NORMAL); // 还原窗口
			     mainFrame.toFront();
			    }

			   }

			  });
		  try {

			   tray.add(trayIcon);

			  } catch (AWTException e1) {
			   // TODO Auto-generated catch block
			   e1.printStackTrace();
			  }
	 }
	 

完,回忆不起来了,转眼就过去一年了


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值