【问题标题】:How do you set the style for a JavaFX ContextMenu using css?如何使用 css 设置 JavaFX ContextMenu 的样式?
【发布时间】:2012-06-20 20:50:52
【问题描述】:

我正在尝试使用单独的 CSS 文件更改 ContextMenu 项目的样式。我查看了 caspian.css 部分,发现了以下定义:

  • .context-menu
  • .context-menu .separator
  • .context-menu .scroll-arrow
  • .context-menu .scroll-arrow:hover
  • .context-menu:show-mnemonics .mnemonic-underline

我将它们完全复制到我的 css 文件中,并仅更改了背景颜色值作为测试:

.context-menu {
    -fx-skin: "com.sun.javafx.scene.control.skin.ContextMenuSkin";
    -fx-background-color: #006699;
    -fx-background-insets: 0, 1, 2;
    -fx-background-radius: 0 6 6 6, 0 5 5 5, 0 4 4 4;
/*    -fx-padding: 0.666667em 0.083333em 0.666667em 0.083333em;  8 1 8 1 */
    -fx-padding: 0.333333em 0.083333em 0.666667em 0.083333em; /* 4 1 8 1 */
}

.context-menu .separator {
    -fx-padding: 0.0em 0.333333em 0.0em 0.333333em; /* 0 4 0 4 */
}

.context-menu .scroll-arrow {
    -fx-padding: 0.416667em 0.416667em 0.416667em 0.416667em; /* 5 */
    -fx-background-color: #006699;
}

.context-menu .scroll-arrow:hover {
    -fx-background: -fx-accent;
    -fx-background-color: #006699;
    -fx-text-fill: -fx-selection-bar-text;
}

.context-menu:show-mnemonics .mnemonic-underline {
    -fx-stroke: -fx-text-fill;
}

这显然行不通,否则我不会在这里。无论我更改什么值,它似乎都没有效果。

我打开 JavaFX Scene Builder 进行查看(旁注,我将其用作最后的手段,因为我发现它使用起来非常笨拙)。我注意到上下文菜单的 CSS 部分的 Styleable Parts 下列出了CSSBridge[context-menu],这看起来很奇怪。其他诸如标签之类的东西有Label[label]

谁能向我解释这里发生了什么,因为它似乎忽略了上下文菜单的 css 文件并使用 caspian.css 中的默认值?


附加要运行的示例 FXML 文件、css 和 java 代码。

Sample.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>

<AnchorPane fx:id="myroot" xmlns:fx="http://javafx.com/fxml">
  <children>
    <Label text="Right click for options">
      <contextMenu>
        <ContextMenu>
          <items>
            <MenuItem text="Help" />
            <MenuItem text="Me" />
          </items>
        </ContextMenu>
      </contextMenu>
    </Label>
  </children>
  <stylesheets>
    <URL value="@contextcolor.css" />
  </stylesheets>
</AnchorPane>

contextcolor.css

.root {
  -fx-background-color: cornsilk; 
  -fx-padding: 10;
}

.context-menu {
  -fx-background-color: #006699;
  -fx-text-fill: white;
}

.menu-item .label {
  -fx-text-fill: yellow;
}

.menu-item:focused .label {
  -fx-text-fill: white;
}

Test.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Test extends Application {

    public static void main(String[] args) {
        Application.launch(Test.class, args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        System.out.println(com.sun.javafx.runtime.VersionInfo.getVersion());

        Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));

        stage.setScene(new Scene(root));
        stage.show();
    }
}

【问题讨论】:

标签: styling javafx-2


【解决方案1】:

这是一个通过 css 设置 JavaFX 上下文菜单样式的简单示例。

在 WinXPsp3、Jdk7u6b14ea、JavaFX 2.2b12 上测试。

Java 应用程序

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;

public class ContextColor extends Application {
  public static void main(String[] args) { launch(args); }
  @Override public void start(Stage stage) {
    Label label = new Label("Right click for options");
    label.setContextMenu(new ContextMenu(new MenuItem("Help"), new MenuItem("Me")));
    Scene scene = new Scene(label);
    scene.getStylesheets().add(ContextColor.class.getResource("contextcolor.css").toExternalForm());
    stage.setScene(scene);
    stage.show();
  }
}

css 样式表

/** contextcolor.css
 *   place in same folder as ContextColor.java
 *   ensure your build system copies this file to the ContextColor.class output directory on build
 */
.root {
  -fx-background-color: cornsilk; 
  -fx-padding: 10;
}

.context-menu {
  -fx-background-color: #006699;
  -fx-text-fill: white;
}

.menu-item .label {
  -fx-text-fill: yellow;
}

.menu-item:focused .label {
  -fx-text-fill: white;
}

我无法告诉您 css 样式未按预期运行的确切原因。 一些可能的原因是:

  1. 您没有正确加载它。
  2. 您的 css 文件未复制到您的输出路径。
  3. 您的 css 文件已损坏或语法不正确。
  4. 您使用的是较早版本的 JavaFX,难以从 css 中设置上下文菜单的样式。

更新

查看问题中通过 fxml 加载 css 文件的完整代码,我可以重现上下文菜单未设置样式的问题。如果不是在 fxml 中设置样式表,而是在代码中设置样式表在场景中(就像在我的测试应用程序中一样),那么一切正常。

通过fxml设置css的区别在于fxml不是在场景中设置样式表,而是在场景的父根节点上设置。如果在代码中我将样式表添加到父级而不是场景,那么我最终会从代​​码实现中得到与 fxml 相同的行为。所以这并不是 fxml 本身的问题,而是 JavaFX 2.2 css 处理的继承规则的问题。 IMO,css 处理是错误的 - 无论样式表是在场景中还是在场景的根节点上设置的,样式都应该相同。

我建议您在 http://javafx-jira.kenai.com 提交针对 JavaFX 运行时控件的错误,并附上您的测试用例和返回此 StackOverflow 问题的链接,JavaFX 团队将在适当的时候解决该问题。

作为一种解决方法,现在只需在代码中将样式表设置在场景中即可。


更新

此问题的根本原因似乎是 RT-19435: popup control not styled be parent's style sheet declarations

【讨论】:

  • 我运行的是 2.1 版,所以更新到 2.2.0-beta 版。我运行了您的示例并且它有效。由于我使用的是 FXML 文件,因此我将您的示例转换为 FXML 并再次运行它。不幸的是,它不起作用。如果您不介意看一下,我将使用 FXML 更新我的问题。
  • 感谢您发布代码 jschoen,我根据您发布的代码更新了我的答案。
  • 我按照建议创建了新问题#RT-22871。感谢您的帮助。
  • 谢谢,这对我来说也是个问题。
【解决方案2】:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.geometry.Insets;

/**
 *
 * @author nidhi.a.agrawal
 */
public class Context extends Application {

    @Override
    public void start(Stage stage) throws Exception {
      //  Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));

        TextArea notification = new TextArea();
        ContextMenu contextMenu = new ContextMenu();

        Node itemIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_createnew.png")));
        Node con_test_hierIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_Configure_Test _Hierachy.png")));
        Node cutIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_cut.png")));
        Node copyIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_copy.png")));
        Node pasteIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_paste.png")));
        Node insertIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_insert.png")));
        Node editIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_edit.png")));
        Node renameIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_rename.png")));
        Node deleteIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_delete.png")));
        Node tagIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_tag.png")));
        Node refreshIcon = new ImageView(new Image(getClass().getResourceAsStream("icon_refresh.png")));


        MenuItem sap_new = new MenuItem("Create New Sap System", itemIcon);
        MenuItem con_test_hier = new MenuItem("Configure Test Hierarchy", con_test_hierIcon);
        MenuItem cut = new MenuItem("Cut", cutIcon);
        MenuItem copy = new MenuItem("Copy", copyIcon);
        MenuItem paste = new MenuItem("Paste", pasteIcon);
        MenuItem insert = new MenuItem("Insert", insertIcon);
        MenuItem edit = new MenuItem("Edit", editIcon);
        MenuItem rename = new MenuItem("Rename", renameIcon);
        MenuItem delete = new MenuItem("Delete", deleteIcon);
        MenuItem tag = new MenuItem("Tag", tagIcon);
        MenuItem refresh = new MenuItem("Refresh", refreshIcon);

         contextMenu.getItems().addAll(sap_new,con_test_hier,cut,copy,paste,insert,edit,rename,delete,tag,refresh);
notification.setContextMenu(contextMenu);
 Group root = new Group();
        root.getChildren().add(notification);
         Scene scene = new Scene(root);
          scene.getStylesheets().add(Context.class.getResource("contextcolor.css").toExternalForm());
        stage.setScene(scene);
        stage.show();

       }
public static void main(String[] args) {
        launch(args);
    }
}

对于这些菜单,我设置了如下样式:---

.

root {
  -fx-background-color: cornsilk; 
  -fx-padding: 10;
}

.context-menu {
  -fx-background-color: #C8CFD7;
  -fx-border-color: #BBC2CC;
  -fx-text-fill: white;
}


.menu-item .label {
  -fx-fill:red;
    -fx-font-family:tahoma;
    -fx-font-size: 12px;;
    -fx-stroke:#C8CFD7;
    -fx-strok-width:.25;
}

.menu-item:focused .label {
  -fx-text-fill: white;
}
.menu-item{
    -fx-border-color: #DDDEE2 transparent #B9C0C8 transparent;

    -fx-border-width:0.50px;

}
.menu-item:focused {
     -fx-background: -fx-accent;
     -fx-background-color: #7092BE;
     -fx-text-fill: -fx-selection-bar-text;
}

运行良好,我可以更改背景颜色、边框颜色、设置图标等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-18
    • 2011-03-17
    • 2016-02-29
    • 1970-01-01
    相关资源
    最近更新 更多