JavaFX中MVC例子理解

news2025/1/18 16:53:04

       JavaFX可以让你使用GUI组件创建桌面应用程序。一个GUI应用程序执行三个任务:接受用户的输入,处理输入,并显示输出。而一个GUI应用程序包含两个
类型的代码:

  • 领域代码。处理特定领域的数据和遵循业务规范。
  • 交互代码。处理用户输入信息。

       MVC模型最大的优点就是同一组数据可以根据需求在不同的界面或表格中显示。例如你可以在web端,桌面端、工控机等不同UI界面上同时查看同一组数据。。MVC模型对应的有三个模型组件:model,view和controller。如下图所示:

        MVC模型介绍。

  • model:由记录数据的领域对象组成。
  • view:显示给用户的界面。
  • controller:处理用户输入,及对用户输入的响应。

       这里有个简单的例子。模型模块PersonTableUtil保存领域数据Person,因为只是显示数据,所有此示例中没有controller模块,显示模块SimplestableView

领域数据Person:

package cn.learnjavafx.ch11;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
 * @copyright 2023-2022
 * @package   learnjavafx8.ch11
 * @file      Person.java
 * @date      2023-07-01 21:31
 * @author    qiao wei
 * @version   1.0
 * @brief     模型类。保存数据,字段使用属性,可以通过注册监听器监听数据更新情况,自动更新属性。
 * @history
 */
public class Person {

	/**
	 * @class   Person
	 * @date    2023-07-01 21:31
	 * @author  qiao wei
	 * @version 1.0
	 * @brief   Default constructor.
	 * @param
	 * @return
	 * @throws
	 */
	public Person() {
		this("None", "None", null);
	}

	/**
	 * @class   Person
	 * @date    2023-07-01 21:32
	 * @author  qiao wei
	 * @version 1.0
	 * @brief   Constructor.
	 * @param   firstName 名。
	 * @param   lastName  姓。
	 * @param   birthDate 出生日期。
	 * @return
	 * @throws
	 */
	public Person(String firstName, String lastName, LocalDate birthDate) {
		this.firstName.set(firstName);
		this.lastName.set(lastName);
		this.birthDate.set(birthDate);
	}
	
	public final int getPersonId() {
		return personId.get();
	}
	
	public final ReadOnlyIntegerProperty getPersonIdProperty() {
		return personId.getReadOnlyProperty();
	}

	/**
	 * @class   Person
	 * @date    2023-07-01 21:37
	 * @author  qiao wei
	 * @version 1.0
	 * @brief   Get first name property.
	 * @param
	 * @return  Person first name.
	 * @throws
	 */
	public final String firstName() {
		return firstName.get();
	}

	public final void setFirstName(String firstName) {
		firstNameProperty().set(firstName);
	}

	public final StringProperty firstNameProperty() {
		return firstName;
	}

	public final String lastName() {
		return lastName.get();
	}

	public final void setLastName(String lastName) {
		lastNameProperty().set(lastName);
	}

	public final StringProperty lastNameProperty() {
		return lastName;
	}

	/** birthDate Property */
	public final LocalDate birthDate() {
		return birthDate.get();
	}
	
	public final void setBirthDate(LocalDate birthDate) {
		birthDateProperty().set(birthDate);
	}
	
	public final ObjectProperty<LocalDate> birthDateProperty() {
		return birthDate;
	}

	/**
	 * @class   Person
	 * @date    2023-07-02 10:30
	 * @author  qiao wei
	 * @version 1.0
	 * @brief   Domain specific business rules.
	 * @param   localDate 当地时区日期
	 * @return
	 * @throws
	 */
	public boolean isValidBirthDate(LocalDate localDate) {
		return isValidBirthDate(localDate, new ArrayList<>());
	}
	
	/**
	 * @class   Person
	 * @date    2023-07-08 19:21
	 * @author  qiao wei
	 * @version 1.0
	 * @brief   验证输入的出生日期是否有效。出生日期无效时,将错误日志记录到errorList中。
	 * @param   date 出生日期。
	 * @param   errorList 错误日志。   
	 * @return  出生日期有效返回true,反之返回false。
	 * @throws
	 */
	public boolean isValidBirthDate(LocalDate date, List<String> errorList) {
		if (null == date) {
			return true;
		}

		// Birthdate cannot be in the future
		if (date.isAfter(LocalDate.now())) {
			errorList.add(LocalDate.now().toString() + " : Birth date must not be in future.");

			return false;
		}

		return true;
	}

	/**
	 * @class   Person
	 * @date    2023-07-02 11:51
	 * @author  qiao wei
	 * @version 1.0
	 * @brief   重写方法,验证个人信息是否正确。Domain specific business rules。
	 * @param   errorList 错误信息列表。
	 * @return
	 * @throws
	 */
	public boolean isValidPerson(List<String> errorList) {
		return isValidPerson(this, errorList);
	}

	/**
	 * @class   Person
	 * @date    2023-07-02 11:53
	 * @author  qiao wei
	 * @version 1.0
	 * @brief   重写方法,验证个人信息是否正确,对个人的姓、名、生日进行有效性验证。Domain specific business
	 *           rules。
	 * @param   person 需要验证的个人信息。
	 * @param   errorList 错误信息列表。记录错误信息。 
	 * @return  true 个人信息有效;false 个人信息无效。
	 * @throws
	 */
	public boolean isValidPerson(Person person, List<String> errorList) {
		boolean isValidPerson = true;
		String firstName = person.firstName();

		// 将以下3个判断条件都走一遍,将所有异常信息统计到errorList中
		if (firstName == null || firstName.trim().length() == 0) {
			errorList.add("First name must contain minimum one character.");
			isValidPerson = false;
		}

		String lastName = person.lastName();
		if (null == lastName || 0 == lastName.trim().length()) {
			errorList.add("Last name must contain minimum one character.");
			isValidPerson = false;
		}

		if ( !isValidBirthDate(this.birthDate.get(), errorList)) {
			isValidPerson = false;
		}

		return isValidPerson;
	}
	
	/**
	 * @class   Person
	 * @date    2023-07-02 12:15
	 * @author  qiao wei
	 * @version 1.0
	 * @brief   根据年龄,返回不同的年龄层。
	 * @param
	 * @return  年龄层,枚举类型。根据不同年龄返回不同年龄层。
	 * @throws
	 */
	public AgeCategory getAgeCategory() {
		if (null == birthDate.get()) {
			return AgeCategory.UNKNOWN;
		}
		
		// 计算年龄。
		long years = ChronoUnit.YEARS.between(birthDate.get(), LocalDate.now());
		if (0 <= years && 2 > years) {
			return AgeCategory.BABY;
		} else if (2 <= years && 13 > years) {
			return AgeCategory.CHILD;
		} else if (13 <= years && 19 >= years) {
			return AgeCategory.TEEN;
		} else if (19 < years && 50 >= years) {
			return AgeCategory.ADULT;
		} else if (50 < years) {
			return AgeCategory.SENIOR;
		} else {
			return AgeCategory.UNKNOWN;
		}
	}

	public boolean save(List<String> errorList) {
		boolean isSaved = false;

		if (isValidPerson(errorList)) {
			System.out.println("Saved " + this.toString());
			isSaved = true;
		}

		return isSaved;
	}

	@Override
	public String toString() {
		StringBuilder stringBuilder = new StringBuilder("[personId=");
		stringBuilder.append(personId.get()).
			append(", firstName = ").append(firstName.get()).
			append(", lastName = ").append(lastName.get()).
			append(", birthDate = ").append(birthDate.get()).append("]");

		return stringBuilder.toString();
	}

	/**
	 * @date   2023-07-01 21:33
	 * @author qiao wei
	 * @brief  Person id
	 */
	private final ReadOnlyIntegerWrapper personId =
		new ReadOnlyIntegerWrapper(this, "personId", personSequence.incrementAndGet());
	
	private final StringProperty firstName =
		new SimpleStringProperty(this, "firstName", null);

	private final StringProperty lastName =
		new SimpleStringProperty(this, "lastName", null);

	/**
	 * @date   2023-07-01 21:33
	 * @author qiao wei
	 * @brief  出生日期。
	 */
	private final ObjectProperty<LocalDate> birthDate =
		new SimpleObjectProperty<>(this, "birthDate", null);

	/**
	 * @date   2023-07-01 21:34
	 * @author qiao wei
	 * @brief  Class field. Keeps track of last generated person id.
	 */
	private static AtomicInteger personSequence = new AtomicInteger(0);
}

模型模块PersonTableUtil,将Person数据添加到ObservabList中,作为数据模型返回给View。同时,PersonTableUtil有多个static方法返回TableColumn,进行处理,并根据显示模块的要求进行处理。

package cn.learnjavafx.ch13.tableview01;

import java.time.LocalDate;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;

import cn.learnjavafx.ch11.Person;

/**
 * @copyright 2023-2022
 * @package   cn.learnjavafx.ch13.tableview01
 * @file      PersonTableUtil.java
 * @date      2023-07-05 20:30
 * @author    qiao wei
 * @version   1.0
 * @brief     模型类。方法getPersonList返回与视图绑定的列表。方法getIdColumn,getFirstNameColumn,
 *             getLastNameColumn以列的数据格式返回列表中各项的对应值。
 * @history
 */
public class PersonTableUtil {
    
    /**
     * @class   PersonTableUtil
     * @date    2023-07-06 16:41
     * @author  qiao wei
     * @version 1.0
     * @brief   Default constructor.
     * @param   
     * @return  
     * @throws
     */
    public PersonTableUtil() {}
    
    /**
     * @class   PersonTableUtil
     * @date    2023-07-05 20:32
     * @author  qiao wei
     * @version 1.0
     * @brief   Retrieve an observable list of person.
     * @param   
     * @return  Person列表。要显示的模型。
     * @throws
     */
    public static ObservableList<Person> getPersonList() {
        Person p1 = new Person("Ashwin"
            , "Sharan"
            , LocalDate.of(2012, 10, 11));
        
        Person p2 = new Person("Advik"
            , "Tim"
            , LocalDate.of(2012, 10, 11));
        
        Person p3 = new Person("Layne"
            , "Estes"
            , LocalDate.of(2011, 12, 16));
        
        Person p4 = new Person("Mason"
            , "Boyd"
            , LocalDate.of(2003, 4, 20));
        
        Person p5 = new Person("Babalu"
            , "Sha"
            , LocalDate.of(1980, 1, 10));
        
        return FXCollections.<Person>observableArrayList(p1, p2, p3, p4, p5);
    }
    
    /**
     * @class   PersonTableUtil
     * @date    2023-07-05 20:40
     * @author  qiao wei
     * @version 1.0
     * @brief   Retrieve person Id TableColumn.
     * @param   
     * @return  Id column.
     * @throws
     */
    public static TableColumn<Person, Integer> getIdColumn() {
        /**
         * 创建显示的列实例。参数Person:列绑定的数据模型。参数Integer:数据模型中数据的类型,类型必须是引用类型。
         *  “Id”是列表头显示的内容。
         */
        TableColumn<Person, Integer> personIdCol = new TableColumn<>("Id");
        
        // 列实例绑定模型的对应属性。
        personIdCol.setCellValueFactory(new PropertyValueFactory<>("personId"));
        
        return personIdCol;
    }
    
    /**
     * @class   PersonTableUtil
     * @date    2023-07-05 20:51
     * @author  qiao wei
     * @version 1.0
     * @brief   Retrieve first name TableColumn.
     * @param   
     * @return  First name column.
     * @throws
     */
    public static TableColumn<Person, String> getFirstNameColumn() {
        TableColumn<Person, String> firstNameColumn = new TableColumn<>("First Name");
        firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));
        
        return firstNameColumn;
    }
    
    /**
     * @class   PersonTableUtil
     * @date    2023-07-05 20:59
     * @author  qiao wei
     * @version 1.0
     * @brief   Retrieve last name TableColumn.
     * @param   
     * @return  Last name column.
     * @throws
     */
    public static TableColumn<Person, String> getLastNameColumn() {
        TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
        lastNameColumn.setCellValueFactory(new PropertyValueFactory<>("lastName"));
        
        return lastNameColumn;
    }
    
    /**
     * @class   PersonTableUtil
     * @date    2023-07-05 21:00
     * @author  qiao wei
     * @version 1.0
     * @brief   Retrieve birthdate TableColumn.
     * @param   
     * @return  Birthdate column.
     * @throws
     */
    public static TableColumn<Person, LocalDate> getBirthDateColumn() {
        TableColumn<Person, LocalDate> birthDateColumn = new TableColumn<>("Birth Date");
        birthDateColumn.setCellValueFactory(new PropertyValueFactory<>("birthDate"));
        
        return birthDateColumn;
    }
}

SimplestTableView是显示模块,将模型模块中的数据显示出来。

package cn.learnjavafx.ch13.tableview01;

import java.time.LocalDate;

import javafx.application.Application;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;

import cn.learnjavafx.ch11.Person;

/**
 * @copyright 2023-2022
 * @package   cn.learnjavafx.ch13.tableview01
 * @file      SimplestTableView.java
 * @date      2023-07-05 22:52
 * @author    qiao wei
 * @version   1.0
 * @brief     
 * @history
 */
public class SimplestTableView extends Application {
    
    @Override
    public void start(Stage primaryStage) {
        try {
            start03(primaryStage);
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
    
    /**
     * @class   SimplestTableView
     * @date    2023-07-05 22:52
     * @author  qiao wei
     * @version 1.0
     * @brief   
     * @param   primaryStage Main window.
     * @return  
     * @throws
     */
    private void start01(Stage primaryStage) throws Exception {
        // Create a TableView and bind model.
        TableView<Person> table = new TableView<>(PersonTableUtil.getPersonList());
        
        /**
         * Add columns to the TableView in order.
         */
        table.getColumns().addAll(PersonTableUtil.getIdColumn()
            , PersonTableUtil.getFirstNameColumn()
            , PersonTableUtil.getLastNameColumn());
        
        // Add a table column in index position.
        table.getColumns().add(2, PersonTableUtil.getBirthDateColumn());
        
        VBox root = new VBox(table);
        root.setStyle("-fx-padding: 10;"
            + "-fx-border-style: solid inside;"
            + "-fx-border-width: 2;"
            + "-fx-border-insets: 5;"
            + "-fx-border-radius: 5;"
            + "-fx-border-color: pink;");        
        Scene scene = new Scene(root);
        
        primaryStage.setScene(scene);
        primaryStage.setTitle("Simplest TableView");
        primaryStage.show();
    }
    
    /**
     * @class   SimplestTableView
     * @date    2023-07-05 22:53
     * @author  qiao wei
     * @version 1.0
     * @brief   设置复合表头,占位符测试。设置表头Name中包含FirstName和LastName。当表格没有内容时,显示占位符内容。
     * @param   primaryStage 主窗体。
     * @return  
     * @throws
     */
    private void start02(Stage primaryStage) throws Exception {
        // Create a TableView with a list of persons.
        TableView<Person> table = new TableView<>(PersonTableUtil.getPersonList());
        
        // Placeholder。当table没有内容显示时,显示Label内容。
        table.setPlaceholder(new Label("No visible columns and/or data exist."));
        
        // Setup nest table header.
        TableColumn<Person, String> nameColumn = new TableColumn<>("Name");
        nameColumn.getColumns().addAll(PersonTableUtil.getFirstNameColumn()
            , PersonTableUtil.getLastNameColumn());
        
        // Inserts columns to the TableView.
        table.getColumns().addAll(PersonTableUtil.getIdColumn(), nameColumn);
        
        /**
         * 在指定列添加列表信息,列从0开始计数。FirstName和LastName设置在复合表头,只算一列。所以插入“出生日期”列只
         *  能在0~2列。
         */
        table.getColumns().add(2, PersonTableUtil.getBirthDateColumn());
        
        VBox root = new VBox(table);
        root.setStyle("-fx-padding: 10;"
            + "-fx-border-style: solid inside;"
            + "-fx-border-width: 2;"
            + "-fx-border-insets: 5;"
            + "-fx-border-radius: 5;"
            + "-fx-border-color: gray;");
        Scene scene = new Scene(root);
        
        primaryStage.setScene(scene);
        primaryStage.setTitle("Simplest TableView02");
        primaryStage.show();
    }
    
    private void start03(Stage primaryStage) {
        // Create a TableView instance and set Placeholder.
        TableView<Person> tableView = new TableView<>(PersonTableUtil.getPersonList());
        tableView.setPlaceholder(new Label("No rows to display"));
        
        // 调用PersonTableUtil.getIdColumn方法,返回TableColumn。
        TableColumn<Person, Integer> idColumn = PersonTableUtil.getIdColumn();
        
        /**
         * 创建TableColumn实例,参数Person表示列中显示数据来自于那里,参数String表示显示数据的类型,参数
         *  First Name是该列显示的列表头内容。
         */
        TableColumn<Person, String> firstNameColumn = new TableColumn<>("First Name");
        
        /**
         * PropertyValueFactory的参数是Person对象的字段,绑定Person的字段显示。
         * In the example shown earlier, a second PropertyValueFactory is set on the second
         *  TableColumn instance. The property name passed to the second PropertyValueFactory is
         *  lastName, which will match the getter method getLastName() of the Person class.
         */
        firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));
        
        TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
        lastNameColumn.setCellValueFactory(new PropertyValueFactory<>("lastName"));
        
        tableView.getColumns().addAll(lastNameColumn, firstNameColumn);
        tableView.getColumns().add(0, idColumn);
        
        tableView.getItems().add(new Person("John"
            , "Doe"
            , LocalDate.of(2000, 8, 12)));
        
        VBox root = new VBox(tableView);
        Scene scene = new Scene(root);
        
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

启用方法start01的运行结果如下图,02/03方法主要对数据插入不同列,在模型外添加模型数据测试。

start02方法和start03方法自测。

      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/755113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Zookeeper集群 + Kafka集群 + Filebeat + ELK

目录 一&#xff1a;Zookeeper 概述 1、Zookeeper 定义 2、Zookeeper 工作机制 3、Zookeeper 特点 4、 Zookeeper 数据结构 5、 Zookeeper 应用场景 6、 Zookeeper 选举机制 &#xff08;1&#xff09;第一次启动选举机制 &#xff08;2&#xff09;非第一次启动选举机制…

Java InetAddress类

【InetAddress类】 【相关方法】 【使用方法实例】 【代码结果】

HUAWEI Mate X3:内外屏双享,折叠影像诠释精彩

HUAWEI Mate X3是全球首款四曲折叠手机&#xff0c;轻薄实力派。它采用了独创的寰宇舷窗设计&#xff0c;内外双屏高清呈现均支持120Hz疾速高刷&#xff0c;10.7亿色彩显示&#xff0c;获得德国莱茵TV色准和准确色彩投射双认证。无论是看视频、玩游戏、办公学习&#xff0c;还是…

山西电力市场日前价格预测【2023-07-15】

日前价格预测 预测明日&#xff08;2023-07-15&#xff09;山西电力市场全天平均日前电价为282.84元/MWh。其中&#xff0c;最高日前电价为546.79元/MWh&#xff0c;预计出现在20: 30。最低日前电价为0.00元/MWh&#xff0c;预计出现在11: 45-14:15。 价差方向预测 1&#xff1…

国产芯片——单片机32位mcu的应用

随着物联网与人工智能和智能制造的发展&#xff0c;单片机作为嵌入式系统的核心控制器&#xff0c;在各类行业应用中占据重要位置。其中32位MCU在芯片设计、制造工艺、封装技术上等取得显著突破&#xff0c;以高性能的技术条件被广泛应用在智能物联等行业的方案开发中。今天我们…

自动脱扣型绝缘靴(手套)耐压支架

一、概述 武汉凯迪正大自动脱扣型绝缘靴&#xff08;手套&#xff09;耐压支架是根据《DLT 976-2017 带电作业工具、装置和设备预防性试验规程》、《DLT 1476-2015电力b2b平台工器具预防性试验规程》、《GBT 17622-2008带电作业用绝缘手套》、《CB21148 2020足部防护 b2b平台鞋…

客户案例 | 燕千云加速『名创优品』数智化转型进程

名创优品积极响应政府改革的号召&#xff0c;坚持推进数智化转型。数智化转型底层需要依托技术支撑。甄知燕千云面对名创庞大的用户体量、繁杂的终端门店需求、海量的企业知识&#xff0c;为其搭建统一的服务管理平台&#xff0c;实现内部信息协同及可视化管理&#xff0c;高效…

ElasticSearch 数据迁移工具elasticdump

ElasticSearch 数据迁移工具elasticdump Elasticdump 是一个用于导入和导出 Elasticsearch 数据的命令行工具。它提供了一种方便的方式来在不同的 Elasticsearch 实例之间传输数据&#xff0c;或者进行数据备份和恢复。 使用 Elasticdump&#xff0c;你可以将 Elasticsearch …

继承【C++】

继承 继承解决了什么问题&#xff1f;继承的应用场景是什么&#xff1f;简单举例继承的关系语法 继承解决了什么问题&#xff1f; C代码的 可重用性 通过继承实现。 新类从已有类获得已有的特性。 继承的应用场景是什么&#xff1f; 继承是一种设计的结果。&#xff08;举例…

Linux线程的生产者消费者模型 --- 阻塞队列(blockqueue)

文章目录 线程同步条件变量条件变量的接口 生产者消费者场景消费者和消费者的关系生产者和生产者的关系生产者和消费者的关系从何体现出效率的提高 Blockqueueblockqueue.hpp为什么条件变量的接口有锁作为参数 CP.cc生产者 -> queue -> 消费者兼生产者 -> queue ->…

javaweb使用Thymeleaf 最凝练的CRUD项目-中

javaweb使用Thymeleaf 最凝练的CRUD项目-中 6、显示首页 ①目标 浏览器访问index.html&#xff0c;通过首页Servlet&#xff0c;渲染视图&#xff0c;显示首页。 ②思路 ③代码 [1]创建PortalServlet <servlet><servlet-name>PortalServlet</servlet-name…

复习第一课 C语言-ubuntu下的命令

目录 linux命令 【1】打开关闭终端 【2】终端 【3】ls命令 【4】cd 切换路径 【5】新建 【6】删除 【7】复制 【8】移动 【9】常用快捷键 【10】vi编辑器 【11】简单编程步骤 任务&#xff1a; linux命令 【1】打开关闭终端 打开终端&#xff1a; 1. 直接点击 …

【优选算法题练习】day6

文章目录 一、76. 最小覆盖子串1.题目简介2.解题思路3.代码4.运行结果 二、704. 二分查找1.题目简介2.解题思路3.代码4.运行结果 三、34. 在排序数组中查找元素的第一个和最后一个位置1.题目简介2.解题思路3.代码4.运行结果 总结 一、76. 最小覆盖子串 1.题目简介 76. 最小覆…

IDE /字符串 /字符编码与文本文件(如cpp源代码文件)

文章目录 概述文本编辑器如何识别文件的编码格式优先推测使用了UTF-8编码&#xff1f;字符编码的BOM字节序标记重分析各文本编辑器下的测试效果Qt Creator的文本编辑器系统记事本VS的文本编辑器Notepad 编译器与代码文件的字符编码ANSI编码其他 概述 前期在整理 《IDE/VS项目属…

Unity VR 开发教程 OpenXR+XR Interaction Toolkit(九)根据不同物体匹配对应的抓取手势

文章目录 &#x1f4d5;教程说明&#x1f4d5;前置准备&#x1f4d5;HandData 脚本存储手部数据&#x1f4d5;制作预设手势&#x1f4d5;手势匹配脚本 GrabHandPose⭐完整代码⭐需要保存的数据⭐得知什么时候开始抓取和取消抓取⭐将手势数据赋予手部模型⭐平滑变化手势⭐开始抓…

Linux重定向符怎么用/Centos和Ubuntu怎么安装软件?Vim编辑器是啥、又怎么用/Linux权限怎么修改设置

前情提要&#xff1a;经过一段时间的沉淀&#xff0c;因为要用到Linux&#xff0c;索性就梳理总结一下Linux的基本知识&#xff01; 紧接着前文&#xff0c;有需要点击这里查看哦&#xff01;(╹▽╹) 3.10 echo命令 作用&#xff1a;在命令行内输出指定内容语法&#xff1a;…

Windows多网卡通过跃点数设置网络优先级失败解决办法

在有多个网卡的情况下&#xff0c;网络优先级往往不是自己所需的&#xff0c;默认情况Windows会自动决策出应该优先使用的最佳网络连接顺序&#xff0c;但用户也有可能需要访问某一网卡所在内网等情况&#xff0c;此时可能就无法正常访问。网上查找可以通过修改跃点数的方式手动…

XUbuntu22.04之解决蓝牙鼠标不停掉线问题(追凶过程)(一百八十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

python_day8_bar

初识柱状图 导包 from pyecharts.charts import Bar from pyecharts.options import *创建柱状图对象 bar Bar()添加x轴数据,注意数据格式为列表 bar.add_xaxis([中国, USA, 不列颠])添加y轴数据,注意格式&#xff1a;图例&#xff0c;列表数据&#xff0c;设置 bar.add_…

Stable Diffusion Webui 之 ControlNet使用

一、安装 1.1、插件安装 1.2、模型安装 模型安装分为预处理模型和 controlnet所需要的模型。 先安装预处理模型&#xff0c;打开AI所在的安装目录\extensions\sd-webui-controlnet\annotator,将对应的预处理模型放进对应的文件夹中即可&#xff0c; 而controlnet所需模型则…