Java小项目点餐系统(一)之客户端

这段时间在学校开了Java课程之后动手写了一个小项目——点餐系统,我会分四篇博客去记录整个项目。

一:客户端

二:服务端

三:数据库端

四:项目心得和移植到linux环境下遇到的问题

源代码已上传:http://download.csdn.net/detail/u010214003/8138421

源码中包含客户端和服务端,数据库文件没有包含,在看完这几篇博客之后,可以自己动手去添加一些数据编译整个工程。

客户端详解:

一.界面分析

1.初始界面

用jfame的setUndecorated(true函数隐藏窗口标题栏,

然后就可以自定义自己的窗口,可以通过添加按钮和标签的方式实现最小化和关闭

调用函数;AWTUtilities.setWindowOpaque(this, false) 设置窗体透明

创建一个JLabel对象,用你想要的背景图片去填充,然后利用jframe的三层结构,把JLabel对象添加到分成窗格的最底层作伪背景图片,然后把

内容窗格设置为透明,即可实现上图效果,时钟是用Time单独开始一个线程画上去的

窗体背景代码:这里只是截取代码分析,具体实现参见源码

<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="white-space:pre">		</span>//获取屏幕大小
<span style="white-space:pre">		</span>Dimension screenSize =Toolkit.getDefaultToolkit().getScreenSize();
<span style="white-space:pre">	</span> <span style="white-space:pre">	</span>//设置窗体的位置和大小
	 <span style="white-space:pre">	</span>setBounds((screenSize.width-640)/2,(screenSize.height-480)/2,640,480);
		//不要标题栏的修饰
		setUndecorated(true);
		//设置窗体透明
		AWTUtilities.setWindowOpaque(this, false);
		
		background = init.backImage;// 背景图片
		bgLabel = new JLabel(background);// 把背景图片显示在一个标签里面
		// 把标签的大小位置设置为图片刚好填充整个面板
		bgLabel.setBounds(0, 0, background.getIconWidth(),
				background.getIconHeight());
		// 把内容窗格转化为JPanel,否则不能用方法setOpaque()来使内容窗格透明
		JPanel imagePanel = (JPanel)this.getContentPane();
		imagePanel.setOpaque(false);
		// 内容窗格默认的布局管理器为BorderLayout
		imagePanel.setLayout(new FlowLayout());
		
		getLayeredPane().setLayout(null);
		// 把imagePanel.add(new JButton("测试按钮"));
		//背景图片添加到分层窗格的最底层作为背景
		getLayeredPane().add(bgLabel, new Integer(Integer.MIN_VALUE));
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(background.getIconWidth(), background.getIconHeight());
		setResizable(false);</span>

最小化和关闭用按钮的话就去实现ActionListenr接口的actionPerformed函数

这里使用的是标签,要实现MouseListener接口的五个接口函数(有些用不到也要实现),代码如下

<pre name="code" class="java"><span style="font-family:KaiTi_GB2312;font-size:18px;">//添加监听
	minButton.addMouseListener(this);
	exitButton.addMouseListener(this);
//实现接口函数
<span style="white-space:pre">	</span>public void mouseClicked(MouseEvent e)
	{
		if(e.getSource() == minButton)
		{
		   setExtendedState(JFrame.ICONIFIED);
		}
		else if(e.getSource() == exitButton)
		{
				dispose();
		}
	}
	public void mousePressed(MouseEvent e)
	{
		
	}
	public void mouseReleased(MouseEvent e)
	{
		
	}
	public void mouseEntered(MouseEvent e)
	{
		
	}
	public void mouseExited(MouseEvent e)
	{
		
	}</span>

 


定时器线程代码:

<span style="font-family:KaiTi_GB2312;font-size:18px;">package mytool;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.util.Date;

import javax.swing.JLabel;
import javax.swing.Timer;



public class CreateClock extends JLabel implements ActionListener
{
	 public Timer timer;
	 double pointsx[]=new double[60];
	 double pointsy[]=new double[60];
	 double pointmx[]=new double[60];
	 double pointmy[]=new double[60];
	 double pointhx[]=new double[60];
	 double pointhy[]=new double[60];
	 public int second,hour,minute;
	 public Date date;
	 public Line2D secondline,hourline,minuteline;
	 public int a,b,c;
	 public CreateClock()
	 {
	  
		///初始化各个点的坐标
		pointsx[0]=pointmx[0]=pointhx[0]=0;
		pointsy[0]=-70;
		pointmy[0]=-55;
		pointhy[0]=-40;
		double angle=6* Math.PI/180;
		for(int i=0;i<59;i++)
		{
			pointsx[i+1]=pointsx[i]*Math.cos(angle)-pointsy[i]*Math.sin(angle);
			pointsy[i+1]=pointsy[i]*Math.cos(angle)+pointsx[i]*Math.sin(angle);
		   	pointmx[i+1]=pointmx[i]*Math.cos(angle)-pointmy[i]*Math.sin(angle);
		   	pointmy[i+1]=pointmy[i]*Math.cos(angle)+pointmx[i]*Math.sin(angle);
		   	pointhx[i+1]=pointhx[i]*Math.cos(angle)-pointhy[i]*Math.sin(angle);
		   	pointhy[i+1]=pointhy[i]*Math.cos(angle)+pointhx[i]*Math.sin(angle);
		}
	  for(int i=0;i<60;i++)
	  {
		   pointsx[i]=pointsx[i]+80;
		   pointsy[i]=pointsy[i]+100;
		   pointmx[i]=pointmx[i]+80;
		   pointmy[i]=pointmy[i]+100;
		   pointhx[i]=pointhx[i]+80;
		   pointhy[i]=pointhy[i]+100;
		  }
	  /初始化各条线
	  a=b=c=0;
	  secondline=new Line2D.Double(0,0,0,0);
	  minuteline=new Line2D.Double(0,0,0,0);
	  hourline=new Line2D.Double(0,0,0,0);

	  
	  //设置定时器
	  timer=new Timer(1000,this);
	  
	  timer.start();
	 }
	 public void paint(Graphics g)
	 {
		 ///画表盘
		 for(int i=0;i<60;i++)
		 {
			 int m=(int)pointsx[i];
			 int n=(int)pointsy[i];
			 if(i%5==0)
			 {
				 g.setColor(Color.blue);
				 g.fillOval(m-4, n-4, 8, 8);
			 }
		     else
		     {
		    	g.setColor(Color.green);
		    	g.fillOval(m-2,n-2,4,4);
		     }
	     }
		  g.fillOval(75,95,10,10);
		  ///画表针 
		  Graphics2D grap=(Graphics2D)g;
		  BasicStroke bb=new BasicStroke(2f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER);
		  grap.setStroke(bb);
		  grap.setColor(Color.green);
		  grap.draw(secondline);
		  BasicStroke bs=new BasicStroke(3f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER);
		  grap.setStroke(bs);
		  grap.setColor(Color.BLUE);
		  grap.draw(minuteline);
		  BasicStroke bss=new BasicStroke(6f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER);
		  grap.setStroke(bss);
		  grap.setColor(Color.YELLOW);
		  grap.draw(hourline);
	 }
	 public void actionPerformed(ActionEvent arg0)
	 {
		  // TODO Auto-generated method stub
		  if(arg0.getSource()==timer)
		  {
		   date=new Date();
		   String str=date.toString();
		   second=Integer.parseInt(str.substring(17,19));
		   minute=Integer.parseInt(str.substring(14,16));
		   hour=Integer.parseInt(str.substring(11,13));
		   int h=hour%12;
		   a=second;
		   b=minute;
		   c=h*5+minute/12;
		   secondline.setLine(80,100,pointsx[a],pointsy[a]);
		   minuteline.setLine(80,100,pointmx[b],pointmy[b]);
		   hourline.setLine(80,100,pointhx[c],pointhy[c]);
		   repaint();
		  }
	
	 }
}
</span>

2.主界面分析

这里在进入主界面的时候会进行登陆,服务端根据登陆的账号判断你是普通学生还是商家,在登陆后会根据返回信息确定进入哪个身份的界面

,这里只是简单介绍一下学生界面。


主界面使用一个JPanel对象mainPanel,对此mainPanel使用盒式布局,然后每一个功能区继承重写一个JPanel,添加到mainPanel,

当鼠标点击功能标签时,在监听标签的接口函数中调用card.show()函数进行JPanel的切换。

这里还对每个功能标签准备了两张图片,在点击相应的标签时,改变其背景图片与其他三张不一样就可以实现图上的效果。

监听函数中相应的代码如下:

<span style="font-family:KaiTi_GB2312;font-size:18px;">//添加监听
<span style="white-space:pre">		</span>每日推荐.addMouseListener(this);
		店铺一览.addMouseListener(this);
		我的菜单.addMouseListener(this);
		吐槽专区.addMouseListener(this);
		

	public void mouseClicked(MouseEvent e)
	{
		if(e.getSource() == 每日推荐)
		{
        <span style="white-space:pre">		</span> //改变标签的图片
			每日推荐.setIcon(init.suggestImage_enter);
			店铺一览.setIcon(init.shopImage);
			我的菜单.setIcon(init.myOrderImage);
			吐槽专区.setIcon(init.opinionImage);
<span style="white-space:pre">			</span>//切换面板
			card.show(mainPanel,"suggest");
		}
		else if (e.getSource() == 店铺一览)
		{
			每日推荐.setIcon(init.suggestImage);
			店铺一览.setIcon(init.shopImage_enter);
			我的菜单.setIcon(init.myOrderImage);
			吐槽专区.setIcon(init.opinionImage);
			card.show(mainPanel,"shop");
		}
		else if(e.getSource() == 我的菜单)
		{
			每日推荐.setIcon(init.suggestImage);
			店铺一览.setIcon(init.shopImage);
			我的菜单.setIcon(init.myOrderImage_enter);
			吐槽专区.setIcon(init.opinionImage);
			myOrderPanel.update();
			card.show(mainPanel,"myOrder");
		}
		else if(e.getSource() == 吐槽专区)
		{
			每日推荐.setIcon(init.suggestImage);
			店铺一览.setIcon(init.shopImage);
			我的菜单.setIcon(init.myOrderImage);
			吐槽专区.setIcon(init.opinionImage_enter);
			JOptionPane.showMessageDialog(mainWindow.getContentPane(),
				       "时间紧迫,此功能尚未开通,敬请期待!!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
		}
		<span style="white-space:pre">	</span>
	}
<span style="white-space:pre">	</span>public void mousePressed(MouseEvent e)
	{
		
	}
	public void mouseReleased(MouseEvent e)
	{
		
	}
	public void mouseEntered(MouseEvent e)
	{
		
	}
	public void mouseExited(MouseEvent e)
	{
		
	}</span>

二.Socket连接服务端

在登陆界面要求用户输入账号,密码,ip地址和端口号,客户端城尝试与服务端建立连接,验证用户并返回用户信息,

根据返回信息判断进入哪一个界面

<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="white-space:pre">			</span>String ip = loginPanel.ipTextField.getText(),
				   account = loginPanel.accountTextField.getText(),
				   passwd = new String(loginPanel.passwdTextField.getPassword());
			int  port = Integer.parseInt(loginPanel.portTextField.getText());	
			if(clientSocket.isConnected())
			{}
			else
			{
				try
				{
				InetAddress address = InetAddress.getByName(ip);
				InetSocketAddress socketAddress = new InetSocketAddress(address,port);
				clientSocket.connect(socketAddress);
				}
				catch (IOException e1)
				{
					JOptionPane.showMessageDialog(getContentPane(),
						       "网络连接异常", "系统信息", JOptionPane.ERROR_MESSAGE);
				}
				try
				{
				in = new DataInputStream(clientSocket.getInputStream());
				out = new DataOutputStream(clientSocket.getOutputStream());
				out.writeUTF("LOGIN");
				out.writeUTF(account);
				out.writeUTF(passwd);
				String reply = in.readUTF();
				if(reply.equals("student"))
				{
					studentPanel = new StudentPanel(init,in,out,this);
					mainPanel.add("student",studentPanel);
					card.show(mainPanel,"student");
				}
				else if(reply.equals("seller"))
				{
					sellerPanel = new SellerPanel(init,in,out);
					mainPanel.add("seller",sellerPanel);
					card.show(mainPanel,"seller");
				}
				else if(reply.equals("defeat"))
				{
					JOptionPane.showMessageDialog(getContentPane(),
						       "用户名或密码输入错误", "系统信息", JOptionPane.ERROR_MESSAGE);
				}
				}
				catch (IOException e1)
				{
				}
			}</span>

三.功能分析

功能简介:

该点餐系统在用户(学生)登陆后,会从服务器端获取当天的推荐菜单信息,店铺信息和店铺商品信息。用户可以从推荐界面和店铺里进行点餐,并在我的菜单里修改菜单,提交订单和付款。点餐系统在商家登陆后可以管理自己店铺的菜单,获取学生的订单并对订单进行处理,然后反馈信息给服务端,所有与数据库进行的信息交互都在服务端完成,功能比较简单。

1.推荐菜单

先从服务器端获取信息,然后显示用JTabel来显示,并在JTabel中添加JCheckBox来直接通过对JCheckBox的操作来选中和取消相应的菜单项。

代码:SuggetPanel.java

<span style="font-family:KaiTi_GB2312;font-size:18px;">package mypanel;

import init.Init;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.LinkedList;

import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;

import mytool.Food;
import mytool.SuggestTabelModel;
import mytool.SuggestTableCellRenderer;

public class SuggestPanel extends JPanel implements ActionListener{

	DataInputStream in = null;;
	DataOutputStream out = null;
	public int food_num;
	public LinkedList<Food> food;
	public LinkedList<Food> selectfood;
	final String[] headers = {"编号","菜名","店铺","类别","价格/元","推荐度",""};
	Object[][] cellData =  null;
	JTable table;
	SuggestTabelModel model;
	JScrollPane jscrollPane;
	private TableColumn column = null;
	private JButton enterButton;
		

	public SuggestPanel(Init init,DataInputStream in,DataOutputStream out)
	{
		int i=0;
		selectfood = new LinkedList<Food>();
		model = new SuggestTabelModel(cellData,headers);
		table =  new JTable(model);
		jscrollPane = new JScrollPane(table);
		jscrollPane.setPreferredSize(new Dimension(340, 270));
		enterButton = new JButton("加入菜单");
		enterButton.setPreferredSize(new Dimension(340,30));
		add(jscrollPane);
		add(enterButton);
		enterButton.addActionListener(this);
		//居中显示
		DefaultTableCellRenderer r=new DefaultTableCellRenderer();   
		r.setHorizontalAlignment(JLabel.CENTER);   
		table.setDefaultRenderer(Object.class,r);
		column = table.getColumnModel().getColumn(0);
		column.setPreferredWidth(120);
		column =table.getColumnModel().getColumn(1);
		column.setPreferredWidth(140);
		column =table.getColumnModel().getColumn(2);
		column.setPreferredWidth(170);
		column =table.getColumnModel().getColumn(6);
		column.setPreferredWidth(30);
		try
		{
			model.setRowCount(0);
			food_num = in.readInt();
			System.out.println(food_num);
			food = new LinkedList<>();
			for(i=0;i<food_num;i++)
			{
				Food tempfood=new Food();
				tempfood.num = in.readInt();
				tempfood.name = in.readUTF();
				tempfood.shop = in.readUTF();
				tempfood.type = in.readUTF();
				tempfood.price = in.readFloat();
				tempfood.satisfication = in.readUTF();
				food.add(tempfood);
			}
		}
		catch(IOException e)
		{
			
		}
			for(i=0;i<food.size();i++)
			{
				model.addRow(new Object[]{food.get(i).num,food.get(i).name,food.get(i).shop,food.get(i).type
						,food.get(i).price,food.get(i).satisfication,new Boolean(false)});
			}
			table.getColumnModel().getColumn(6).setCellEditor
			(new DefaultCellEditor(new JCheckBox()));    
			table.getColumnModel().getColumn(6).setCellRenderer
			(new SuggestTableCellRenderer());    
		
		table.invalidate();
	}
	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource() == enterButton)
		{
			for(int i=0;i<food_num;i++)
			if(Boolean.parseBoolean(table.getValueAt(i, 6).toString()) == true)
			{
				System.out.println(table.getValueAt(i,1).toString());
				selectfood.add(food.get(i));
				table.setValueAt(false, i, 6);
			}
		}
	}
	
}
</span>

2.店家预览

系统把从服务端获取的店铺信息已JTable的形式显示出来,用户可以在对应店铺的选中条上双击进入店铺

代码:ShopPanel.java

<span style="font-family:KaiTi_GB2312;font-size:18px;">package mypanel;

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.LinkedList;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;

import mytool.Food;
import mytool.Shop;
import mytool.SuggestTabelModel;

public class ShopPanel extends JPanel{
	LinkedList<Shop> shop;
	public LinkedList<Food> orderFood;
	public LinkedList<Food> shop1;
	public LinkedList<Food> shop2;
	public LinkedList<Food> shop3;
	int shop_num,shop1_num,shop2_num,shop3_num;
	public JTable table;
	SuggestTabelModel model;
	JScrollPane jscrollPane;
	final String[] headers = {"序号","编号","店铺名"};
	Object[][] cellData =  null;
	private TableColumn column = null;
	
	public ShopPanel(StudentPanel studentPanel)
	{
		shop = new LinkedList<Shop>();
		orderFood = new LinkedList<Food>();
		shop1 = new LinkedList<Food>();
		shop2 = new LinkedList<Food>();
		shop3 = new LinkedList<Food>();
		
		model = new SuggestTabelModel(cellData,headers);
		table =  new JTable(model);
		jscrollPane = new JScrollPane(table);
		jscrollPane.setPreferredSize(new Dimension(340, 310));
		add(jscrollPane);
		//居中显示
		DefaultTableCellRenderer r=new DefaultTableCellRenderer();   
		r.setHorizontalAlignment(JLabel.CENTER);   
		table.setDefaultRenderer(Object.class,r);
//		column = table.getColumnModel().getColumn(0);
//		column.setPreferredWidth(120);
//		column =table.getColumnModel().getColumn(1);
//		column.setPreferredWidth(140);
//		column =table.getColumnModel().getColumn(2);
//		column.setPreferredWidth(170);
//		column =table.getColumnModel().getColumn(6);
//		column.setPreferredWidth(30);
		try
		{
			shop_num = studentPanel.in.readInt();
			System.out.println(shop_num);
			for(int i=0;i<shop_num;i++)
			{
				Shop tempshop=new Shop();
				tempshop.num = studentPanel.in.readInt();
				tempshop.name = studentPanel.in.readUTF();
				shop.add(tempshop);
			}
			shop1_num = studentPanel.in.readInt();
			for(int i=0;i<shop1_num;i++)
			{
				Food tempfood=new Food();
				tempfood.num = studentPanel.in.readInt();
				tempfood.name = studentPanel.in.readUTF();
				tempfood.shop = "龙鑫赣味小炒";
				tempfood.type = studentPanel.in.readUTF();
				tempfood.price = studentPanel.in.readFloat();
				shop1.add(tempfood);
			}
			shop2_num = studentPanel.in.readInt();
			for(int i=0;i<shop2_num;i++)
			{
				Food tempfood=new Food();
				tempfood.num = studentPanel.in.readInt();
				tempfood.name = studentPanel.in.readUTF();
				tempfood.shop = "牛肉面馆";
				tempfood.type = studentPanel.in.readUTF();
				tempfood.price = studentPanel.in.readFloat();
				shop2.add(tempfood);
			}
			shop3_num = studentPanel.in.readInt();
			for(int i=0;i<shop3_num;i++)
			{
				Food tempfood=new Food();
				tempfood.num = studentPanel.in.readInt();
				tempfood.name = studentPanel.in.readUTF();
				tempfood.shop = "dashitou";
				tempfood.type = studentPanel.in.readUTF();
				tempfood.price = studentPanel.in.readFloat();
				shop3.add(tempfood);
			}
		}
		catch(IOException e)
		{
			
		}
		model.setRowCount(0);
		for(int i=0;i<shop.size();i++)
		{
			model.addRow(new Object[]{i+1,shop.get(i).num,shop.get(i).name});
		}
		table.addMouseListener(studentPanel);
//				new MouseAdapter()
//		{ 
//			public void mouseClicked(MouseEvent e) 
//            {
//				if(e.getClickCount() == 2)
//				{ 
//					int row =((JTable)e.getSource()).rowAtPoint(e.getPoint()); //获得行位置 
//					int  col=((JTable)e.getSource()).columnAtPoint(e.getPoint()); //获得列位置 
//					System.out.println("行号:"+row+"列号:"+col+"数据:");
//					if(row == 0)
//					{
//						shopFoodPanel.updatePanel(1);
//						studentPanel.card.show(studentPanel, "foodPanel");
//					}
//					else if(row == 1)
//					{
//						
//					}
//					else if(row == 2)
//					{
//						
//					}
//				} 
//				else return;
//			}
//		});
		table.invalidate();
	}
	public ShopPanel()
	{
		
	}
}
</span>

3.我的菜单

在用户选择了菜单后系统会添加到我的菜单里,用户可以在该功能界面进行预览和修改菜单,确认后可以提交并进入付款界面

对应的类为MyOrderPanel.java和PayPanel.java,代码在源码中查看,不再贴出来。

4.吐槽专区

该功能尚未实现,打算用UDP来传输信息,由于时间问题,以后再说吧。如果大家有好的方法,可以在底下回复我。



  • 17
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值