I have a tableview in JavaFX and I don't want focused row to differ from others. The problem is that when I click on a row and select it, the row's bottom border goes away. Which css property makes it and how can I fix that?
In the attached screen shot all rows selected, and my last click was on "nature" row.
MCVE:
Main.java:
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
HBox hBox = new HBox();
Scene scene = new Scene(hBox, 300, 275);
scene.getStylesheets().add("main.css");
TableView<Keyword> keywordsTable = new TableView<>();
TableColumn<Keyword, String> wordColumn = new TableColumn<>();
ObservableList<Keyword> data = FXCollections.observableArrayList();
wordColumn.setCellValueFactory(new PropertyValueFactory<>("word"));
keywordsTable.getColumns().add(wordColumn);
keywordsTable.setItems(data);
keywordsTable.setRowFactory(param -> {
TableRow<Keyword> row = new TableRow<>();
row.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
keywordsTable.requestFocus();
if (!row.isEmpty() && e.getButton().equals(MouseButton.PRIMARY)) {
changeRowSelection(keywordsTable, row.getItem(), row.getIndex());
}
e.consume();
});
row.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
keywordsTable.requestFocus();
e.consume();
});
return row;
});
keywordsTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
data.add(new Keyword("one"));
data.add(new Keyword("two"));
data.add(new Keyword("three"));
data.add(new Keyword("four"));
data.add(new Keyword("five"));
hBox.getChildren().add(keywordsTable);
primaryStage.setScene(scene);
primaryStage.show();
}
private void changeRowSelection(TableView table, Keyword keyword, int index) {
if (table.getSelectionModel().getSelectedItems().contains(keyword)) {
table.getSelectionModel().clearSelection(index);
} else {
table.getSelectionModel().select(index);
}
}
public static void main(String[] args) {
launch(args);
}
public class Keyword {
private final SimpleStringProperty word;
public Keyword(String word) {
this.word = new SimpleStringProperty(word);
}
public String getWord() {
return word.get();
}
public void setWord(String word) {
this.word.set(word);
}
}
}
main.css:
.table-row-cell:focused {
-fx-background-insets: 0;
-fx-padding: 0;
}
.list-cell:filled:selected,
.tree-cell:filled:selected,
.table-row-cell:filled:selected,
.tree-table-row-cell:filled:selected,
.table-row-cell:filled > .table-cell:selected,
.tree-table-row-cell:filled > .tree-table-cell:selected {
-fx-background: #C7E8EA;
-fx-table-cell-border-color: #26ABD7 !important;
-fx-text-fill: black;
}
.table-row-cell:focused {
-fx-background-insets: 0 0 0;
}
.table-cell {
-fx-background-insets: 0 !important;
}
It worked for me with the following css
see for information : https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html
.table-view {
-my-bg-color: #C7E8EA;
-my-bd-color: violet;
}
.table-row-cell {
-fx-background: -my-bg-color;
-fx-background-color: -my-bd-color, -fx-background;
-fx-background-insets: 0, 0 0 1 0;
-fx-padding: 0;
-fx-text-fill: black;
}
.table-cell {
-fx-padding: 0.166667em; /* 2px, plus border adds 1px */
-fx-background-color: null;
-fx-border-color: transparent -my-bd-color transparent transparent;
-fx-cell-size: 2.0em; /* 24 */
-fx-text-fill: -fx-text-background-color;
}
Note the custom css variable definition in .table-view. This is not mandatory, just for convenience.
Related
I'm working with JavaFX 8 on Windows 10. In a WebView with a dark background, I can see the light grey corner when the scrollbars are visible. WebView"manages scrolling automatically." I already tried this, as well as other selectors:
.corner {
-fx-background-color: black;
}
And also
.corner {
-fx-background-color: black;
}
.scroll-bar > .corner {
-fx-background-color: black;
}
.scroll-pane > .corner {
-fx-background-color: black;
}
.scroll-bar .corner {
-fx-background-color: black;
}
.scroll-pane .corner {
-fx-background-color: black;
}
.web-view .scroll-bar .corner {
-fx-background-color: black;
}
.web-view .scroll-pane .corner {
-fx-background-color: black;
}
But it doesn't work. So what could I do?
Example code: Main class
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.loadContent("<html><body><pre>This is a very very very very very very long string </pre><b>test</b><p>1</p><p>2</p><p>3</p></body></html>");
webEngine.setUserStyleSheetLocation("data:,body { background: black; color: white; } ");
StackPane root = new StackPane();
root.setPadding(new Insets(5));
root.getChildren().add(webView);
webView.setStyle("-fx-background-color:black;");
root.setStyle("-fx-background-color:black;");
root.getStylesheets().add("style.css");
primaryStage.setTitle("JavaFX Test");
primaryStage.setScene(new Scene(root, 300, 150));
primaryStage.show();
}
}
style.css
.scroll-bar .track {
-fx-background-color: black;
}
.scroll-bar .thumb {
-fx-background-color: brown;
}
.corner {
-fx-background-color: black;
}
This also has an awful behavior where the scrollbars only appear when I hover with the mouse, but nevermind. This doesn't happen in my main application. I just want to change the color of the grey square in the corner.
I am unable to reproduce the effect on Mac OS X v10.13.6 with Java v1.8.0_201. Because WebView "manages scrolling automatically" and JavaFX uses WebKit, #Pagbo suggests using -webkit-scrollbar-corner, as suggested here. In another context, #DVarga suggests using -fx-background-color, as shown here. As the effect may be platform/version dependent, I've added a complete example and screenshot for reference. In particular, the lower-right corner is overlain by the vertical scrollbar's decrement button. Stretching the window to hide the vertical scrollbar reveals the horizontal scrollbar's increment button. The corner is always occupied by a scrollbar button or black.
Main.java
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.loadContent("<html><body><pre>"
+ "This is a very very very very very very long string<br>"
+ System.getProperty("os.name") + " v"
+ System.getProperty("os.version") + "; Java v"
+ System.getProperty("java.version")
+ "</pre><b>test</b><p>1</p><p>2</p><p>3</p></body></html>");
webEngine.setUserStyleSheetLocation("data: ,body "
+ "{ background: black; color: white; } "
+ "::-webkit-scrollbar-corner { background: #0c0c0c; } ");
StackPane root = new StackPane();
root.setPadding(new Insets(5));
root.getChildren().add(webView);
webView.setStyle("-fx-background-color:black;");
root.setStyle("-fx-background-color:black;");
root.getStylesheets().add("style.css");
primaryStage.setTitle("JavaFX Test");
primaryStage.setScene(new Scene(root, 300, 150));
primaryStage.show();
}
}
style.css
.scroll-bar .track {
-fx-background-color: black;
}
.scroll-bar .thumb {
-fx-background-color: brown;
}
.corner {
-fx-background-color: black;
}
I am currently creating the game PacMan using JavaFX MVC. I made an FXML file using SceneBuilder.
I have also added 2 themes: a classic theme and an X-Mas theme. The thing I want to do now is switch themes using a button which is created in the FXML file (see image: buttons 'classic' & 'xmas'.
Please help me out.
This is how it looks like:
This is my current code:
FXMLSideMenucontroller.fxml
package sidemenu;
import com.jfoenix.controls.JFXButton;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
public class FXMLSideMenuController implements Initializable {
#FXML
private AnchorPane ap_main;
#FXML
private AnchorPane ap_gamefield;
#FXML
private Pane pnl_highscore;
#FXML
private Pane pnl_main;
#FXML
private Pane pnl_moeilijkheid;
#FXML
private VBox vbox_moeilijkheid;
#FXML
private JFXButton btn_easy;
#FXML
private JFXButton btn_medium;
#FXML
private JFXButton btn_hard;
#FXML
private Pane pnl_credits;
#FXML
private Pane pnl_spelers;
#FXML
private JFXButton btn_mraerts;
#FXML
private ImageView iview_mraerts;
#FXML
private JFXButton btn_mrlemmens;
#FXML
private ImageView iview_mrlemmens;
#FXML
private Pane pnl_thema;
#FXML
private VBox vbox_thema;
#FXML
private JFXButton btn_classic;
#FXML
private JFXButton btn_xmas;
#FXML
private AnchorPane ap_sidemenu;
#FXML
private AnchorPane ap_sidepane;
#FXML
private JFXButton btn_spelers;
#FXML
private JFXButton btn_moeilijkheid;
#FXML
private JFXButton btn_thema;
#FXML
private JFXButton btn_highscore;
#FXML
private JFXButton btn_credits;
#FXML
private FontAwesomeIconView iview_spelers;
#FXML
private FontAwesomeIconView iview_niveau;
#FXML
private FontAwesomeIconView iview_thema;
#FXML
private FontAwesomeIconView iview_highscore;
#FXML
private FontAwesomeIconView iview_credits;
#FXML
private void handleButtonAction(ActionEvent event) {
if(event.getSource() == btn_spelers) {
pnl_spelers.toFront();
} else
if(event.getSource() == btn_moeilijkheid) {
pnl_moeilijkheid.toFront();
} else
if(event.getSource() == btn_thema) {
pnl_thema.toFront();
} else
if(event.getSource() == btn_highscore) {
pnl_highscore.toFront();
} else
if(event.getSource() == btn_credits) {
pnl_credits.toFront();
}
}
/**
#FXML
private void handleThemeSwitcher(ActionEvent event) {
if(event.getSource() == btn_classic) {
scene.getStylesheets().remove(getClass().getResource("Resources/style.css").toExternalForm());
scene.getStylesheets().remove(getClass().getResource("Resources/xmas.css").toExternalForm());
scene.getStylesheets().add(getClass().getResource("Resources/style.css").toExternalForm());// Load voor custom stylesheet
}
if(event.getSource() == btn_xmas) {
scene.getStylesheets().remove(getClass().getResource("Resources/style.css").toExternalForm());
scene.getStylesheets().remove(getClass().getResource("Resources/xmas.css").toExternalForm());
scene.getStylesheets().add(getClass().getResource("Resources/xmas.css").toExternalForm());// Load voor custom stylesheet
}
} */
/** #FXML
private void closeMenuItem(ActionEvent event) {
if(event.getSource() == icon_close) {
pnl_main.toFront();
}
}*/
#Override
public void initialize(URL location, ResourceBundle resources) {
pnl_main.toFront();
}
}
SideMenu.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package sidemenu;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.stage.Stage;
/**
*
* #author User
*/
public class SideMenu extends Application {
#Override
public void start(Stage stage) throws Exception {
Font.loadFont(
SideMenu.class.getResource("Resources/CrackMan.TTF").toExternalForm(),
10); // Load voor custom font
Parent root = FXMLLoader.load(getClass().getResource("FXMLSideMenu.fxml"));
Scene scene = new Scene(root);
//scene.getStylesheets().add(getClass().getResource("Resources/style.css").toExternalForm());// Load voor custom stylesheet
stage.setTitle("PacMan");
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Style.css
/* Classic */
#ap_sidemenu {
-fx-background-color: #1919A6;
}
#ap_sidepane {
-fx-background-color: #a8a8a8;
}
#pnl_main {
-fx-background-color: #FFFF00;
}
#pnl_spelers {
-fx-background-color: #FFFF00;
}
#pnl_moeilijkheid {
-fx-background-color: #FFFF00;
}
#pnl_thema {
-fx-background-color: #FFFF00;
}
#pnl_highscore {
-fx-background-color: #FFFF00;
}
#pnl_credits {
-fx-background-color: #FFFF00;
}
.button {
-fx-background-radius: 50;
-fx-font-family: CrackMan;
-fx-font-size: 26;
}
.button:hover {
-fx-background-color: #1919A6;
-fx-background-radius: 50;
-fx-font-family: CrackMan;
-fx-font-size: 26;
-fx-border-color: black;
-fx-border-radius: 50;
-fx-border-width: 1;
-fx-text-fill: white;
}
.button:pressed {
-fx-background-color: #1919A6;
-fx-background-radius: 50;
-fx-font-family: CrackMan;
-fx-font-size: 26;
-fx-border-color: black;
-fx-border-radius: 50;
-fx-border-width: 3;
-fx-text-fill: white;
-fx-rotate: 2;
}
.button:focused {
-fx-background-color: #1919A6;
-fx-background-radius: 50;
-fx-font-family: CrackMan;
-fx-font-size: 26;
-fx-text-fill: darkgrey;
}
xmas.css
/* X-Mas*/
#ap_sidemenu {
-fx-background-color: #165B33;
}
#ap_sidepane {
-fx-background-color: #BB2528;
}
#pnl_main {
-fx-background-color: #F8B229;
}
#pnl_spelers {
-fx-background-color: #F8B229;
}
#pnl_moeilijkheid {
-fx-background-color: #F8B229;
}
#pnl_thema {
-fx-background-color: #F8B229;
}
#pnl_highscore {
-fx-background-color: #F8B229;
}
#pnl_credits {
-fx-background-color: #F8B229;
}
.button {
-fx-background-radius: 50;
-fx-font-family: CrackMan;
-fx-font-size: 26;
}
.button:hover {
-fx-background-color: #EA4630;
-fx-background-radius: 50;
-fx-font-family: CrackMan;
-fx-font-size: 26;
-fx-border-color: #146B3A;
-fx-border-radius: 50;
-fx-border-width: 1;
-fx-text-fill: white;
}
.button:pressed {
-fx-background-color: #BB2528;
-fx-background-radius: 50;
-fx-font-family: CrackMan;
-fx-font-size: 26;
-fx-border-color: #165B33;
-fx-border-radius: 50;
-fx-border-width: 3;
-fx-text-fill: white;
-fx-rotate: 2;
}
.button:focused {
-fx-background-color: #BB2528;
-fx-background-radius: 50;
-fx-font-family: CrackMan;
-fx-font-size: 26;
-fx-text-fill: darkgrey;
}
You can do this doing this:
First, create the urls for both themes:
private String urlTheme1 = getClass().getResource("css1.css").toExternalForm();
private String urlTheme2 = getClass().getResource("css2.css").toExternalForm();
And when click on the "Change Style" button, you can do something like this:
changeStylebtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
//Remove from scene the theme1(asumming you added to your scene when your app starts)
scene.getStylesheets().remove(urlTheme1);
//Add the new theme
scene.getStylesheets().add(urlTheme2);
}
}
this will do the trick.
I want to remove the inner shadow in TextField.
Here is css.
-fx-font-size: 12px;
-fx-font-family: "Segoe UI Semibold";
-fx-pref-width:250px;
-fx-pref-height:35px;
-fx-background-radius:0px;
Try adding this line:
-fx-background-color: -fx-text-box-border, -fx-control-inner-background;
The problem is that it is NOT shadow. It is a specially decorated background. So making it transparent or putting a key which its value is transparent will work well.
.text-field {
-fx-text-box-border: transparent;
-fx-background-color: transparent;
}
.text-field:focused {
-fx-faint-focus-color: transparent; /*JavaFX 8*/
-fx-focus-color: transparent; /*JavaFX 2.2*/
}
The style code above(style.css) will generate a text field without any border and background and make it clear. By the way putting -fx-border-color or -fx-faint-color instead of transparent in -fx-background-color is completely fine since their value is transparent.
Edit: I'm adding now a little example code.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import javafx.scene.layout.Pane;
public class TextFieldDemo extends Application {
public void start(Stage primaryStage) {
TextField textField = new TextField();
textField.setPromptText("TextField");
textField.setMaxWidth(100);
textField.setLayoutX(50);
textField.setLayoutY(25);
textField.setFocusTraversable(false);
Rectangle background = new Rectangle(40, 20, 120, 40);
background.setStyle("-fx-arc-width: 40px; -fx-arc-height: 40px;-fx-fill: yellow;");
Scene scene = new Scene(new Pane(background, textField), 200, 80);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Example Output:
Example Image
I have a white border around my TextArea that I cannot get rid of
Heres the code:
textArea = new TextArea();
textArea.getStyleClass().add("textArea");
textArea.setWrapText(true);
And the css:
.textArea{
-fx-background-insets: 0 0 0 0, 0, 1, 2;
-fx-background-radius: 0;
-fx-text-fill: white;
-fx-border-color: #2a2a2a;
-fx-border-width: 0;}
.textArea .content{
-fx-background-color: #2a2a2a;
-fx-border-color: #2a2a2a;
}
Can anyone help?
This works in my test case:
.text-area, .text-area .content {
-fx-background-color: #2a2a2a ;
-fx-background-radius: 0 ;
}
.text-area {
-fx-text-fill: white ;
}
Test code:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TextAreaBorderTest extends Application {
#Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea();
BorderPane root = new BorderPane(textArea);
root.setPadding(new Insets(24));
Scene scene = new Scene(root);
scene.getStylesheets().add("text-area-border-test.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I added
.root {
-fx-background-color: black ;
}
to the CSS in order to test.
I've set the following custom row factory:
treeTblViewFiles.setRowFactory(new Callback<TreeTableView<FileModel>, TreeTableRow<FileModel>>() {
#Override
public TreeTableRow<FileModel> call(TreeTableView<FileModel> treeTableView) {
final TreeTableRow<FileModel> row = new TreeTableRow<>();
final ContextMenu rowMenu = new ContextMenu();
MenuItem removeItem = new MenuItem("Remove");
removeItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
int currentPlaylistIndex = m_playlists.indexOf(row.getTreeItem().getParent().getValue());
boolean itemRemoved = false;
if (row.getItem().getClass().equals(Song.class)) {
itemRemoved = m_playlists.get(currentPlaylistIndex).getSongs().remove(row.getItem());
m_playlists.get(currentPlaylistIndex).updatePlaylist((Song) row.getItem());
} else if (row.getItem().getClass().equals(Playlist.class)) {
itemRemoved = m_playlists.remove(row.getTreeItem().getValue());
}
TreeItem<FileModel> treeItem = row.getTreeItem();
// may need to check treeItem.getParent() is not null:
treeItem.getParent().getChildren().remove(treeItem);
treeTblViewFiles.getSelectionModel().clearSelection();
if (MyApp.DEBUG) {
System.out.println(m_playlists.size());
if (currentPlaylistIndex > -1) {
System.out.println(m_playlists.get(currentPlaylistIndex).getSongs().size());
}
}
}
});
rowMenu.getItems().add(removeItem);
row.contextMenuProperty().bind(Bindings.when(Bindings.isNotNull(row.itemProperty()))
.then(rowMenu)
.otherwise((ContextMenu) null));
return row;
}
});
and in my css I have:
/******************
* ContextMenu
******************/
.context-menu{
-fx-background-color: transparent;
}
.context-menu .menu-item{
-fx-background-image: url("styles/cm_bg.png");
-fx-background-repeat: no-repeat;
-fx-background-position: center;
-fx-background-color: transparent;
}
.context-menu .menu-item .label{
-fx-text-fill: #ababab;
-fx-font-weight: normal;
-fx-font-size: 12pt;
}
The problem is that it doesn't show the entire image(which is 220x40) but only the width that suits the 'Remove' string. The right-most part is cut.
EDIT:
Simplified version(the same result goes for a contextMenu on a Label):
ContextMenu cm = new ContextMenu();
MenuItem mi = new MenuItem("Test");
cm.getItems().addAll(mi);
lblUploader.setContextMenu(cm);
Why is that happening and how to solve it?
Thanks in advance.
Problem solved with the following .css:
.context-menu {
-fx-background-color: transparent;
-fx-min-width: <image_width>;
-fx-min-height: <image_height>;
}
Just remember to set the preferred(or min) sizes.