JavaFX 11 Set Color on a PhongMaterial with fxml - fxml

I have been endeavouring to implement 3D shapes in JavaFX using fxml, but have encountered difficulty in specifying the static predefined colors in the Color class on a PhongMaterial.
As an example, a code snippet for a Box object is:
<Box fx:id="box" width="100" height="200" depth="300">
<material>
<PhongMaterial >
</PhongMaterial>
</material>
</Box>
If anybody can please tell me how to specify the required color attribute on this object it will be much appreciated.

It was as simple as including a diffuseColor attribute in the PhongMaterial tag,
<PhongMaterial diffuseColor="GREEN" />
whereas I had originally attempted to include a nested diffuseColor tag between the PhongMaterial tags.

Related

Determine If component is visible in the screen

I use Nativescript + Angular and this is my code:
<ScrollView class="body" id="scroll" #scroll (scroll)="scrollEvent($event);">
<StackLayout #stackScroll>
<ng-template ngFor let-card [ngForOf]="allList">
<StackLayout [card]="card">
<my-custom-component [aCard]="card"></my-custom-component>
</StackLayout>
</ng-template>
</StackLayout>
</ScrollView>
I have used this snippet of code and it works great:
https://discourse.nativescript.org/t/how-to-detect-if-component-is-in-screen-view-is-visible/1148/4
I can change the background colour of the "StackLayout" inside the "ng-template".
But I can't access to my custom component variables to modify his behaviour.
For example, if "my-custom-component" is shown, I want to change the property "isShown" in the "card" object passed in the "aCard" attribute.
Thanks to all :)
EDIT1:
"isShown" is a custom variable that I have used for this test. My idea is to calculate in the afterScroll function what is the cards visible and pass to aCard the parameter to change his behaviour.
You could find the location of each child component inside ScrollView upon scroll event, comparing the same with the vertical offset will let you know whether the component is really visible on screen.
Here is a Playground example. As you scroll down / up, the background color of visible components will turn green, red otherwise.
onScroll(event: EventData) {
const scrollView = <ScrollView>event.object,
verticalOffset = scrollView.verticalOffset,
height = scrollView.getActualSize().height,
visibleRange = verticalOffset + height,
container = <StackLayout>this.container.nativeElement;
let index = 0;
container.eachLayoutChild((childView) => {
const locationY = childView.getLocationRelativeTo(container).y;
this.cards[index].isShown = locationY >= verticalOffset && locationY <= visibleRange
index += 1;
});
}
You need to update your allList object as NgForOf is bindable, it will update the card and that will reflect in [acard] of your my-custom-component
In the scroll event where you must be playing with relative height you take a unique variable to identify the component that is shown and change the property for that index in allList.
I have created a sample playgrod here where I am changing the text of the custom component Label to isShown if scroll height is greater than 300. The way I am changing the label name, you can have a boolean variable in allList in change that where you have your logic to change the background color of stackLayout. Let me know if you want to update the playgrond.

React Native clickable Image with Alpha

I have an image in a .png format with the alpha channel and i wish it to be clickable. The click should be detected only if the real image is clicked (not the alpha background).
<TouchableHighlight onPress={this.imgClick}>
<Image
source={this.img1}
/>
</TouchableHighlight>
And i want to create a clickable circle of these elements
Thank you for helping and i wish you a Merry X-Mas !!
You can detect where on the image has been clicked and then you should have some metadata on the image to detect that it is in the non-alpha bounds.
imgClick = ({nativeEvent: {locationX, locationY}}) => {
if (ImageService.inBounds(image, locationX, locationY)) {
// do your event handling here
}
}
ImageService would be where your metadata and logic is stored for each image. You probably want a simple point in polygon algorithm.
https://en.wikipedia.org/wiki/Point_in_polygon

Very simple flex animation not moving along x axis

I'm trying to use Animate in MXML to move a button along X or Y axis.
My button increase width when clicked, but does not move at all. What is wrong with this code ? It should be something really simple, but I can't find it.
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
initialize='init()'>
<fx:Script>
<![CDATA[
public function init():void {}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout id='l' horizontalAlign="left" />
</s:layout>
<fx:Declarations>
<s:Animate id="mover" target="{button}" duration="1000">
<s:SimpleMotionPath property="x" valueFrom="0" valueTo="100"/>
<s:SimpleMotionPath property="y" valueTo="100"/>
<s:SimpleMotionPath property="width" valueBy="20"/>
</s:Animate>
</fx:Declarations>
<s:Button id="button" click="mover.play()" label="Button"/>
</s:Application>
I got this sample from Adobe docs. I think it should be related to layout or something like that, but all my tries of changing layout, including into a Canvas or other tricks does not change anything : the button still stay at the same place.
Thanks for your help !
The problem is caused by the use of the VerticalLayout. This layout, as well as the HorizontalLayout, ignores x/y properties of the objects that are being laid out.
If you remove your layout declaration altogether, it will then use the default BasicLayout which will honor the x/y properties and allow your animation to work.

Get all Image Elements within a Grid->Canvas using LINQ?

i'm using a Grid within my Application which Contain some Canvas Elements which Contain some Images or Textblocks.
e.g.:
<Grid>
<Canvas>
<Image />
<Image />
</Canvas>
<Canvas>
<Textblock />
<Textblock />
</Canvas>
</Grid>
Now i need to get all Image Elements within the Grid.
Currently i'm using several foreach loops and if-statements to achive this. But i was asking myself if there isn't a more elegant way using LINQ so fetch all Image Elements from the Grid. But unfortunely my LINQ Knowledges aren't that well so i didn't found a way to get the to the Children of the Canvas Element.
Maybe someone has a good Solution to this.
Thanks in advance and kind regards
Kornelis
I added a Name to the Grid to reference in the link
<Grid Name="MyGrid">
Then this linq returns Images inside of canvases that are children of the Grid. I cast it as an object so that it could query every control that was in the Children collection.
IEnumerable<Image> results = (from c in MyGrid.Children.Cast<Object>()
where c.GetType() == typeof(Canvas)
select c).Cast<Canvas>()
.SelectMany(r => r.Children.Cast<object>()
.Where(c => c.GetType() == typeof(Image))).Cast<Image>();

XAML : How to change background color only in Design mode?

I have a control with white text foreground color and transparent background color.
Later on this usercontrol will be added into a different control that carries the real background color.
However during designing this, control due white foreground on white background in VS 2010, I can't obviously see anything. In there anyway to define a different color for just the design time?
I have tried this:
if (System.ComponentModel.DesignerProperties.IsInDesignTool)
{
LayoutRoot.Background = new SolidColorBrush(Colors.Blue);
}
But this doesn't work. Any tips?
UPDATE:
I dont understand how this works for you guys. I have created a new Silverlight 4.0 Application and have inserted this line of code into the ctor:
public MainPage()
{
InitializeComponent();
LayoutRoot.Background = new SolidColorBrush(Colors.Blue);
}
<UserControl x:Class="SilverlightApplication3.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot">
</Grid>
</UserControl>
When I go into Designer, I still dont see it as blue. And I dont even have any isInDesignTime Condition there. What I am missing here?
Thanks,
Kave
Here's one way:
if (System.ComponentModel.DesignerProperties.IsInDesignTool)
{
LayoutRoot.Background = new SolidColorBrush(Colors.Yellow);
}
If you switch to creating a templated control, you'll need to wait to set things up in OnApplyTemplate, like in this example:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Border b = this.GetTemplateChild("backBorder") as Border;
if (b != null && System.ComponentModel.DesignerProperties.IsInDesignTool)
{
b.Background = new SolidColorBrush(Colors.Orange);
}
}
Assuming this is the template:
<Style TargetType="local:TemplatedControl1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TemplatedControl1">
<Border x:Name="backBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I also like to add conditional compile directives around code like this, as it's only for the developer/designer and is never needed at run-time.
#if DEBUG
if (System.ComponentModel.DesignerProperties.IsInDesignTool)
{
LayoutRoot.Background = new SolidColorBrush(Colors.Yellow);
}
#endif
Note that this entire technique works only when the UserControl you're creating is used within* another* UserControl/Control at design time. So, if the code I suggested above is placed in a UserControl named UserControlWithDesignMode, then you must have another UserControl, UserControlHost, that contains an instance of the UserControlWithDesignMode control to see the behavior work at design time. The code-behind for the currently edited control does not execute when you're editing it. It only executes when it's contained within another host (in Silverlight, another UserControl for example).
One option would be to give the UserControl a background color, and then override that where you use it. So when you're editing the UserControl in isolation, it would have a background color; but when you're editing a control that contains that UserControl, you would see it with the transparent background like you want.
So the UserControl's XAML file would look like this:
<UserControl x:Class="MyUserControl" ... Background="DarkBlue">
And then in some other screen, where you use it, you could do:
<my:MyUserControl Background="Transparent" ...>
Inelegant, but simple.
Alternate approach that doesn't involve code:
Install the "Visual Studio 2012 Color Theme Editor" found here:
http://visualstudiogallery.msdn.microsoft.com/366ad100-0003-4c9a-81a8-337d4e7ace05
Or for VS 2010: http://visualstudiogallery.msdn.microsoft.com/20cd93a2-c435-4d00-a797-499f16402378
Create a new custom theme based on the one you want to modify.
Click the "Show All Elements" filter button in the upper-left of the theme editor
Type "artboard" in the search-box in the upper-right of the theme editor
Set the "Cider -> ArtboardBackground" color to a different color of your choice.
Yay! :D
Note: the "Cider -> ArtboardBackground" color theme field is found in VS2012 but I cannot confirm whether it has the same name in VS2010
You can use following code within UserControl constructor:
For WPF:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
{
LayoutRoot.Background = new SolidColorBrush( Colors.Blue );
}
For WPF / Silverlight:
if (DesignerProperties.GetIsInDesignMode( this ))
{
LayoutRoot.Background = new SolidColorBrush( Colors.Blue );
}
Good thread, especially when doing some MVVM the fact that UserControls appear on white when they are transparent is very annoying.
I'm sure you could do this in Blend with a state defined based on whether a designer is running, but I don't think that'd reduce the amount of work.
Still not sure how to avoid the code in the code behind and avoiding having to open blend, so if anybody has suggestions thanks in advance for posting.
I would suggest to use Opacity
<my:MyUserControl Background="Transparent" ...>
That doesn't work, since it will make any child controls inside the usercontrol invisible at run time.
One option would be to give the UserControl a background color, and then override that where you use it.
Did you try to set the Background on the UserControl? Not sure why but for me it doesn't work.
What does work is to set the Background of the Content, like so
<UserControl x:Class="...">
<StackPanel Background="{StaticResource PhoneChromeBrush}">
...
then putting the following code in the constructor of the view
public View() {
InitializeComponent();
var c = Content as Panel;
if (c != null) c.Background = new SolidColorBrush(Colors.Transparent);
}
Another technique mentioned in this SO question is to use the undocumented property d:Design­er­Proper­ties.DesignStyle, which works great for applying a design-time-only style to a single control, but which doesn't appear to work for a Style in a ResourceDictionary that would apply to all of the appropriately-typed controls or elements under the scope of the dictionary.
To solve this, on that same page I provide a simple solution for deploying a designer-only style into a ResourceDictionary. Here is a summary of that answer:
First, put the desired style in a XAML dictionary in the normal way.
<Window.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</Style>
</Window.Resources>
Then, in the C# code, remove the style from the Resource­Dict­ionary when design mode is not detected. Do this is in the OnInitialized override:
protected override void OnInitialized(EventArgs e)
{
if (DesignerProperties.GetIsInDesignMode(this) == false)
Resources.Remove(typeof(TreeViewItem));
base.OnInitialized(e);
}
Design Mode: Runtime Mode:

Resources