Как установить стиль для JavaFX ContextMenu с помощью css?
Я пытаюсь изменить стиль элемента ContextMenu
, используя отдельный файл CSS. Я просмотрел раздел 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 для контекстного меню, в котором перечислены CSSBridge[context-menu]
, которые кажутся нечетными. Другие вещи, такие как Label, имеют 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();
}
}
Ответы
Ответ 1
Вот простой пример стилизации контекстного меню JavaFX через css.
Протестировано на 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 не функционировал так, как вы ожидаете.
Возможные причины:
- Вы не загружаете его правильно.
- Ваш файл css не копируется в ваш выходной путь.
- Ваш css файл иначе поврежден или синтаксически неверен.
- Вы используете более раннюю версию JavaFX, которая имеет трудности с отображением контекстных меню из css.
Обновление
Посмотрев полный код в вопросе, где загружается файл css через fxml, я могу воспроизвести вашу проблему, если контекстное меню не оформлено. Если вместо установки таблицы стилей в fxml, я устанавливаю таблицу стилей на сцену в коде (как в моем тестовом приложении), тогда все работает отлично.
Разница, когда css устанавливается через fxml, заключается в том, что fxml не устанавливает таблицу стилей на сцене, а вместо этого на родительский корень node сцены. Если в коде я добавляю таблицу стилей к родительскому, а не к сценарию, то в итоге я получаю такое же поведение от реализации кода, что и fxml. Таким образом, это не проблема с fxml как таковой, а, скорее, проблема с правилами наследования обработки css JavaFX 2.2 css. IMO, обработка css неверна - стиль должен быть одинаковым, независимо от того, установлена ли таблица стилей на сцене или в корневой папке node сцены.
Я советую указать ошибку с элементами управления временем исполнения JavaFX на http://javafx-jira.kenai.com с вашим тестовым примером и ссылкой на этот вопрос StackOverflow и Команда JavaFX решит проблему своевременно.
Как обходной путь, просто установите для своей таблицы стилей на сцене в коде.
Обновление
Корневая причина для этой проблемы выглядит как RT-19435: всплывающий элемент управления не является объявлением таблицы родительского стиля.
Ответ 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);
}
}
Для этого меню я установил syles следующим образом: ---
.
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;
}
он работает отлично, я могу изменить цвет фона, цвет рамки, значки настроек и т.д.