Java程序设计课程设计项目名称
项目名称:自动挡汽车操作模拟系统的设计与实现
英文名称:Design and Implementation of Operation Simulation System aboutAutomatic Vehicle
1、功能描述:
1)汽车的操作正常为启动(或熄火)、挂档、制动、油门控制等操作;
2)挂档实现自动挡的4档操作,既驻车档、倒车档、空档、行车档;
3)使用图形界面进行操作,汽车的状态在图形界面上显示出来;
4)操作流程不合理,要有相应的控制;
5)附加功能:
(1)汽车的油也要进行控制,发动机需要消耗汽油,提供汽油报警功能;
(2)汽车的行程数进行控制,用户界面显示当前行程数;
6)正常操作流程为:启动->刹车->挂档->放刹车->汽车运动->加油门->刹车->驻车档->熄火。行驶中严禁换挡,行驶档位不能启动。
参考文档:
【1】系统类的API文档,见CarApp.jar文件内的doc下的index.html文件
【2】系统运行效果,使用控制台,输入命令为:java –jar CarApp.jar
【3】汽车的运行可以选择gif文件,从网上搜索关键词“车运动 gif”或“动漫小车”等关键字搜索你喜欢的gif小车运动图片,然后使用“工具GIF帧提取器 V1.1 绿色版.rar”提出图片中的每帧图片。
【4】系统的运行效果参考图见图1.
图1:系统运行效果图
主要有四个类
测试类
public class CarApp {
public static void main(String[] args){
new MyFrame();
}
}
窗口类
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
//import javafx.beans.value.ChangeListener;
import javax.swing.*;
import javax.swing.event.*;
public class MyFrame extends JFrame implements ActionListener{
private JPanel pl1;
private JPanel pl2;
private JPanel pl3;
private JToggleButton start;
private JToggleButton barke;
private CardLayout card = null;
private MytomaticCar car;
private JRadioButton rb1;
private JRadioButton rb2;
private JRadioButton rb3;
private JRadioButton rb4;
private JSlider s2;//一个让用户以图形方式在有界区间内通过移动滑块来选择值的组件。
public JTextArea area1;
private JTextArea area;
private JButton refresh,jiayou;
private int s;
private JTextArea ll3;
public MyFrame(){
//大容器设置
super("自动挡小车模拟驾驶系统");
pack();//调整此窗口的大小,以适合其子组件的首选大小和布局
//setDefaultCloseOperation(3);//默认关闭状态
setSize(500, 680);
Dimension screen = //屏幕居中
Toolkit.getDefaultToolkit().getScreenSize();
setLocation((int)((screen.getWidth() - getWidth()) / 2.0D), (int)((screen.getHeight() - getHeight()) / 2.0D));
this.car= new MytomaticCar(new Engine());//创建自动控制对象并以发动机作为参数调用相应的构造函数
this.card = new CardLayout();
//容器上部分
this.pl1= new JPanel(card);//创建容器对象采用卡片布局
add(this.pl1, BorderLayout.NORTH);
this.pl1.setBorder(BorderFactory.createTitledBorder("汽车状态显示"));//BorderFactory创建一个具有指定颜色的线边框。
ImageIcon[] ims = new ImageIcon[25];//创建一个数组未初始化的图像图标。
int i = 0;
String[] imfn = new String[25];//用来存储相对路径制定文件名
JPanel[] pls = new JPanel[25];//面板数组装卡片
for (i = 0; i < 25; i++) imfn[i] = (".\\images\\Frame" + i + ".jpg");
for (i = 0; i < 25; i++) ims[i] = new ImageIcon(imfn[i]);//根据指定的文件创建一个 ImageIcon,指定 String 可以是一个文件名或是一条文件路径
for (i = 0; i < 25; i++) {
pls[i] = new JPanel();//创建对象并加载图片到面板上
pls[i].add(new JLabel(ims[i]));//把图片放在标签中再放到面板中显示
this.pl1.add(pls[i], "p" + i);//加到面板中去 同时命名
}
//容器中间部分(显示耗油量和里程数)
this.pl3 = new JPanel();
this.pl3.setBorder(BorderFactory.createTitledBorder("数据显示"));
add(this.pl3,BorderLayout.CENTER);
JLabel jl1 = new JLabel("油量(L):");
this.area1 = new JTextArea(1,5);
this.ll3=new JTextArea(1,7);
this.area1.setFont(new Font("华文行楷",Font.BOLD,20));
this.ll3.setFont(new Font("华文行楷",Font.BOLD,20));
this.ll3.setEditable(false);
this.ll3.setBackground(Color.yellow);
pl3.add(jl1);
pl3.add(ll3);
this.jiayou=new JButton("加油");
this.jiayou.addActionListener(this);
pl3.add(this.jiayou);
pl3.add(area1);
JLabel jl2 = new JLabel("里程(KM):");
pl3.add(jl2);
this.area= new JTextArea(1,5);
this.area.setEditable(false);
this.area.setBackground(Color.blue);
this.area.setForeground(Color.RED);
this.area.setFont(new Font("华文行楷",Font.BOLD,20));
pl3.add(this.area);
this.refresh=new JButton("重置");
this.refresh.addActionListener(this);
pl3.add(this.refresh);
//容器下部分
this.pl2 = new JPanel();
this.pl2.setBorder(BorderFactory.createTitledBorder("汽车驾驶室"));
add(this.pl2,BorderLayout.SOUTH);
//四个小部件的添加
JPanel m1=new JPanel();
m1.setBorder(BorderFactory.createTitledBorder("引擎发动器"));
m1.setLayout(new GridLayout(7,2));//网格布局管理器
this.start=new JToggleButton("启动");//JToggleButton按钮按下去会陷下 去,不会弹回来,除非你再按一次
this.start.addActionListener(this);//添加监听器
m1.add(new JLabel(""));
m1.add(this.start);
this.pl2.add(m1);
this.pl2.add(new JLabel(" "));
JPanel m2 = new JPanel();
m2.setBorder(BorderFactory.createTitledBorder("制动器"));
m2.setLayout(new GridLayout(7,2));//网格布局管理器
this.barke=new JToggleButton("制动器");//JToggleButton按钮按下去会陷下 去,不会弹回来,除非你再按一次
this.barke.addActionListener(this);//添加监听器
m2.add(new JLabel(" "));
m2.add(this.barke);
this.pl2.add(m2);
this.pl2.add(new JLabel(" "));
JPanel m3 = new JPanel();
m3.setBorder(BorderFactory.createTitledBorder("档位控制器"));
m3.setLayout(new GridLayout(1,3));
//需要再创一个小面板才能实现排序
JPanel m33=new JPanel();
m33.setLayout(new GridLayout(8,2));
this.rb1 = new JRadioButton("P");
this.rb1.addActionListener(this);
this.rb1.setSelected(true);//默认位置
this.rb2 = new JRadioButton("R");
this.rb2.addActionListener(this);
this.rb3 = new JRadioButton("N");
this.rb3.addActionListener(this);
this.rb4 = new JRadioButton("D");
this.rb4.addActionListener(this);
ButtonGroup grp1 = new ButtonGroup();//单选按钮
m3.add(new JLabel(" "));
grp1.add(this.rb1); grp1.add(this.rb2); grp1.add(this.rb3); grp1.add(this.rb4);
m33.add(this.rb1);m33.add(new JLabel(""));m33.add(this.rb2); m33.add(new JLabel(""));
m33.add(this.rb3);m33.add(new JLabel("")); m33.add(this.rb4);
m3.add(m33);
this.pl2.add(m3);
this.pl2.add(new JLabel(" "));
JPanel m4 = new JPanel();
m4.setBorder(BorderFactory.createTitledBorder("油门控制器"));
m4.setLayout(new GridLayout(0, 2));
this.s2 = new JSlider(1, 0, 200, 0);
this.s2.setForeground(Color.ORANGE);
this.s2.setMajorTickSpacing(50);
this.s2.setMinorTickSpacing(10);
this.s2.setPaintTicks(true);
this.s2.setPaintLabels(true);
this.s2.setPaintTrack(true);
this.s2.setSnapToTicks(true);
this.s2.addChangeListener(new ChangeListener()//事件监听器
{
public void stateChanged(ChangeEvent e)
{
int n = MyFrame.this.s2.getValue();
MyFrame.this.car.addSpeed(n);
}
});
m4.add(s2);
this.pl2.add(m4);
this.pl2.add(new JLabel(" "));
int nn=this.car.getoil();
this.ll3.setText(""+nn);
setVisible(true);//可视 一定放在所有组件放好之后 否则有些不会显示
showautocarspeed();//控制显示车速
}
public void actionPerformed(ActionEvent e){
Object o = e.getSource();//获得按钮的变化
if ((o instanceof JRadioButton)) {//单选按钮变化
JRadioButton rbt = (JRadioButton)e.getSource();//获取按钮状态
String ch = rbt.getText();//获得按钮的字符
String s = "PRND";
int n = s.indexOf(ch);//返回该字符在字符串中出现的位置
int gear = this.car.getGear();//获得档位
if (!this.car.getParkBrake()){//判断制动器状态
JOptionPane.showMessageDialog(this, "制动时才能换挡!", "非法操作", 0);
switch (gear) {//制动时候才能换挡的操作若换挡,则不会改变单选按钮的选中状态
case 0:
this.rb1.setSelected(true);//将该按钮设置为选中模式
break;
case 1:
this.rb2.setSelected(true);
break;
case 2:
this.rb3.setSelected(true);
break;
case 3:
this.rb4.setSelected(true);
default:
break;
}
}else {
this.car.engageGear(n);//挂档操作
}
}else if ((o instanceof JToggleButton)) {//判断按钮是否是JToggleButton
JToggleButton jtb = (JToggleButton)o;
String name = jtb.getText();
if (name.equals("启动")) {
this.car.startEngine();
this.s2.setValue(1);
jtb.setText("熄火");
}else if(name.equals("制动器")) {
if (!this.car.ParkBrake) {
this.car.brake();
this.s2.setValue(1);
jtb.setText("制动中");
}
} else if (name.equals("熄火")){
if(this.car.getGear()!=0){
JOptionPane.showMessageDialog(this, "停车挡才能熄火!", "非法操作", 0);
this.start.setSelected(true);
}else{
jtb.setText("启动");
this.rb1.setSelected(true);
this.car.flameout();
}
}else if(name.equals("制动中")){
this.car.freeBrake();
jtb.setText("制动器");
}
}else if((o instanceof JButton)){
JButton jtb = (JButton)o;
String name = jtb.getText();
if((!this.car.getParkBrake()) && (this.car.getEngineThread() != null) && (this.car.getEngineThread().isAlive())){//判断状态
JOptionPane.showMessageDialog(this, "运动状态不能进行此操作", "非法操作", 0);
}else if(name.equals("重置")){
this.area.setText("0");
this.s=0;
}else if(name.equals("加油")&& (this.car.getEngineThread() == null)){
String sss=area1.getText();
int n=Integer.parseInt(sss);
int nn=this.car.getoil();
if(nn<500){
if(n+nn>=500){
this.ll3.setText(""+500);
}else{
this.car.addOil(n);
int ppp=this.car.getoil();
this.ll3.setText(""+ppp);
}
}else if(nn==500){
JOptionPane.showMessageDialog(this, "油量已满", "非法操作", 0);
}
}
}
}
public void showautocarspeed(){
while (true){
if(this.car.getEngineThread() != null){
int n=this.car.getoil();//显示油量
this.ll3.setText(""+n);
}
if((this.car.getoil()==69)||(this.car.getoil()==70)){
JOptionPane.showMessageDialog(this, "油量不足", "非法操作", 0);
}
if(this.car.getoil()==0){
this.start.setText("启动");
this.start.setSelected(false);
this.car.flameout();
}
try{
Thread.sleep(1411 - this.car.getSpeed());
if ((!this.car.getParkBrake()) && (this.car.getEngineThread() != null) && (this.car.getEngineThread().isAlive())) {
this.area.setText(""+s); //显示里程
if (this.car.getGear() == 1) {//后退挡
this.card.previous(this.pl1);
this.s=s+1;
continue;
}
if (this.car.getGear() == 3) {//前进档
this.card.next(this.pl1);
this.s=s+1;
continue;
}
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
引擎类
public class Engine implements Runnable{//多线程,汽车运行是发动机需要启动
public int speed = 0;
private MytomaticCar car;
public void setCar(MytomaticCar car){//在汽车上安装发动机
this.car = car;
}
public void run(){
while (true){
try{
Thread.sleep(2000-this.car.getSpeed());
}
catch (InterruptedException e){
e.printStackTrace();
}
if(this.car.innage > 0) {
this.car.innage -= 1;
if(!this.car.getParkBrake()&&this.car.innage > 0)
if (this.car.getGear() == 1)
{
this.car.innage -= 1;
}
else if (this.car.getGear() == 3&&this.car.innage > 1)
{
this.car.innage -= 2;
}
}else{
try{
this.car.flameout();
}catch (Exception localException){
}
}
if (this.car.innage >= 70)
continue;
}
}
}
控制室类
public class MytomaticCar {
public static int innage = 500;
private Engine engine;
private Thread engineThread;
public static int P = 0;
public static final int R = 1;
public static final int N = 2;
public static final int D = 3;
public boolean ParkBrake = false;
private int gear = 0;
public MytomaticCar(){//无参构造方法
this.engine = null;
}
public MytomaticCar(Engine engine) {//有参构造方法
this.engine = engine;
engine.setCar(this);
}
public Thread getEngineThread(){//获得发动机线程
return this.engineThread;
}
public void setEngine(Engine engine){//安装发动机
this.engine = engine;
engine.setCar(this);
}
public int getoil(){//获取油量
return this.innage;
}
public void addOil(int value){//加油操作
if(this.innage<500){
this.innage+= value;
}
}
public boolean startEngine(){//启动发动
if (this.engineThread == null) {
this.engineThread = new Thread(this.engine);
}
if (!this.engineThread.isAlive()) {
this.engineThread.start();
System.out.println("发动机启动正常!");
}
return true;
}
public void flameout(){//熄火操作
try{
if (this.engineThread.isAlive())
this.engineThread.stop();
}catch (Exception localException) {
}finally {//初始化操作
this.engineThread = null;
this.gear = 0;
}
}
public boolean getParkBrake(){//制动状态
return this.ParkBrake;
}
public void freeBrake(){//放刹车
if (((this.gear == 1) || (this.gear == 3)) && (this.engineThread != null) && (this.engineThread.isAlive())) {
this.engine.speed = 10;
}
this.ParkBrake = false;
}
public void brake(){//刹车
this.engine.speed = 0;
this.ParkBrake = true;
}
public int getGear(){//获得档位
return this.gear;
}
public void engageGear(int gear){//挂挡操作
if (this.ParkBrake)
this.gear = gear;
}
public int getSpeed(){//提出汽车速度
return this.engine.speed;
}
public void addSpeed(int n){//加速
if ((this.engine.speed >= 0) && (this.engine.speed < 1200))
this.engine.speed = (10 + n * 100);
}
}