当前位置: 首页 > article >正文

Java语言程序设计基础篇_编程练习题**18.39(拖动树)

目录

题目:**18.39(拖动树)

代码示例

代码逻辑解析 

类定义和变量初始化

main 方法

start 方法

drawRecursiveTree 方法

动画演示


题目:**18.39(拖动树)

修改编程练习题18.38, 将树移动到鼠标所拖动到的位置

Java语言程序设计基础篇_编程练习题**18.38 (递归树)-CSDN博客

  • 代码示例

编程练习题18_39RecursionTree.java

package chapter_18;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class 编程练习题18_39RecursionTree extends Application{
	private int order;
	private int size;
	private int canvasWidth;
	private int canvasHeight;
	double mouseX,mouseY;
	
	public static void main(String[] args) {
		Application.launch(args);
	}
	@Override
	public void start(Stage primaryStage) throws Exception {
		size = 300;
		canvasWidth = size;
		canvasHeight = size - 50;
		
		Group root = new Group();
		BorderPane treePane = new BorderPane(root);
		Scene scene = new Scene(treePane,size,size);
		
		TextField tfOrder = new TextField();
		Label lbOrder = new Label("Enter a umber",tfOrder);
		lbOrder.setContentDisplay(ContentDisplay.RIGHT);
		lbOrder.setAlignment(Pos.CENTER);
		
		BorderPane borderPane = new BorderPane();
		borderPane.setCenter(treePane);
		borderPane.setBottom(lbOrder);
		BorderPane.setAlignment(lbOrder, Pos.CENTER);
		
		tfOrder.setOnKeyPressed(e ->{
			if(e.getCode() == KeyCode.ENTER) {
				root.getChildren().clear();
				order = Integer.parseInt(tfOrder.getText());
				drawRecursiveTree(root,order,canvasWidth/8,canvasHeight/4,
						canvasHeight*0.24,Math.PI/2);
			}
		});
		treePane.setOnMousePressed(e -> {  
	            mouseX = e.getSceneX();  
	            mouseY = e.getSceneY();  
	        });  
		treePane.setOnMouseDragged(e ->{
			 double offsetX = e.getSceneX() - mouseX;  
	            double offsetY = e.getSceneY() - mouseY;  
	            mouseX = e.getSceneX();  
	            mouseY = e.getSceneY();  
	            treePane.setTranslateX(treePane.getTranslateX() + offsetX);  
	            treePane.setTranslateY(treePane.getTranslateY() + offsetY); 
		});
		scene.setRoot(borderPane);
		primaryStage.setTitle(getClass().getName());
		primaryStage.setScene(scene);
		primaryStage.show();
	}
	private void drawRecursiveTree(Group group,int order,double x,double y,double length,double angle) {
		if(order < 0)
			return;
		double x2 = x + length*Math.cos(angle);
		double y2 = y - length*Math.sin(angle);
		Line line = new Line(x,y,x2,y2);
		line.setStroke(Color.BLACK);
		group.getChildren().add(line);
		drawRecursiveTree(group, order-1, x2, y2, length*0.7, angle-Math.PI/6);
		drawRecursiveTree(group, order-1, x2, y2, length*0.7, angle+Math.PI/6);
	}
}
  • 代码逻辑解析 

类定义和变量初始化
  • 类定义编程练习题18_39RecursionTree 类继承自 Application,是 JavaFX 应用程序的入口。
  • 变量初始化:类中定义了多个私有变量,包括 order(树的阶数),size(窗口大小),canvasWidth 和 canvasHeight(画布的大小,尽管在绘图逻辑中它们主要用于计算初始位置和长度),以及 mouseX 和 mouseY(用于记录鼠标按下时的位置,以实现拖动功能)。
main 方法
  • Application.launch(args);:这是 JavaFX 应用程序的标准启动方式,它接收命令行参数并启动应用程序。
start 方法
  • 初始化窗口和画布:设置窗口大小为 size(300 像素),并计算画布的大小(canvasWidth 和 canvasHeight)。
  • 创建 Group 和 BorderPaneGroup 对象 root 用于存放绘制的图形元素,而 BorderPane 对象 treePane 则用于将 root 作为其中心区域。注意,这里创建了一个额外的 BorderPaneborderPane)来包装 treePane 和包含输入框的 Label,但实际上 treePane 已经足够作为场景的中心内容,并且可以直接与输入框的 Label 结合使用,减少嵌套。
  • 创建用户输入控件TextField 用于接收用户输入的阶数,Label 显示提示信息并与 TextField 关联。Label 的内容显示设置为右侧,但在这个布局中可能看起来不太直观。
  • 布局设置:使用 BorderPane 布局,将包含 Group 的 treePane 设置为中心区域,将包含输入框的 Label 设置为底部区域,并尝试将 Label 对齐到中心(但这对 BorderPane 的底部区域来说并不适用,因为它主要影响水平方向的对齐)。
  • 事件监听
    • 为 TextField 设置按键事件监听器,当按下回车键时,清除 Group 中的所有子元素,解析用户输入的阶数,并调用 drawRecursiveTree 方法绘制树。
    • 为 treePane 设置鼠标按下和拖动事件监听器,以实现整个树的拖动功能。当鼠标按下时,记录鼠标位置;当鼠标拖动时,计算鼠标移动的偏移量,并更新 treePane 的平移变换,从而实现拖动效果。
  • 设置并显示舞台:将包含所有控件的 BorderPaneborderPane)设置为场景的根节点,设置舞台的标题,将场景添加到舞台,并显示舞台。
drawRecursiveTree 方法
  • 递归逻辑:该方法通过递归调用自身来绘制树的每一级分支。
  • 参数:包括 Group 对象(用于添加线条)、阶数(order)、当前分支的起点坐标(xy)、分支的长度(length),以及当前分支的角度(angle)。
  • 递归终止条件:如果阶数小于 0,则递归结束。
  • 绘制线条:计算当前分支的终点坐标,创建 Line 对象,设置其颜色和起点终点坐标,并将其添加到 Group 中。
  • 递归调用:对当前分支的左右两侧进行递归调用,每次递归时减小分支长度并调整角度(左右分支分别减去和加上 Math.PI/6,即 30 度)。

  • 动画演示


http://www.kler.cn/news/317609.html

相关文章:

  • SpringBoot+Thymeleaf租房管理系统
  • 亲测好用,ChatGPT 3.5/4.0新手使用手册,最好论文指令手册~
  • Python知识点:如何使用Python进行物联网数据处理
  • java日志框架之JUL(Logging)
  • Debezium日常分享系列之:Debezium 2.7.3.Final发布
  • sheng的学习笔记-AI-K-摇臂赌博机(K-armed bandit)
  • 96 kHz、24bit 立体声音频ADC芯片GC5358描述
  • 2025秋招LLM大模型多模态面试题(八)- langchain完整面试题
  • 【Python】快速判断两个commit 是否存在cherry-pick 关系
  • ubuntu查看全部的磁盘分区命令
  • ​智慧铜矿厂综合管控平台,智慧矿山数字孪生
  • 应用案例 | 使用dataFEED OPC Tunnel解决基于DCOM的OPC Classic通信难题
  • axios相关知识点
  • Hadoop三大组件之HDFS(一)
  • git remote
  • Transformers | 在自己的电脑上开启预训练大模型使用之旅!
  • 基于Spring Boot的宠物咖啡馆平台【附源码】
  • Ceph官方文档_01_Ceph简介
  • 构建数据分析模型,及时回传各系统监控监测数据进行分析反馈响应的智慧油站开源了。
  • 实时对话翻译软件
  • 【Linux】解锁管道通信和共享内存通信,探索进程间通信的海洋
  • 显示屏显示缺陷检测系统源码分享
  • GEE教程:利用NASA的SMAP(Soil Moisture Active Passive)数据计算2020-2024年的时序土壤湿度分析
  • OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【扩展组件】上
  • 【Power Compiler手册】13.UPF多电压设计实现(7)
  • GPU共享技术深度剖析与总结
  • css禁止图片保存,CSS中的图片保存方法
  • 【逻辑回归+实战】
  • LLM安全风险及应对
  • Android CarrierConfig 配置问题的解决流程