厦大计算机系Java程序设计实验(五)

习题1 赛车

题目描述:绘制一辆赛车(颜色任选,款式如图),使用上下左右箭头控制赛车的移动。注意不能让赛车的任何部位超出界面的边界。

解题思路:本题将小车打包成一个结点,然后放置在一个Pane面板上。并编写四个函数分别处理上下左右四个事件的响应。

源代码

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import static javafx.scene.paint.Color.*;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class RacingCar extends Application
{
    @Override
    public void start(Stage primaryStage)
    {
        Pane pane = new Pane();
        Car carPane = new Car();
        
        carPane.setOnKeyPressed(e -> {
            switch(e.getCode())
            {
                case UP: {
                    carPane.up();
                }break;
                case DOWN: {
                    carPane.down();
                }break;
                case LEFT: {
                    carPane.left();
                }break;
                case RIGHT: {
                    carPane.right();
                }break;
            }
        });
        
        pane.getChildren().add(carPane);
        
        Scene scene = new Scene(pane, 200, 100);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Racing car");
        primaryStage.show();
        carPane.requestFocus();
    }
}

class Car extends Pane
{
    Circle leftWheel = new Circle(5, BLACK);
    Circle rightWheel = new Circle(5, BLACK);
    Rectangle body = new Rectangle(50, 10, AQUA);
    Polygon hat = new Polygon();
    
    Car()
    {
        leftWheel.setCenterX(15);
        leftWheel.setCenterY(95);
        rightWheel.setCenterX(35);
        rightWheel.setCenterY(95);
        body.setX(0);
        body.setY(80);
        ObservableList<Double> list = hat.getPoints();
        list.addAll(20.0, 70.0,
            30.0, 70.0,
            40.0, 80.0,
            10.0, 80.0);
        hat.setFill(BLUE);
        getChildren().addAll(leftWheel, rightWheel, body, hat);
    }
    
    public void up()
    {
        if(leftWheel.getCenterY() - 10 >= 25)
        {
            leftWheel.setCenterY(leftWheel.getCenterY() - 10);
            rightWheel.setCenterY(rightWheel.getCenterY() - 10);
            body.setY(body.getY() - 10);
            ObservableList<Double> list = hat.getPoints();
            for(int i = 1; i < 8; i = i + 2)
                list.set(i, list.get(i) - 10);
        }
    }
    
    public void down()
    {
        if(leftWheel.getCenterY() + 10 <= 95)
        {
            leftWheel.setCenterY(leftWheel.getCenterY() + 10);
            rightWheel.setCenterY(rightWheel.getCenterY() + 10);
            body.setY(body.getY() + 10);
            ObservableList<Double> list = hat.getPoints();
            for(int i = 1; i < 8; i = i + 2)
                list.set(i, list.get(i) + 10);
        }
    }
    
    public void left()
    {
        if(leftWheel.getCenterX() - 10 >= 15)
        {
            leftWheel.setCenterX(leftWheel.getCenterX() - 10);
            rightWheel.setCenterX(rightWheel.getCenterX() - 10);
            body.setX(body.getX() - 10);
            ObservableList<Double> list = hat.getPoints();
            for(int i = 0; i < 8; i = i + 2)
                list.set(i, list.get(i) - 10);
        }
    }
    
    public void right()
    {
        if(leftWheel.getCenterX() + 10 <= 165)
        {
            leftWheel.setCenterX(leftWheel.getCenterX() + 10);
            rightWheel.setCenterX(rightWheel.getCenterX() + 10);
            body.setX(body.getX() + 10);
            ObservableList<Double> list = hat.getPoints();
            for(int i = 0; i < 8; i = i + 2)
                list.set(i, list.get(i) + 10);
        }
    }
}

测试样例


习题2 幻灯片放映

题目描述:写一个程序,将54张扑克牌图片,按照每次1张,每张1秒的放映间隔,按顺序循环显示图片。并且要求:(1)向上箭头加快放映速度;向下箭头减缓放映速度;(2)双击鼠标左键暂停放映,再次双击则继续。程序界面自定。

解题思路:设置一个时间轴,将每一张图片的查看放置在时间轴上,并设置相关的事件响应。

源代码

import java.io.IOException;
import java.io.InputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class ShowSlides extends Application
{
    private int imgNumber = 1;
    private boolean isPlay = true;
    
    @Override
    public void start(Stage primaryStage)
    {
        BorderPane pane = new BorderPane();
        
        String imgAddress = "cards/" + imgNumber + ".png";
        ImageView imgView = new ImageView();
        imgView.setImage(readImageFromJar("D:\\NetBeansProjects\\testJavaFX\\src\\cards.jar", imgAddress));
        
        pane.setCenter(imgView);
        
        EventHandler<ActionEvent> eventHandler = e -> {
            imgNumber = imgNumber % 54 + 1;
            String imgAddressNew = "cards/" + imgNumber + ".png";
            imgView.setImage(readImageFromJar("D:\\NetBeansProjects\\testJavaFX\\src\\cards.jar", imgAddressNew));
        };
        
        Timeline tl = new Timeline(new KeyFrame(Duration.millis(1000), eventHandler));
        tl.setCycleCount(Timeline.INDEFINITE);
        tl.play();
        
        imgView.setOnKeyPressed(e -> {
            if(e.getCode().compareTo(KeyCode.UP) == 0)
            {
                if(tl.getRate() < 1000)
                    tl.setRate(tl.getRate() * 2);
            }
            else if(e.getCode().compareTo(KeyCode.DOWN) == 0)
            {
                if(tl.getRate() >= 0.5)
                    tl.setRate(tl.getRate() / 2);
            }
        });
        imgView.setOnMouseClicked(e -> {
            if(e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 2)
            {
                if(isPlay == true)
                {
                    tl.pause();
                    isPlay = false;
                }
                else
                {
                    tl.play();
                    isPlay = true;
                }
            }
        });
        
        Scene scene = new Scene(pane, 300, 200);
        primaryStage.setTitle("Show Slides");
        primaryStage.setScene(scene);
        primaryStage.show();
        imgView.requestFocus();
    }
    
    public static Image readImageFromJar(String jarname, String picname)
    {
        Image image = null;
        try
        {
            JarFile jarFile = new JarFile(jarname);
            JarEntry entry = jarFile.getJarEntry(picname);
            InputStream in = jarFile.getInputStream(entry);
            image = new Image(in);
            in.close();
            jarFile.close();
        }
        catch (IOException e)
        {
            System.err.println("read file error.");
        }
        return image;
    }
}

测试样例


习题3  交通灯

题目描述:如图,当用户选择交通灯下方的颜色时,自动填充(相当于点亮)上面对应的颜色灯,并注意清空(相当于熄灭)原先点亮的灯。程序开始自动点亮红灯。


解题思路:在主面板上放置一个由矩形和三个圆组成的栈面板,以及一排单选框。并且设置单选框与三个圆颜色的响应。

源代码

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class TrafficLights extends Application
{   
    @Override
    public void start(Stage primaryStage)
    {
        VBox trafficLights = new VBox();
        StackPane centerPane = new StackPane();
        HBox radioButtonsPane = new HBox();
        BorderPane pane = new BorderPane();
        
        RadioButton rbRed = new RadioButton("Red");
        RadioButton rbYellow = new RadioButton("Yellow");
        RadioButton rbGreen = new RadioButton("Green");
        
        radioButtonsPane.getChildren().addAll(rbRed, rbYellow, rbGreen);
        radioButtonsPane.setSpacing(20);
        radioButtonsPane.setAlignment(Pos.CENTER);
        
        ToggleGroup group = new ToggleGroup();
        rbRed.setToggleGroup(group);
        rbYellow.setToggleGroup(group);
        rbGreen.setToggleGroup(group);
        
        Circle light1 = new Circle(20);
        Circle light2 = new Circle(20);
        Circle light3 = new Circle(20);
        
        light1.setFill(Color.RED);
        light2.setFill(Color.WHITE);
        light3.setFill(Color.WHITE);
        
        trafficLights.getChildren().addAll(light1, light2, light3);
        trafficLights.setAlignment(Pos.CENTER);
        trafficLights.setSpacing(10);
        
        Rectangle border = new Rectangle(0, 0, 50, 150);
        border.setStroke(Color.BLACK);
        border.setStrokeWidth(2);
        border.setFill(Color.TRANSPARENT);
        
        centerPane.getChildren().addAll(trafficLights, border); 
        pane.setCenter(centerPane);
        pane.setBottom(radioButtonsPane);
        
        rbRed.setOnAction(e -> {
            if(rbRed.isSelected() == true)
            {
                light1.setFill(Color.RED);
                light2.setFill(Color.WHITE);
                light3.setFill(Color.WHITE);
            }
        });
        rbYellow.setOnAction(e -> {
            if(rbYellow.isSelected() == true)
            {
                light1.setFill(Color.WHITE);
                light2.setFill(Color.YELLOW);
                light3.setFill(Color.WHITE);
            }
        });
        rbGreen.setOnAction(e -> {
            if(rbGreen.isSelected() == true)
            {
                light1.setFill(Color.WHITE);
                light2.setFill(Color.WHITE);
                light3.setFill(Color.GREEN);
            }
        });
        
        Scene scene = new Scene(pane, 300, 200);
        primaryStage.setTitle("Traffic Lights");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

测试样例


初始状态

选中红色

选中黄色

选中绿色

习题4  沿正弦曲线运动的小球

题目描述:如图,编程实现让小球沿着正弦曲线从左向右运动,如果到达曲线右边界,则回到最左边重新开始运动。用户按一次空格键可以暂停小球运动,再按一次空格键可以让小球继续运动。


解题思路:利用折线绘制正弦波图像,然后将小球放到折线运动,并设置相关的事件响应。

源代码

import javafx.animation.PathTransition;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polyline;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class RunningBall extends Application
{   
    private boolean isPlay;
    
    @Override
    public void start(Stage primaryStage)
    {
        Pane pane = new Pane();
        
        Polyline polyline = new Polyline();
        ObservableList<Double> list = polyline.getPoints();
        for(int i = 50; i <= 400; ++i)
        {
            list.add((double)i);
            list.add(50 * Math.cos(((double)i) / 50.0 * Math.PI) + 100);
        }
        pane.getChildren().addAll(polyline);
        
        Line axisX = new Line(25.0, 100.0, 425.0, 100.0);
        Line arrowX1 = new Line(420.0, 95.0, 425.0, 100.0);
        Line arrowX2 = new Line(420.0, 105.0, 425.0, 100.0);
        Line axisY = new Line(225.0, 175.0, 225.0, 25.0);
        Line arrowY1 = new Line(220.0, 30.0, 225.0, 25.0);
        Line arrowY2 = new Line(230.0, 30.0, 225.0, 25.0);
        pane.getChildren().addAll(axisX, arrowX1, arrowX2, axisY, arrowY1, arrowY2);
        
        Text X = new Text(410.0, 90.0, "X");
        Text Y = new Text(235.0, 30.0, "Y");
        Text Zero = new Text(228.0, 112.0, "0");
        Text Pi = new Text(265.0, 110.0, "π");
        Text minusPi = new Text(160.0, 110.0, "-π");
        Text doublePi = new Text(325.0, 112.0, "2π");
        Text minusDoublePi = new Text(125.0, 112.0, "-2π");
        pane.getChildren().addAll(X, Y, Zero, Pi, minusPi, doublePi, minusDoublePi);
        
        Circle ball = new Circle(5);
        ball.setCenterX(50);
        ball.setCenterY(50);
        ball.setFill(Color.BLACK);
        pane.getChildren().add(ball);
        
        PathTransition pt = new PathTransition();
        pt.setNode(ball);
        pt.setPath(polyline);
        pt.setDuration(Duration.millis(6000));
        pt.play();
        
        pt.currentTimeProperty().addListener((ov, old_val, new_val) -> {
            if(pt.getCurrentTime().compareTo(pt.getDuration()) >= 0)
                pt.playFromStart();
        });
        
        isPlay = true;
        ball.setOnKeyPressed(e -> {
            if(e.getCode() == KeyCode.SPACE)
            {
                if(isPlay == true)
                {
                    pt.pause();
                    isPlay = false;
                }
                else
                {
                    pt.play();
                    isPlay = true;
                }
            }
        });
        
        Scene scene = new Scene(pane, 450, 200);
        primaryStage.setTitle("Running Ball");
        primaryStage.setScene(scene);
        primaryStage.show();
        ball.requestFocus();
    }
}

测试样例


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值