Help me with JavaFX CSS. I need to create a border width of 2 pixels:
Up pixel - #000
Down pixel - #5d5c5e
I think I need to use a linear-gradient, but I don't know how to do it.
It's not really clear what you're asking; but the standard way to put a border on something in JavaFX is to use "nested backgrounds". This technique involves creating different color backgrounds, one drawn over the other, with different insets so that you get the effect of a border.
For example, the following CSS in an external CSS file will give a four-pixel black (#000) border around a four-pixel gray border (around the default background color defined in modena.css). (I used wider borders to make the effect clearer.)
style.css:
.root {
-fx-background-color: #000, #5d5c5e, -fx-background ;
-fx-background-insets: 0, 4, 8 ;
}
This works by drawing a black background with no insets, and then drawing a gray background with 4 pixel insets over it (leaving four pixels of the black background visible), and finally drawing a background with the default color over the top of that, with 8 pixels insets (so four pixels of the gray border is visible).
Here's a quick test:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class BackgroundTest extends Application {
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new StackPane(new Label("Nested backgrounds")), 400, 400);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
which results in
This variation
.root {
-fx-background-color: #000, #5d5c5e, -fx-background ;
-fx-background-insets: 0, 4 0 0 0, 4 0 4 0 ;
}
leaves four pixels of the black background visible at the top, and four pixels of the gray background visible at the bottom:
And this has black at the top, grey at the bottom, and a linear gradient fading from black to grey down the sides:
.root {
-fx-background-color: #000, #5d5c5e, linear-gradient(to bottom, #000, #5d5c5e), -fx-background ;
-fx-background-insets: 0, 4 0 0 0, 4 0 4 0 , 4;
}
You need to add a border for your first border, then a box-shadow for your remaining borders:
.doubleBorder{
border: 1px solid #5d5c5e;
box-shadow:
1px 1px #000,
-1px 1px #000,
1px -1px #000,
-1px -1px #000;
}
Related
Currently, I have a button with the following CSS:
Button {
-fx-text-fill: -fx-color-text;
-fx-font: 15pt "Raleway SemiBold";
-fx-background-color: -fx-color-theme;
-fx-background-insets: 0, 0, 0, 0, 0, 1, 2;
-fx-background-radius: 0;
-fx-padding: 4px 20px;
/* -fx-effect: innershadow(two-pass-box, white, 2, 0.2, 0, 0); */
-fx-border-insets: 0;
-fx-border-color: black;
}
And it looks like this:
And I'm trying to add an inner shadow to the button. I want the border to show on the outside of this button, which should result in something like this:
I made that in Swing. However, when I try and apply my inner shadow, it draws on top of my border, as shown:
I've tried setting the border insets to -1 (because there isn't an insets property for the effect), but that just moved the effect with it:
My question is: What can I do to ensure that I can see my border around the outside, but keep my effect on the inside?
EDIT: I'm pretty sure that this is a bug in OpenJFX and I've submitted a bug report. Here's some quick code you can use to reproduce the issue:
public class App extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Region example = new Region();
example.setMaxWidth(100);
example.setMaxHeight(100);
example.setEffect(new InnerShadow(BlurType.GAUSSIAN, Color.RED, 10, 0.04, 0, 0));
example.setStyle("-fx-background-color: white; -fx-border-color: BLUE; -fx-border-width: 5px;");
StackPane container = new StackPane();
container.setStyle("-fx-background-color: black;");
container.setAlignment(Pos.CENTER);
container.getChildren().add(example);
Scene scene = new Scene(container, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I think the border is getting blended with the effect which is applied. And as you are pretty sure that it could be a bug in JavaFX rendering, below is one way to get it look the way you want.
You can consider the below solution as when you think like "I definitely want this look only !!" kind of thing :)
The idea is, instead of setting the effect, you paint the effect manually.
.button {
-fx-text-fill: #FFFFFF;
-fx-font: 15pt "Raleway SemiBold";
-fx-background-color: #000000, #720D4D, #D03A9A, #DD70B6, #B01378, #CC2C93, #D03A9A, #C81688;
-fx-background-insets: 0, 1, 1 2 2 1, 1 2 2 2, 2, 2 3 3 2, 2 3 3 3, 3;
-fx-background-radius: 0;
-fx-padding: 4px 20px;
-fx-border-insets: 0px;
-fx-border-radius: 0px;
-fx-border-width: 0px;
}
And the output is as below [ignore the font as I dont have the .tff ;)]:
And a closer look for verification purpose:
This may not be an actual solution, but can be one alternate (least case).
I'm trying to figure out the CSS for highlighting the top of a TableRow. I'm using this for reordering rows so that anyone reordering them can tell where it will be inserted. Currently I've only been able to draw a rectangle around the row, but I just want the top line of that rectangle.
.table-row-cell.drag {
-fx-focus-color: #00a9d3;
-fx-faint-focus-color: #00a9d322;
-fx-highlight-fill: -fx-accent;
-fx-background-color:
-fx-focus-color,
-fx-control-inner-background,
-fx-faint-focus-color,
linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background);
-fx-background-insets: -0.2, 1, -1.4, 3;
-fx-background-radius: 3, 2, 4, 0;
}
You could specify different -fx-background-insets for the sides. If one color should only appear on one side, the insets of the next color match the insets for the mark color except for the side that should be colored.
Furthermore I recommend using PseudoClass instead of a style class, since this way you don't need to make sure to not add a class multiple times.
final PseudoClass mark = PseudoClass.getPseudoClass("mark");
...
boolean marked = ...
row.pseudoClassStateChanged(mark, marked);
The following CSS is a bit simplified, but it should demonstrate the approach:
.table-row-cell:mark {
-fx-background-color: -fx-table-cell-border-color, red, -fx-background;
/* show red highlight of size 2 at the top */
-fx-background-insets: 0, 0 0 1 0, 2 0 1 0;
}
How can I set the z-index for the selection in a TableView. Some rows are conditional formatted and the formatting is overlying the Selection.
Screenshot of what I mean. Take a look at the last row!
Here is my RowFactory:
public void createRowFactory(){
final String CSS_OUTOFSTOCK = "outofstock";
mainTableView.setRowFactory(row -> {
return new TableRow<Artikel>(){
#Override
protected void updateItem(Artikel article, boolean empty){
super.updateItem(article, empty);
getStyleClass().removeAll(CSS_OUTOFSTOCK);
if(article != null){
if(article.mengeLagerProperty().get() == 0){
getStyleClass().add(CSS_OUTOFSTOCK);
}
}
}
};
});
}
And that's my CSS
.outofstock{
-fx-background-color: rgba(255, 159, 160, .4);
}
Here's how the default CSS from modena works for table rows and table cells:
The background color of a table row is set as a nested background depending on two looked-up colors:
.table-row-cell {
-fx-background-color: -fx-table-cell-border-color, -fx-background;
}
The insets are set as
.table-row-cell {
-fx-background-insets: 0, 0 0 1 0;
}
so the effect of this is that there is a 1-pixel border using -fx-table-cell-border-color along the bottom, and the rest of the row is colored in -fx-background.
-fx-background itself is defined as
.table-row-cell {
-fx-background: -fx-control-inner-background;
}
and overridden for odd rows with
.table-row-cell:odd {
-fx-background: -fx-control-inner-background-alt;
}
to give the striped effect.
Individual cells have no background color (so the background color of the row is visible), but they define a 1-pixel border on the right of each cell with
.table-cell {
-fx-background-color: null;
-fx-border-color: transparent -fx-table-cell-border-color transparent transparent;
}
When the row is selected, the looked-up color -fx-background is modified to take the value of a different looked-up color (essentially the bright blue, by default). Similarly the border color of the cell is modified to a lighter version of that color:
.table-row-cell:filled:selected {
-fx-background: -fx-selection-bar;
-fx-table-cell-border-color: derive(-fx-selection-bar, 20%);
}
Since you just change the background color of the table row directly, you lose the "nested background" (i.e. the border at the bottom of the row). The individual cells still draw their borders, which are either an off-white (if the row is not selected), or a blue (if the row is selected).
So you probably want to redefine each of the key looked-up colors for your CSS class, to inherit all the basic functionality (selection, borders, etc). For example:
.outofstock {
-fx-control-inner-background: rgba(255, 159, 160, .4);
-fx-selection-bar: rgba(255, 79, 80, .4);
}
You could also redefine -fx-table-cell-border-color if you want, though the default is quite neutral: #ececec.
I don't really understand the accepted answer despite reading it 1000x. It's overly complicated and fails to provide the exact css to get this to work. -fx-control-inner-background does nothing to set the background color of a cell when a custom cell factory is defined.
Here is simple css that I found works.
.table-row-cell:selected .outofstock {
-fx-background-color: -fx-accent;
-fx-border-color: -fx-accent;
}
-fx-accent is defined in .root (checkout javafx caspian.css). Its the color that defines what the table row selection is.
I'm trying to get an iTunes like progress bar that is very small (height of about 5px) but I can't seem to go any lower than 19 or 20px.
I tried setting -fx-max-height with no avail, also on the surrounding pane. Note that this value does indeed change the height - I just can't get it less than about 20px.
Any ideas how to achieve that? I'd like to avoid using a plain rectangle for indicating progress because of loss of semantic and support of assistive technology.
Thanks.
The ProgressBar default styling is the reason why you can't reduce its height.
As we can see in the modena.css file for the progress-bar CSS selector:
.progress-bar > .bar {
-fx-background-color: linear-gradient(to bottom, derive(-fx-accent, -7%), derive(-fx-accent, 0%), derive(-fx-accent, -3%), derive(-fx-accent, -9%) );
-fx-background-insets: 3 3 4 3;
/*-fx-background-radius: 0.583em; *//* 7 */
-fx-background-radius: 2;
-fx-padding: 0.75em;
}
two CSS properties are responsible for this: -fx-padding for the height of the blue inner bar and -fx-background-insets for the height of the surrounding gray bar.
So you can customize this selector as you need. For instance, with these properties you will have 5 pixels height:
.progress-bar > .bar {
-fx-background-insets: 1 1 2 1;
-fx-padding: 0.20em;
}
No need for height settings on your code:
#Override
public void start(Stage primaryStage) {
ProgressBar pb = new ProgressBar(0.4);
pb.setPrefWidth(200);
StackPane root = new StackPane(pb);
Scene scene = new Scene(root, 300, 200);
scene.getStylesheets().add(getClass().getResource("root.css").toExternalForm());
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
I'm attempting to style the borders of my context menus in JavaFX with CSS.
The Problem
I want a 1 pixel, solid black line as the border of the context menu. Instead, I'm getting a 2 pixel, solid black line as the border of the context menu.
Here are two images showing the pixel border.
100%
1000%
Clearly, there are 2 pixels being rendered instead of 1 pixel for the border.
CSS
I'm setting the border with the following CSS:
.context-menu {
-fx-skin: "com.sun.javafx.scene.control.skin.ContextMenuSkin";
-fx-background-color: red;
-fx-background-radius: 0;
-fx-background-insets: 0;
-fx-effect: null;
-fx-border-width: 1; /* I also tried 1px here */
-fx-border-color: black;
-fx-border-style: solid outside line-cap square;
-fx-padding: 0;
}
I also set the child nodes to transparent borders and backgrounds just to rule out that they were responsible:
.context-menu .menu-item,
.context-menu .menu-item .label {
-fx-background-color: transparent;
-fx-border-color: transparent;
}
Question(s)
Why am I getting a 2 pixel border, instead of a 1 pixel border?
How can I get a 1 pixel border, instead of this 2 pixel border?
There are a couple of answers already on StackOverflow that explain why the strokes can't seem to render a 1px border all of the time:
JavaFX graphics “blurred” or anti-aliased? (No effects used)
What are a line's exact dimensions in JavaFX 2?
The best workaround I've found for this issue is to not use borders at all. Instead, I use multiple backgrounds and -fx-background-insets to simulate a border:
.context-menu {
-fx-skin: "com.sun.javafx.scene.control.skin.ContextMenuSkin";
-fx-background-color: black, red;
-fx-background-insets: 0, 1;
}
That's all it takes for a clean, 1 pixel, hard border