代码之家  ›  专栏  ›  技术社区  ›  AlwaysNeedingHelp

将css应用于mouseevent上以编程方式创建的窗格时出错

  •  1
  • AlwaysNeedingHelp  · 技术社区  · 7 年前

    我有一个堆栈窗格,当鼠标进入时,我创建一个窗格,在其中粘贴一些文本,并在鼠标附近显示它。

    统计控制器.java

     stackPane.setOnMouseEntered(event -> {
                Pane pane = new Pane();
                Text text = new Text("Example Text");
    
                //Add the text to the pane and set it near the mouse
                pane.getChildren().add(text);
                pane.setLayoutY(event.getSceneY() - 50);
                pane.setLayoutX(event.getSceneX() - 100);
    
                //add the  style class to give it a blueBG background
                pane.getStyleClass().add("blueBG");
    
                // add it too our root
                getRoot().getChildren().add(pane);
    });
    

    当我翻过StackPane(图像中的黑色圆圈和问号)时,窗格和文本出现时,您可以看到下面的内容。

    enter image description here

    但是它没有我要找的蓝色背景。

    我发现奇怪的是,如果不是将它添加到根目录,而是将它添加到现有的vbox中,那么它的样式是正确的(这里我滚动到同一个stackpane上):

    enter image description here

    所以:

     //Styles Correctly
     getInfoBox().getChildren().add(pane);
    
    // Adds but does not style
    getRoot().getChildren().add(pane);
    

    一些值得注意的事情:

    1)getInfoBox()是一个静态getter。我有多个控制器,它们扩展了一个主控制器,它有静态实例变量,所有控制器都希望能够访问的东西-比如信息框,来显示信息。

    2)根是在主类中生成的borderpane:

    主类

    //Create the root
    BorderPane root = new BorderPane();
    
    // I've cut it out to save space but this repeats 4 times to set 
    //an .fxml file for the top, left, right and bottom of the borderPane ///
    FXMLLoader headerLoader = new FXMLLoader(getClass().getResource("/view/header.fxml"));
    Parent headerRoot = headerLoader.load();
    root.setTop(headerRoot);
    //------------------------------------------//
    
    //Set the static reference in the MasterController
    MasterController.setRoot(root);
    
    Scene scene = new Scene(root,1366,768);
    primaryStage.setScene(scene);
    primaryStage.show();
    

    3)css文件都是使用scene builder在.fxml文件中声明的。上、下、左、右.fxml文件都有相同的css(main.css)。加载在按钮上的statistic.fxml也会单击中心(您可以在图像中看到)

    建议:可能是因为css不是为场景或borderpane本身定义的,所以它只适用于添加到borderpane部分的节点?如果是这样,我将如何让进入场景/阶段使用相同的css,这是否会否定向每个.fxml添加css?

    编辑:

    将此代码添加到main以将css应用于场景时:

    Scene scene = new Scene(root,1366,768);
            scene.getStylesheets().add(getClass().getResource("/css/main.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
    

    我明白这一点:

    enter image description here

    所以文本的css现在可以工作了,但不能用于窗格?我不知道为什么会这样。

    //----复制--//

    主类

    package sample;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.scene.layout.BorderPane;
    import javafx.stage.Stage;
    
    public class Main extends Application {
    
        @Override
        public void start(Stage primaryStage) throws Exception{
    
            BorderPane bp = new BorderPane();
    
            MasterController.setRoot(bp);
    
            Parent left = FXMLLoader.load(getClass().getResource("left.fxml"));
            Parent right = FXMLLoader.load(getClass().getResource("right.fxml"));
    
            bp.setLeft(left);
            bp.setRight(right);
    
            Scene scene = new Scene(bp, 600, 400);
            scene.getStylesheets().add(getClass().getResource("main.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    主控制器.java

    package sample;
    
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.VBox;
    
    public class MasterController {
    
        private static VBox rightBox;
        private static BorderPane root;
    
        public static VBox getRightBox() {
            return rightBox;
        }
    
        public static void setRightBox(VBox rightBox) {
            MasterController.rightBox = rightBox;
        }
    
        public static BorderPane getRoot() {
            return root;
        }
    
        public static void setRoot(BorderPane root) {
            MasterController.root = root;
        }
    }
    

    左控制器.java

    package sample;
    
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    
    import java.io.IOException;
    
    public class LeftController extends MasterController {
    
        @FXML
        public void loadCenter(ActionEvent event) {
            try {
                    FXMLLoader loader = new FXMLLoader(getClass().getResource("center.fxml"));
                    Parent center = loader.load();
                getRoot().setCenter(center);
            } catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    

    中心控制器.java

    package sample;
    
    import javafx.application.Platform;
    import javafx.fxml.FXML;
    import javafx.scene.layout.Pane;
    import javafx.scene.layout.StackPane;
    import javafx.scene.layout.VBox;
    import javafx.scene.text.Text;
    
    public class CenterController extends MasterController {
    
    @FXML
    private VBox center;
        public void initialize() {
            Platform.runLater(this::build);
    
        }
    
        public void build() {
            center.getChildren().add(new Text("loaded"));
    
            StackPane stackPane = new StackPane();
            Text text = new Text("ROLL OVER");
    
            stackPane.getChildren().add(text);
            center.getChildren().add(stackPane);
    
            stackPane.setOnMouseEntered(event -> {
                getRightBox().getChildren().clear();
    
                Pane pane1 = new Pane();
                Text exampleText1 = new Text("Example Text");
                pane1.getStyleClass().add("blueBG");
    
                Pane pane2 = new Pane();
                Text exampleText2 = new Text("Example Text");
                pane2.getStyleClass().add("blueBG");
    
                pane1.getChildren().add(exampleText1);
                pane2.getChildren().add(exampleText2);
    
                pane1.setLayoutY(event.getSceneY() + 40);
                pane1.setLayoutX(event.getSceneX() - 40);
    
                getRoot().getChildren().add(pane1);
                getRightBox().getChildren().add(pane2);
            });
        }
    }
    

    右控制器.java 包装样品;

    import javafx.application.Platform;
    import javafx.fxml.FXML;
    import javafx.scene.layout.VBox;
    
    public class RightController extends MasterController {
    
    @FXML
    private VBox rightBox;
    
        public void initialize() {
            setRightBox(rightBox);
    
        }
    }
    

    FXML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import java.lang.*?>
    <?import java.util.*?>
    <?import javafx.scene.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    
    <VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.LeftController">
       <children>
          <Button mnemonicParsing="false" onAction="#loadCenter" prefHeight="38.0" prefWidth="200.0" text="Click me to load center" />
       </children>
    </VBox>
    

    FXML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.text.*?>
    <?import javafx.scene.layout.*?>
    
    <VBox fx:id="center" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="200.0" stylesheets="@main.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.CenterController">
       <children>
          <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Center" />
       </children>
    </VBox>
    

    FXML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.text.*?>
    <?import javafx.scene.layout.*?>
    
    <VBox fx:id="rightBox" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="200.0" stylesheets="@main.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.RightController">
       <children>
          <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Right Box" />
       </children>
    </VBox>
    

    MIN CSS

    .blueBG {
        -fx-background-color: aqua;
    }
    

    你应该得到以下结果。您可以看到窗格在添加到右侧时样式设置正确,但在添加根时样式设置不正确。

    enter image description here

    1 回复  |  直到 7 年前
        1
  •  3
  •   fabian    7 年前

    BorderPane 仅将布局应用于 center , left , right , top bottom 孩子们。但是,它是布局的父级(如果是根,则为场景),设置 Region 在布局过程中(或不,如本例中所示)。

    结果是样式应用于 Pane ,但是 窗格 残余 0 . 您可以通过添加

    pane1.resize(100, 100);
    

    设置窗格大小的事件处理程序。

    您需要使用其他类型的布局作为 pane1 的大小变为非空或自行调整大小。