Changing the NavigationViewContentMargin dynamically, which determines the top margin of the NavigationView, does not change the appearance of the NavigationView dynamically.
Is there a way to dynamically change the top margin of NavigationView from the code?
top margin of NavigationView
You need to get the target Grid "NavigationViewContentMargin" is applied to. This Grid is named "ContentGrid".
The tricky part is that NavigationViews have 2 Grids with the name "ContentGrid". The "ContentGrid" we need is the one that is inside a Grid with the name "ContentRoot". BTW, the other one is inside "Settings".
First, we need to get the "ContentRoot" Grid, then get the "ContentGrid" we need.
Check this example:
MainWindow.xaml
<Window
x:Class="NavigationViewTests.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.UI.Xaml.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:NavigationViewTests"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid ColumnDefinitions="*,Auto">
<Grid.Resources>
<Thickness x:Key="NavigationViewContentMargin">0,48,0,0</Thickness>
</Grid.Resources>
<NavigationView
x:Name="NavigationViewControl"
Grid.Column="0"
IsBackButtonVisible="Visible">
<TextBlock Text="Content" />
</NavigationView>
<StackPanel Grid.Column="1">
<NumberBox
x:Name="NavigationViewContentGridTopMarginNumber"
Header="NavigationView Top Margin"
ValueChanged="NumberBox_ValueChanged" />
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Linq;
namespace NavigationViewTests;
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
this.NavigationViewControl.Loaded += (s, e) =>
{
this.NavigationViewContentGrid = GetNavigationViewContentGridInsideContentGrid();
if (this.NavigationViewContentGrid is not null)
{
this.NavigationViewContentGridTopMarginNumber.Value = this.NavigationViewContentGrid.Margin.Top;
}
};
}
private Grid? NavigationViewContentGrid { get; set; }
private Grid? GetNavigationViewContentGridInsideContentGrid()
{
Grid? contentRoot = this.NavigationViewControl
.FindChildrenOfType<Grid>()
.Where(x => x.Name == "ContentRoot")
.FirstOrDefault();
return contentRoot?
.FindChildrenOfType<Grid>()
.Where(x => x.Name == "ContentGrid")
.FirstOrDefault();
}
private void NumberBox_ValueChanged(NumberBox _, NumberBoxValueChangedEventArgs args)
{
if (NavigationViewContentGrid is not null)
{
Thickness currentMargin = this.NavigationViewContentGrid.Margin;
this.NavigationViewContentGrid.Margin = new Thickness(
currentMargin.Left,
args.NewValue,
currentMargin.Right,
currentMargin.Bottom);
}
}
}
I have this css file which sets the default font size and type in JavaFX application:
.root {
-fx-font: 13px Tahoma;
}
scene.getStylesheets().add(getClass().getResource("/styles/Styles.css").toExternalForm());
I want to update the size and the font type from the Java code dynamically of the root component (all components). How I can do this?
Note:
This code updates the Font type and size of all components into the JavaFX application.
Please consider taking a look at the official JavaFX documentation. There you find the code example which answers your question:
Text t = new Text("That's the text");
t.setFont(Font.font ("Verdana", 20));
UPDATE
In your application controller get an instance of your root pane, e.g. AnchorPane and use the setId("") function to set new style for the whole pane (my actionChange is connected with a button on the pane, which triggers the event/change):
public class AppController implements Initializable {
#FXML
private AnchorPane mainPane;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
}
#FXML
public void actionChange() {
mainPane.setId("fancytext");
}
}
When pressing the button, the style for the pane is changed. I just used the font-size as an example. Before, you need to specify the new style in your CSS file:
.root {
-fx-font: 12px Tahoma;
}
#fancytext {
-fx-font: 20px Tahoma;
}
That's before:
That's after the button was pressed:
When user presses a button in my JavaFX2.2 UI, a dark blue halo appears to show it was clicked. During the course of events, my program may want to 'unclick' it to show it is no longer selected.
I expected a button.setSelected(false); I remember Swing used to have this, but there isn't such a call in JavaFx.
This article discusses drop shadows but I want to simply use the same appearance used when a button is clicked which isn't really a drop shadow. setEffect(new DropShadow())
Using setStyle() is ok, but what values to use?
I think for your description, that you actually want a ToggleButton rather than a standard Button.
There is a nice Oracle tutorial on ToggleButtons.
Addressing Items from the Question
dark blue halo appears to show it was clicked
The blue halo is actually a focus ring indicating that a control has focus.
To focus a control, you can invoke the requestFocus method.
During the course of events, my program may want to 'unclick' it to show it is no longer selected.
To remove focus from a control, you can call requestFocus on another control to focus on that control instead.
I expected a button.setSelected(false);
To have a button which can toggle between a selected and unselected state, use a ToggleButton. A ToggleButton has a setSelected method.
setEffect(new DropShadow()) Using setStyle() is ok, but what values to use
css style values for drop shadow effects are define in the JavaFX CSS Reference Guide.
It is visually equivalent to define the drop shadow effect in code via setEffect or via css with setStyle or applying a style class from a stylesheet. Of the three approaches, I would never recommend the setStyle approach, but only the css from stylesheet or the setEffect from code approach.
Related
Note there is an additional related property - armed:
Indicates that the button has been "armed" such that a mouse release will cause the button's action to be invoked. This is subtly different from pressed. Pressed indicates that the mouse has been pressed on a Node and has not yet been released. arm however also takes into account whether the mouse is actually over the button and pressed.
A button in an armed state has a slightly different look than one which is not in an armed state. Most programs never need to interact with the armed state of buttons.
Sample for styling the selected state
The standard way to differentiate a selected ToggleButton from one which is not Selected is to darken it to give it a depth style effect and make it appear further away when it has been pushed. Here is the standard toggle button css for JavaFX 2.2:
.toggle-button:selected {
-fx-background-color:
-fx-shadow-highlight-color,
linear-gradient(to bottom, derive(-fx-color,-90%) 0%, derive(-fx-color,-60%) 100%),
linear-gradient(to bottom, derive(-fx-color,-60%) 0%, derive(-fx-color,-35%) 50%, derive(-fx-color,-30%) 98%, derive(-fx-color,-50%) 100%),
linear-gradient(to right, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0) 10%, rgba(0,0,0,0) 90%, rgba(0,0,0,0.3) 100%);
-fx-background-insets: 0 0 -1 0, 0, 1, 1;
/* TODO: -fx-text-fill should be derived */
-fx-text-fill: -fx-light-text-color;
}
You can override this default behavior by defining your own stylesheet that provides an alternate definition for the selected state. The sample below will ensure that the selected state display is much more subtle than the standard, only darkening the selected state color a small fraction rather than a lot.
Unselected
Selected
Associated css:
/**
* file: colored-toggle.css
* Place in same directory as ColoredToggle.java.
* Have your build system copy this file to your build output directory.
**/
.root {
-fx-background-color: cornsilk;
-fx-padding: 10;
}
.toggle-button {
-fx-color: paleturquoise;
}
.toggle-button:selected {
-fx-background-color:
-fx-shadow-highlight-color,
linear-gradient(to bottom, derive(-fx-color,-22%) 0%, derive(-fx-color,-15%) 100%),
linear-gradient(to bottom, derive(-fx-color,-15%) 0%, derive(-fx-color,-10%) 50%, derive(-fx-color,-8%) 98%, derive(-fx-color,-12%) 100%);
}
.toggle-button:selected:focused {
-fx-background-color:
-fx-focus-color,
linear-gradient(to bottom, derive(-fx-color,-22%) 0%, derive(-fx-color,-15%) 100%),
linear-gradient(to bottom, derive(-fx-color,-15%) 0%, derive(-fx-color,-10%) 50%, derive(-fx-color,-8%) 98%, derive(-fx-color,-12%) 100%);
}
Source file:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ColoredToggle extends Application {
public static void main(String[] args) { Application.launch(ColoredToggle.class, args); }
#Override public void start(Stage stage) {
ToggleButton visibilityControl = new ToggleButton("Winterfell");
VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER);
layout.getChildren().setAll(visibilityControl);
layout.getStylesheets().add(getClass().getResource("colored-toggle.css").toExternalForm());
stage.setScene(new Scene(layout));
stage.show();
}
}
From a css stylesheet this command also works. There is no need for a toggle button. Once you press a different button, focus changes to the new one.
.button:focused{
-fx-background-color: gray;
I'm using JavaFx13, I used css to achieve my active button state. Here is my code(Only some part).
Controller:
#FXML
private BorderPane bp;
#FXML
private Button mnu_list;
#FXML
private Button mnu_address;
private Button activeMenu;
// This is my Constructor
public DashboardController() {
this.activeMenu = null;
}
public void initialize() {
mnu_list.setOnMouseClicked(
actionEvent -> this.setActiveMenu(mnu_list, ListController.class)
);
mnu_address.setOnMouseClicked(
actionEvent -> this.setActiveMenu(mnu_address, AddressController.class)
);
}
private void setActiveMenu(Button s, Class c) {
if (c != null) {
// I'm using FXWeaver. Here I'm setting a new fxml to borderpane.
bp.setCenter(this.fxWeaver.loadView(c));
}
if (this.activeMenu != null) {
this.activeMenu.getStyleClass().removeAll("active");
}
s.getStyleClass().add("active");
this.activeMenu = s;
}
CSS:
.btn_menu{
-fx-background-radius: 0px;
-fx-cursor: hand;
-fx-alignment: center-left;
}
.btn_accent_color{
-fx-background-color: #7c4dff;
-fx-text-fill: #FFFFFF;
}
.btn_accent_color.active{
-fx-background-color: #aa3bfe;
-fx-text-fill: #FFFFFF;
}
Note: In .fxml file - I have set all menu button class as btn_menu, btn_accent_color.
Info: Here I'm toggleing (adding and removing) a css-class to a button. (Same as we do in Website using js)
I have several questions how to improve this Primefaces chart.
This is the source code:
<h:form>
<p:barChart id="basic" value="#{DashboardController.categoryModel}" legendPosition="ne"
title="Accounts and Groups" min="0" max="200" style="height:400px"
shadow="true" barPadding="60"/>
</h:form>
import org.primefaces.model.chart.CartesianChartModel;
import org.primefaces.model.chart.ChartSeries;
#Named("DashboardController")
#SessionScoped
public class Dashboard implements Serializable
{
/*
* Call the Oracle JDBC Connection driver
*/
#Resource(name = "jdbc/Oracle")
private DataSource ds;
private CartesianChartModel categoryModel;
public Dashboard()
{
createCategoryModel();
}
public CartesianChartModel getCategoryModel()
{
return categoryModel;
}
private void createCategoryModel()
{
categoryModel = new CartesianChartModel();
// Active Accounts
ChartSeries ActiveAccounts = new ChartSeries();
ActiveAccounts.setLabel("Active Accounts");
ActiveAccounts.set("Active Accounts", 120);
categoryModel.addSeries(ActiveAccounts);
// Blocked Accounts
ChartSeries BlockedAccounts = new ChartSeries();
BlockedAccounts.setLabel("Blocked Accounts");
BlockedAccounts.set("Blocked Accounts", 120);
categoryModel.addSeries(BlockedAccounts);
// Active Groups
ChartSeries ActiveGroups = new ChartSeries();
ActiveGroups.setLabel("Active Groups");
ActiveGroups.set("Active Groups", 120);
categoryModel.addSeries(ActiveGroups);
// Blocked Groups
ChartSeries BlockedGroups = new ChartSeries();
BlockedGroups.setLabel("Blocked Groups");
BlockedGroups.set("Blocked Groups", 120);
categoryModel.addSeries(BlockedGroups);
}
}
Can you tell me how I can change the color of the chart size, also the color of "Accounts and Groups"?
I also want to ask you how I can add names below every column? Now I have only one name "Active Accounts". I want to name the columns individually.
Best wishes
P.S I tested this code into the JSF header but it's not working:
<script type="text/css">
.jqplot-title{
color:red;
}
</script>
P.S 2 Only the label of the chart is changed
Use the seriesColors attribute of <p:barChart
like this seriesColors="000000, FFFFFF, 2288AA"
about the title and the axis color, use this:
.jqplot-title{
color: #FF0000;
}
.jqplot-xaxis-label{
color: #FF0000;
}
.jqplot-yaxis-label{
color: #FF0000;
}
I have the wrapped into my own faces component. Right now we found that when adding several messages the are of the expands moving the actual page components to the very far bottom of the page.
It's not viable to change the 300 pages we have on this system. Tried to find way to limit the height of the <h:messages> by CSS with no success.
The bright side is that when adding messsages to the current faces context is required that caller uses a method from the super class. I was able to limit the messages, but my control variables are not reseting when the page is reloaded.
My question, is there any other way to limit the messages from faces context?
(using javaEE5, JSF 1.1, tomcat5)
The h:messages renders by default an unordered list (<ul><li>). So to limit the height using CSS, you need to set a fixed height on the <ul> element and apply an overflow on y-axis it so that the users will still be able to scroll through it.
Basically:
.messages {
height: 100px;
overflow-y: scroll;
}
Apply it using styleClass attribute:
<h:messages styleClass="messages" />
Here is what I did to workaround the problem. As I said on my original post the component I use is wrapped. I overwrote the encodeBegin and encodeEnd to wrap the original h:messages with a div element:
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlMessages;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.ValueBinding;
public class UIMessages extends HtmlMessages implements LayoutComponent {
public void encodeBegin(FacesContext context) throws IOException{
ResponseWriter writer = context.getResponseWriter();
layout.startRow(writer);
layout.startData(writer);
writer.startElement("div", this);
writer.writeAttribute("style", "overflow:auto; border:0px solid; max-height:100px;", null);
super.encodeBegin(context);
}
public void encodeEnd(FacesContext context) throws IOException{
ResponseWriter writer = context.getResponseWriter();
super.encodeEnd(context);
writer.endElement("div");
layout.endData(writer);
layout.endRow(writer);
}
}