嘿,我正在尝试找出如何将我的 JavaFX 滑块开关转换为 Scene Builder 2.0 控件,以便我可以在场景生成器中使用它。
我目前正在观看这 2 个 YouTube 视频:
要进行滑块开关: Youtube 视频#1
创建场景生成器控件: Youtube 视频#2
上面 2 个 YouTube 视频的问题在于,它展示了如何首先在 Scene Builder 2.0 中开始设计,这不是我在关注第一个 YouTube 视频时所做的方式。 那么有没有办法将我在java中的内容转移到场景生成器来创建控件?
我完整的滑块开关代码:
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.animation.FillTransition;
import javafx.animation.ParallelTransition;
import javafx.animation.TranslateTransition;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.Parent;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontSmoothingType;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.util.Duration;
public class Main extends Application {
static Text text;
static Pane root = new Pane();
private Parent createContent() {
root.setPrefSize(300, 300);
TranslateTransition translateAnimation2 = new TranslateTransition(Duration.seconds(0.25));
ParallelTransition animation2 = new ParallelTransition(translateAnimation2);
Rectangle bg = new Rectangle(300, 300);
ToggleSwitch toggle = new ToggleSwitch();
toggle.setTranslateX(100);
toggle.setTranslateY(100);
text.setTranslateX(toggle.getTranslateX());
text.setTranslateY(toggle.getTranslateY() + 9);
translateAnimation2.setNode(text);
root.getChildren().addAll(toggle, text);
return root;
}
private static class ToggleSwitch extends Parent {
private BooleanProperty switchedOn = new SimpleBooleanProperty(false);
private TranslateTransition translateAnimation = new TranslateTransition(Duration.seconds(0.25));
private TranslateTransition translateAnimation2 = new TranslateTransition(Duration.seconds(0.25));
private FillTransition fillAnimation = new FillTransition(Duration.seconds(0.25));
private ParallelTransition animation = new ParallelTransition(translateAnimation, fillAnimation);
private ParallelTransition animation2 = new ParallelTransition(translateAnimation2);
public BooleanProperty switchedOnProperty() {
return switchedOn;
}
public boolean checkSwitch() {
switchedOn.set(!switchedOn.get());
return switchedOn.get();
}
public ToggleSwitch() {
Rectangle background = new Rectangle(30, 10);
background.setArcWidth(10);
background.setArcHeight(10);
background.setFill(Color.rgb(255, 161, 161));
background.setStroke(Color.SLATEGREY);
Circle trigger = new Circle(10);
trigger.setCenterX(8);
trigger.setCenterY(6);
trigger.setFill(Color.rgb(245, 245, 245));
trigger.setStroke(Color.SLATEGREY);
DropShadow shadow = new DropShadow();
shadow.setRadius(2);
trigger.setEffect(shadow);
text = new Text();
text.setFont(Font.font("Verdana", FontWeight.MEDIUM, 8));
text.setFill(Color.rgb(0, 0, 0));
text.setTextAlignment(TextAlignment.CENTER);
text.setFontSmoothingType(FontSmoothingType.LCD);
text.textProperty().bind(Bindings.when(switchedOnProperty()).then("ON").otherwise("OFF"));
text.setOnMouseClicked(e -> {
switchedOn.set(!switchedOn.get());
});
translateAnimation.setNode(trigger);
translateAnimation2.setNode(text);
fillAnimation.setShape(background);
getChildren().addAll(background, trigger);
switchedOn.addListener((obs, oldState, newState) -> {
boolean isOn = newState.booleanValue();
translateAnimation.setToX(isOn ? 45 - 30 : 0);
translateAnimation2.setToX(isOn ? this.getTranslateX() + 17 : this.getTranslateX());
fillAnimation.setFromValue(isOn ? Color.rgb(255, 161, 161) : Color.rgb(156, 240, 168));
fillAnimation.setToValue(isOn ? Color.rgb(156, 240, 168) : Color.rgb(255, 161, 161));
animation.play();
animation2.play();
});
setOnMouseClicked(event -> {
switchedOn.set(!switchedOn.get());
});
}
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(createContent()));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
遵循以下步骤:
在此示例中,我将所有内容压缩到单个模块和项目中。
步骤类似,这里不再重复。
场景生成器中的自定义控件:
应用程序中的自定义控件:
ToggleSwitch.java
package org.example.customcomponent;
import javafx.animation.FillTransition;
import javafx.animation.ParallelTransition;
import javafx.animation.TranslateTransition;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.Parent;
import javafx.scene.effect.DropShadow;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.*;
import javafx.util.Duration;
public class ToggleSwitch extends Parent {
private BooleanProperty switchedOn = new SimpleBooleanProperty(false);
private TranslateTransition translateAnimation = new TranslateTransition(Duration.seconds(0.25));
private TranslateTransition translateAnimation2 = new TranslateTransition(Duration.seconds(0.25));
private FillTransition fillAnimation = new FillTransition(Duration.seconds(0.25));
private ParallelTransition animation = new ParallelTransition(translateAnimation, fillAnimation);
private ParallelTransition animation2 = new ParallelTransition(translateAnimation2);
private final Text text = new Text();
public BooleanProperty switchedOnProperty() {
return switchedOn;
}
public boolean checkSwitch() {
switchedOn.set(!switchedOn.get());
return switchedOn.get();
}
public Text getText() {
return text;
}
public ToggleSwitch() {
Rectangle background = new Rectangle(30, 10);
background.setArcWidth(10);
background.setArcHeight(10);
background.setFill(Color.rgb(255, 161, 161));
background.setStroke(Color.SLATEGREY);
Circle trigger = new Circle(10);
trigger.setCenterX(8);
trigger.setCenterY(6);
trigger.setFill(Color.rgb(245, 245, 245));
trigger.setStroke(Color.SLATEGREY);
DropShadow shadow = new DropShadow();
shadow.setRadius(2);
trigger.setEffect(shadow);
text.setFont(Font.font("Verdana", FontWeight.MEDIUM, 8));
text.setFill(Color.rgb(0, 0, 0));
text.setTextAlignment(TextAlignment.CENTER);
text.setFontSmoothingType(FontSmoothingType.LCD);
text.textProperty().bind(Bindings.when(switchedOnProperty()).then("ON").otherwise("OFF"));
text.setOnMouseClicked(e -> switchedOn.set(!switchedOn.get()));
translateAnimation.setNode(trigger);
translateAnimation2.setNode(text);
fillAnimation.setShape(background);
getChildren().addAll(background, trigger);
switchedOn.addListener((obs, oldState, newState) -> {
boolean isOn = newState;
translateAnimation.setToX(isOn ? 45 - 30 : 0);
translateAnimation2.setToX(isOn ? this.getTranslateX() + 17 : this.getTranslateX());
fillAnimation.setFromValue(isOn ? Color.rgb(255, 161, 161) : Color.rgb(156, 240, 168));
fillAnimation.setToValue(isOn ? Color.rgb(156, 240, 168) : Color.rgb(255, 161, 161));
animation.play();
animation2.play();
});
setOnMouseClicked(event -> switchedOn.set(!switchedOn.get()));
}
}
ToggleController.java
package org.example.customcomponent;
import javafx.fxml.FXML;
import javafx.scene.layout.VBox;
public class ToggleController {
@FXML
private VBox toggleContainer;
@FXML
private ToggleSwitch toggleSwitch;
@FXML
private void initialize() {
toggleContainer.getChildren().add(
toggleSwitch.getText()
);
toggleSwitch.switchedOnProperty().addListener((o, wasOn, isOn) ->
System.out.println("Switch state: " + isOn)
);
}
}
ToggleApp.java
package org.example.customcomponent;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class ToggleApp extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader loader = new FXMLLoader(ToggleApp.class.getResource("toggle.fxml"));
Parent toggle = loader.load();
stage.setScene(new Scene(toggle));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
切换.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.VBox?>
<?import org.example.customcomponent.ToggleSwitch?>
<VBox fx:id="toggleContainer" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="6.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.customcomponent.ToggleController">
<children>
<ToggleSwitch fx:id="toggleSwitch" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
模块信息.java
module org.example.customcomponent {
requires javafx.controls;
requires javafx.fxml;
opens org.example.customcomponent to javafx.fxml;
exports org.example.customcomponent;
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>customcomponent</artifactId>
<version>1.0-SNAPSHOT</version>
<name>customcomponent</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>21.0.3</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>21.0.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>