Is it possible to override a JavaFX CSS definition in code?
For example, in my CSS file I defined a button's height as follows:
.button {
-fx-pref-height: 30px;
}
When I try to override this height for some button in code...
Button button = new Button();
button.setPrefSize(100, 50); // width, height
...the button still has a height of 30 pixels.
There are two solutions:
Make sure that button.setPrefSize(100, 50); // width, height is called after the Button became visible.
Use Bindings to force its size (CSS does not overwrite bound values), for example: button.prefHeightProperty().bind(new SimpleDoubleProperty(60));
Related
I have a class that extends FlowPanel. I add a DataGrid widget and a Grid widget like this:
dataGrid.setWidth("100%");
dataGrid.setHeight("100%");
grid.setWidth("100%");
grid.setHeight("100%");
this.add(dataGrid);
this.add(grid);
this.setWidth("100%");
this.setHeight("100%");
Only the DataGrid widget appears. I've tried both switching from FlowPanel to VerticalPanel and wrapping the Grid in a FlowPanel, with no joy. I tried putting the DataGrid and the Grid into a 2 row, 1 column Grid and that didn't display anything. This is GWT 2.6.0 on Safari.
I suspect that I have a misunderstanding of what setHeight() and setWidth() are doing in this case, but I'm not sure. Is there any way to see what GWT thinks it's doing in terms of layout?
Thanks.
You tell DataGrid to take all available space inside the FlowPanel. Then you tell Grid widget to do the same. The result is that your Grid has a height of zero, since there was no space left for it after the DataGrid took 100% of the FlowPanel height.
You either have to use "50%" for heights, or make your DataGrid fixed size ("100px") and then tell the Grid to take the rest. The easiest way to achieve that is to use a LayoutPanel, and then, for example:
layoutPanel.setWidgetTopHeight(dataGrid, 0, Unit.PX, 100, Unit.PX);
layoutPanel.setWidgetTopBottom(grid, 100, Unit.PX, 0, Unit.PX);
EDIT:
This is the code that I use to resize the DataGrid:
public void resize(final boolean addHeader, final boolean addFooter) {
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
// 37 is the height of header and footer based on my CSS
int height = addHeader ? 37 : 0;
if (addFooter) {
height += 37;
}
for (int i = 0; i < getRowCount(); i++) {
height += getRowElement(i).getOffsetHeight();
}
setHeight(height + "px");
}
});
}
If you use this approach, simply add your DataGrid to the FlowPanel, and then add your Grid to the FlowPanel. Call resize() on the DataGrid, and do not set any height or width on your DataGrid or Grid.
For a finer control look at the flex-box layout model. It is supported in all modern browsers.
#Patrick, regarding your comment, I use DockLayoutPanel to take care of resizing for me:
DockLayoutPanel gridPanel = new DockLayoutPanel(Unit.PCT);
gridPanel.addNorth(dataGrid, 60); //datagrid will take 60% of the panel
gridPanel.add(grid); //grid will take the remaining space
I have a QDockWidget with a transparent background, but I would like to change the background color or background image when it is floating. It doesn't look like the qt style sheets have a pseudo state to tell you whether or not they are floating, so I'd like to know: is this possible to do?
Found the solution. Add the following connection in the code:
connect(knobDock, &QDockWidget::topLevelChanged, [&] (bool isFloating)
{
if (isFloating)
{
setAttribute(Qt::WA_TranslucentBackground, false);
setAttribute(Qt::WA_NoSystemBackground, false);
}
});
This will cause the dock widgetto use whatever background is specified in the stylesheet when the dock is floating, but it will be transparent (i.e. show the mainwindow background) when it's docked.
You can use custom properties to do this.
Thanks #phyatt for link to Dynamic Properties and Stylesheets.
To declare custom property in your custom class you can write in .cpp:
setProperty("customPropertyName", 1);
or in .h (don't forget to define and implement used get/set access methods too):
Q_PROPERTY( int customPropertyName, READ getCustomPropertyName, WRITE setCustomPropertyName);
And in your global stylesheet file you can use the state of your custom property as following:
.YourClass[customPropertyName="1"] {
background-color: transparent;
}
.YourClass[customPropertyName="2"] {
background-color: black;
}
Also it's needed to reload stylesheet of the object instance after your set new property value, because stylesheets are not recalculated automatically:
object->style()->unpolish(tstFrame);
object->style()->polish(tstFrame);
object->update();
or:
object->setStyleSheet("/* */");
I have these buttons with different size:
Image
How I can make all buttons with same with size?
It depends on layout where the button is located. For example, if you add all the buttons into GridPane or BorderPane, you have to specify each button width to correspond to certain variable. In the following example I wrap all buttons inside VBox, set VBox preference width and tie up all buttons minimum width to it:
VBox vBox = new VBox();
vBox.setPrefWidth(100);
Button btn1 = new Button("Short");
Button btn2 = new Button("Super Long Button");
btn1.setMinWidth(vBox.getPrefWidth());
btn2.setMinWidth(vBox.getPrefWidth());
vBox.getChildren().addAll(btn1, btn2);
It is also worth to mention that there are two ways to specify the button size. You can do it in the java code or specify it in javafx .fxml file. The above method is an example for java code implementation.
You can also unclamp a button's maximum dimensions so it will grow to fill the available space (unlike most nodes, by default a button node has it's max size clamped to it's preferred size so it doesn't usually grow to fill available space). An Oracle tutorial on Tips for Sizing and Aligning Nodes explains this in more detail.
VBox vBox = new VBox();
Button btn1 = new Button("Short");
Button btn2 = new Button("Super Long Button");
btn1.setMaxWidth(Double.MAX_VALUE);
btn2.setMaxWidth(Double.MAX_VALUE);
vBox.getChildren().addAll(btn1, btn2);
using css you can override the preferred width of all buttons like
.button {
-fx-pref-width: 200px;
}
or create your own style class for certain button groups and add the style to the button like:
css:
.my-special-button {
-fx-pref-height: 28px;
-fx-pref-width: 200px;
}
and then set the style to your button with either
fxml:
styleClass="my-special-button"
or in java
myButton.getStyleClass().add("my-special-button");
I have a FocusPanel that when gets clicked adds new Elements/Widgets to itself making its height increase. Note, that there is no explicit change of height in the css of the FocusPanel, the height just increases as the result of adding new elements inside the panel
I would like that increase in height to occur through a smooth transition but I am not sure how to achieve it.
I tried applying css transition: height 2s; to the FocusPanel and also to all the other Elements/Widgets that I add to it. But it does not seem to work, there is no transition at all. I assume it is because the height does not increase as a result of me changing the css property but rather by just adding more elements to a container.
What is the right way to achieve a smooth transition of height when adding new elements programatically to a Panel? Thanks!
PS. A good example of what I would like to achieve is the way twitter handles the transition of the panel height when one clicks on a twit.
CSS animations only work if you set the height to fixed values.
A way is to create your own implementation of panel, and override the add method, so as it takes care of computing height and setting it before and after animation time.
As #fascynacja points in its comment, I would go with gwtquery to do that, because of different reasons, but main one is that it is a lightweight library developed in gwt which allows you doing a lot of things with few code lines.
Here you have an example of a panel doing what you want using gquery animations.
import static com.google.gwt.query.client.GQuery.*;
[...]
// Create your own implementation of a panel
public static class MyFlowPanel extends FlowPanel {
// The GQuery object for this panel
GQuery $this = $(this);
// Override the add method so as each time it is called, we run an animation
// You can do the same with the remove method.
#Override
public void add(Widget w) {
// Compute the actual height
int hInitial = $this.height();
// Set height to auto before adding the new child.
$this.height("auto");
// Add the new widget to panel
super.add(w);
// Compute the new height
int hFinal = $this.height();
// Use Gquery to .animate the panel from the old to the new height
// You could replace this with css3 transitions
$this.height(hInitial)
.stop(true)
.animate("height: " + hFinal, 2000);
};
};
public void onModuleLoad() {
// Create your panel, and use it as usual in GWT
final FlowPanel myFlowPanel = new MyFlowPanel();
RootPanel.get().add(myFlowPanel);
// Set some css properties to your panel. You could set these in your style-sheet.
$(myFlowPanel).css($$("border: 1px solid grey; border-radius: 8px; background: #F5FFFA; width: 500px; padding: 8px"));
// Add 10 labels to the panel in periodes of 1000 ms
Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
int c = 10;
public boolean execute() {
if (c-- > 0) {
myFlowPanel.add(new Label(c + " Lorem ipsum dolor sit amet, consectetur adipiscing elit."));
return true;
}
return false;
}
}, 1000);
}
in MXML, there is a Button class which you can instantiate like so:
<mx:Button id="something />
but what if you wanted to dynamically build this in AS3 and add it to the Flex app dynamically, without the use of components (just AS3) and then modify Flex's styles, for example, here you access the Button's properties and set them:
var btn:Button = new Button();
btn.height = 50;
btn.width = 75;
btn.x = 100;
btn.y = 40;
but how would you go about changing the Style, for example:
btn.downSkin = "something";
btn.color = "0xfffff";
I'm sort of starting to lean towards making a flex component in MXMLand than just making it visible true/false, but i like the fact that i create an object in AS3 and then destroy it when I don't need it anymore, than create it again once needed.
This page has a solution to the problem:
Setting and getting Style attributes in ActionScript:
// setting a components styleName to reference a CSS class
component.styleName = "highlight";
// set a Button's background color and font size
submitButton.setStyle( "backgroundColor", 0x000000 );
submitButton.setStyle( "fontSize", 14 );
// get a TextArea's font family and color
textArea.getStyle( "fontFamily" );
textArea.getStyle( "color" );
You could use CSS, either inline or as an external CSS file. That way you don't have to set the properties manually every time you create a button.
/* CSS file */
Button {
borderColor: red;
}
Check out Styling Button control, by Peter deHaan (also read the comments in that post).