Problems with setting TableColumn width in FXML using CSS - css

Here is my .fxml code:
<TableColumn id="tableColumnVertical" text="">
<graphic>
<VBox>
<Label text="text"/>
</VBox>
</graphic>
</TableColumn>
Here I have simplified .css code:
#tableColumnVertical {
-fx-background-color: Lime;
-fx-min-width: 40;
-fx-max-width: 40;
}
This doesn't set width of TableColumn but sets background. Why?
I can use this code:
<TableColumn id="tableColumnVertical" text="" minWidth="40" maxWidth="40">
and it works. Why inline works and .css does not?
While writing this post I tried adding -fx-pref-width: 40; to .css and now it also works.
1) I would like know why inline works and .css does not (while background-color works)? Why after adding prefWidth it started to work?
2) Can I use both fx:id and id?
3) Also, in some SO answers I saw people advice to use styleClass to set style. When should I use styleClass?
Edit:
a TableColumn also contains the necessary properties to:
Be resized (using minWidth/prefWidth/maxWidth and width properties)
https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TableColumn.html
Not sure if this is accurate, but I decided to post this edit.

The -fx-pref-width is setting the property of the TableColumnHeader (same for -fx-min-width, see below). Setting this property via CSS is buggy: JDK-8087822.
You can use both fx:id and id. If you only set fx:id it will also be used for the id. If you set both, the id is used for CSS and the fx:id is used for injecting the instance into a controller.
You would add a style class if you want to style many nodes the same way.
Note: The following mostly deals with implementation details for JavaFX 11.0.1 (at least, I couldn't find documentation).
The problem is the difference between TableColumnBase.minWidth and Region.minWidth. The former is not styleable from CSS because it is not a StyleableProperty. The latter is and it is that property that defines the -fx-min-width CSS property.
When you do:
<TableColumn id="tableColumnVertical" text="" minWidth="40" maxWidth="40">
You are setting the minWidth property of the TableColumn using a property setter. It is not analogous to setting the CSS property.
However, the JavaFX CSS Reference Guide does document that TableColumn is part of the substructure of a TableView. This would seem to indicate you can style the column via CSS. But again, non of the properties are actually styleable; the getCssMetaData() method returns Collections.emptyList().
TableColumnBase does implement Styleable (where getCssMetaData() comes from) which means it has the following method: getStyleableNode(). The TableColumn implementation of this method, once the TableView has been displayed, returns an instance of TableColumnHeader. What this means is any CSS applied to the TableColumn is actually applied to the TableColumnHeader. It is this latter class that extends Region and thus has the styleable minWidth property. And from some testing the minWidth property of the TableColumnHeader instance is set as expected.
The problem appears to be that the minWidth of the TableColumnHeader has no affect on the TableColumn. The implementation only takes TableColumn.minWidth into account. And this unfortunately means you won't be able to set the minWidth of the TableColumn from CSS.
This behavior might be a bug.

Related

Setting attributes both in FXML and in CSS

If I am trying to set the same attribute in FXML and in a class definition in CSS, I would expect that the attribute set in FXML is considered more specific than the one from CSS.
For example, if I have a control such as
<Label styleClass="myLabel" prefHeight="40.0">
and, at the same time, a CSS definition such as
Label.myLabel {
-fx-pref-height: 100px;
}
I would expect the label to have a height of 40 px. Instead, it has 100 px.
Is there a way to make the attribute in the FXML have precedence?
In the (so far) absence of a qualified answer, I can only guess:
While one could expect that the FXML attributes have about the same specificity as an inline style definition, they haven't any relation.
The reason for this is the evaluation order: the FXML attributes are evaluated at an earlier time than and completely independent of the CSS definitions. That's why the CSS definitions completely overwrite the attribute definitions, making them obsolete.
Now it is more than a guess: Here I just found that the order of precedence is
a style from a user agent stylesheet in Application.setUserAgentStylesheet(java.lang.String)
value set from code, for example calling Node.setOpacity(double)
a style from an author stylesheet in Scene.getStylesheets() or Parent.getStylesheets()
a style from Node.setStyle(java.lang.String)
assuming that pre-setting a value in the FXML is equivalent to a value set from code.

JavaFX and css misunderstanding

In my fxml I have url for css (this fxml created via SceneBuilder)
<AnchorPane>
...
<stylesheets>
<URL value="#../styles/test.css" />
</stylesheets>
</AnchorPane>
and test.css contains
.root{
...
}
If I do preview in SceneBuider everything is ok. But in runtime this style doesn't apply. I change definition to
#AnchorPane{
...
}
and this way everynting is ok both in preview and runtime. What's wrong with .root?
Why it doesn't work
You aren't applying your css to the root node of the scene. You are applying it to the AnchorPane (the <stylesheets> element is a child of the <AnchorPane> element). Therefore if you set a .root css selector for a stylesheet only applied to the AnchorPane, the .root css selector is never going to apply because (as the documentation you quote in your comment states), "the .root style class is applied to the root node of the Scene instance".
Setting a root style class for your pane
You could make it work by setting a .root class on the AnchorPane, for example: <AnchorPane styleClass="root">. Though you may want to use a different style class name (e.g. <AnchorPane styleClass="custom-root"> and leave the .root style class to be reserved for the scene (as overriding .root might have unintended consequences).
Setting a stylesheet for the scene
The other way you could handle it is to not define your css stylesheet in your FXML, but instead to add the css stylesheet to your scene in code using:
scene.getStylesheets().add("/com/example/javafx/app/mystyles.css")
As using .root indicates that you want to change the style for the entire scene, I'd advise using this approach.
If you do so, you can still preview the scene with styles by selecting in SceneBuilder the menu item Preview | Scene Stylesheets | Add a Style Sheet....

Flex percent-width not working

I have a TitleWindow of dimensions 600 X 400. There are a bunch of VBoxes thrown in here that I want to occupy around 80% of the width of the title window in which they are contained.
But they don't seem to register the percent-width property. This is what one of the VBoxes looks like
<mx:VBox styleName="vboxes">
.vboxes
{
cornerRadius:4;
border-style:solid;
percent-width:80;
padding-left:5px;
padding-right:5px;
padding-bottom:5px;
padding-top:5px;
}
The other CSS properties such as border-style and corner-radius seem to register just fine but the percent-width property fails. As a side not, even the width style property fails in this case.
Does anybody know what's wrong here?
Bad news, width/height, percentWidth/percentHeight are not CSS attributes but properties in Flex 3.
Good news, Flex supports custom CSS, which means you can define your own style. This means you would need to override the styleChanged method of your VBox, for example:
override public function styleChanged(styleProp:String):void
{
super.styleChanged(styleProp);
if (styleProp == "percentWidth")
{
var val:Number = getStyle("percentWidth") as Number;
//set percent width logic goes here
}
}
Not every Flex property is available through CSS. In fact, I would say more are not than are. You cannot set dimensions of components via CSS for any component as far as I am aware. You are also using incorrect property names for the ones that are valid.
Please see the Adobe LiveDocs documentation of VBox styles here.

Qt: Background color on QStandardItem using StyleSheet

I have a class that inherits QStandardItem and I put the elements in a QTreeWidget. The class receives notifications from the outside and I want to change the background color of the item based on what happened.
If I do not use stylesheets, it works just fine, like this:
void myClass::onExternalEvent()
{
setBackground(0, QColor(255,0,0)));
}
However, as soon as I put a stylesheet on the QTreeWidget, this has no effect : the stylesheet seems to override the setBackground() call.
So I tried :
void myClass::onExternalEvent()
{
this->setStyleSheet("background-color: red");
}
but this is probably all wrong, it changed the color of some other element on my screen, not sure why.
Does anyone have an idea on how I can alter the background color like with setBackgroundColor but still be able to use stylesheet on my QTreeWidget?
Palettes propagate to the children of a widget, and it's bad to mix and match style-sheet controls and native controls (I do not have a citation for the latter handy, but I have read it in the QT docs somewhere).
That being said, try setting setAutoFillBackground(false) on your QStandardItem derived class.
EDIT: Sorry - also, are you specifying the QTreeWidget in the stylesheet or just setting "background-color:"? If you specify the QTreeWidget only in the stylesheet that might take care of it as well.
QTreeWidget { background-color: white; }
But I think you still have to set the autoFillBackground(false).

Flex: How to access properties of component in dynamic creation?

I have a component which is created dynamically. I want to access the properties on it.
for example i create a vbox and i want to access the text font or gap of the component
var MyVBox: VBox = new VBox;
MyPanel.addChild(MyVBox);
How should it be done?
All properties and methods are accessed with "." (dot) notation.
Example:
myVBox.width = 400;
Styles are set using the setStyle() method. In your case that would be
myVBox.setStyle("fontFamily", "arial");
myVBox.setStyle("verticalGap", 20);
Check the docs at http://livedocs.adobe.com/flex/3/langref/ for the available properties and styles of each component.
The thing to remember when using ActionScript instead of MXML is that the style properties are not accessed as properties on the object but through the getStyle("propertyName") method. Font is a style for example.

Resources