I have a issue with my Marquee animation with JavaFX. I have a HBox with three Nodes and in the second node I have a Text node inside that I need do the Marquee transformation, but when the text goes out of the second node I need it doesn't be visible.
I'll go to set a picture to show my issue (the text is visible in the white area).
My Hbox code:
HBox bill = new HBox(0);
bill.getChildren().addAll(logoPane,product,total);
bill.setBackground(new Background(new BackgroundFill(Color.web("#FFFFFF"), CornerRadii.EMPTY, Insets.EMPTY)));
bill.setHgrow(product, Priority.ALWAYS);
Animation:
timelineAnimation = new Timeline();
final KeyValue kv = new KeyValue(productLabel.translateXProperty(), -1000);
final KeyFrame kf = new KeyFrame(Duration.millis(2000), kv);
timelineAnimation.getKeyFrames().add(kf);
And how I define my product node:
productLabel.setFont(new Font("Times New Roman",30));
product = new StackPane();
product.setMaxWidth(2000);
product.setMaxHeight(100);
product.setMinWidth(574);
product.setMinHeight(100);
product.getChildren().add(productLabel);
product.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
product.setAlignment(productLabel, Pos.CENTER);
Hope it was enough information.
Thanks!
Simply add a Rectangle as clip for the product pane and bind it's size to the size of the pane:
Rectangle clip = new Rectangle();
product.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> {
clip.setWidth(newValue.getWidth());
clip.setHeight(newValue.getHeight());
});
product.setClip(clip);
This will make sure no descendants of product are drawn outside the bounds of this node.
Related
I'm attempting to create something like a minimap with JavaFX, i.e. a (darkened) background image with some circles layered on top of it. Some of these circles need to be able to shed light on the background, revealing a small part of it. The following figure shows what I am aiming at.
I have worked my way forward using this SO solution, but at the moment, I am stuck because it seems that you can only set one instance of javafx.scene.effect.Lighting on the underlying StackPane.
I would really like to keep this as simple as possible and ideally only employ JavaFX. Any help is greatly appreciated :)
I recommend adding together Circles filled with a RadialGradient on a Pane with black background using BlendMode.LIGHTEN and combining this with a ImageView containing the "map" using BlendMode.MULTIPLY:
private Circle circle;
// gradient with yellow in the center and black on the border
private final static RadialGradient GRADIENT = new RadialGradient(0, 0, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE, new Stop(0, Color.YELLOW), new Stop(1, Color.BLACK));
private void newCircle(Pane container) {
circle = new Circle(50, GRADIENT);
circle.setBlendMode(BlendMode.LIGHTEN);
circle.setManaged(false);
container.getChildren().add(circle);
}
private void setCirclePosition(MouseEvent event) {
circle.setCenterX(event.getX());
circle.setCenterY(event.getY());
}
#Override
public void start(Stage primaryStage) {
Image image = new Image(imageURL);
ImageView imageView = new ImageView(image);
Pane mask = new Pane();
mask.setBlendMode(BlendMode.MULTIPLY);
mask.setStyle("-fx-background-color: black;");
mask.setOnMouseMoved(this::setCirclePosition); // move cricle with mouse
newCircle(mask);
// create new circle on mouse click
mask.setOnMouseClicked(evt -> {
newCircle(mask);
setCirclePosition(evt);
});
StackPane root = new StackPane(imageView, mask);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
I'm trying to make Item In JScrollPane dynamically.
but when i add JPanel(for represent item) that Panel fill all Scroll area.
when I add 2 JPanel item, it divide and also fill all Scroll Area.
enter image description here
'Green' Area mean Item Area this pic is when I add one Item to Scroll Area.
enter image description here
'cyan' color mean another item. this pic is when i add second Item to Scroll Area
I want fix each item's height (And fill width)
when I add item that item adding to Scroll Pane Area, and left area remain empty space.
how can i do this?
below is my code.
Thanks.
public class JPanelINScrollPanel extends JFrame{
public JPanelINScrollPanel(){
this.setSize(700,700);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel basePanel = new JPanel();
JScrollPane scrollPanel = new JScrollPane();
JPanel listPanel = new JPanel();
JPanel itemPanel1 = new JPanel();
JPanel itemPanel2 = new JPanel();
JPanel itemPanel3 = new JPanel();
basePanel.setBackground(Color.BLACK);
getContentPane().add(basePanel);
basePanel.setLayout(new BorderLayout(0, 0));
scrollPanel.setBackground(Color.BLUE);
basePanel.add(scrollPanel);
listPanel.setSize(500,500);
listPanel.setBackground(Color.red);
listPanel.setLayout(new BoxLayout(listPanel, BoxLayout.PAGE_AXIS));
scrollPanel.add(listPanel);
scrollPanel.setViewportView(listPanel);
//itemPanel1.setSize(50,50);
itemPanel1.setPreferredSize(new Dimension(50, 50));
itemPanel1.setBackground(Color.GREEN);
listPanel.add(itemPanel1);
}
public static void main(String[] args){
JPanelINScrollPanel test = new JPanelINScrollPanel();
test.setVisible(true);
}
}
It's simple
just setMaximumSize to item panel.
it's solved.
I am trying to create a continuous animation, eventually the goal would be a bouncing ball that bounces off the edges of the screen, however, one step at a time.
I started with the sample code from Oracle that has an animation of circles that move for 40 seconds.
public void start(Stage primaryStage)
{
Group root = new Group();
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
Group circles = new Group();
for (int i = 0; i < 1; i++)
{
MovingCircle circle = new MovingCircle(150, Color.web("white", 0.05));
circle.setStrokeType(StrokeType.OUTSIDE);
circle.setStroke(Color.web("black", 0.16));
circle.setStrokeWidth(4);
circles.getChildren().add(circle);
}
root.getChildren().add(circles);
Timeline timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
for (Node circle: circles.getChildren())
{
if(circle instanceof MovingCircle)
{
MovingCircle c = (MovingCircle)circle;
timeline.getKeyFrames().addAll(
/* new KeyFrame(Duration.ZERO, // set start position at 0
new KeyValue(circle.translateXProperty(), random() * 800),
new KeyValue(circle.translateYProperty(), random() * 600)
),*/
new KeyFrame(new Duration(10), // set end position at 40s
c.getXMovement(), c.getYMovement())
);
c.updateCenter();
}
}
// play 40s of animation
timeline.play();
primaryStage.show();
}
I created a new MovingCircle that extends Circle to try and add other stuff to it later. The two new class methods return exactly what was commented out from the default code given.
I changed the cycle to indefinite so that it would go forever. All the circle does though is bounce between its original starting point and the translated point. I have tried updating its center location in hopes that the next bounce would move it to a different location, however, that doesn't work.
I am at quite a loss as to what to try next to get this working more the way I was hoping.
Hey I am trying to make a simple 2d scroller but I simply cannot seem to get the picture to scroll. I am using an ImagveView for the picture, and I have tried both a translatetransition and a pathtransition, but I can't get any good results? Here is my code:
public void aboutSceneAnimation() {
Rectangle2D psb = Screen.getPrimary().getVisualBounds();
Path path = new Path();
MoveTo moveTo = new MoveTo();
moveTo.setX(0.0);
path.getElements().add(moveTo);
PathTransition pt = new PathTransition();
pt.setDuration(Duration.INDEFINITE);
pt.setNode(map);
pt.setPath(path);
pt.setCycleCount(4);
pt.setAutoReverse(true);
pt.play();
}
public Scene aboutScene() {
Rectangle2D psb = Screen.getPrimary().getVisualBounds();
//Create the map
BorderPane border = new BorderPane();
border.getChildren().addAll(map2);
//Size the map
map2.setFitWidth(psb.getWidth());
map2.setFitHeight(psb.getHeight());
Scene scene = new Scene(border, 500, 500);
aboutSceneAnimation();
return scene;
}
The way it works is that when the program starts there is a start scene loaded into my stage, and then I just show the stage. When a button is pressed I simply change to the aboutScene which also calls the aboutSceneAnimation, which is where I want the map to scroll. Any ideas would be greatly appreciated!
-Cheers
You need to use a Pane instead of a BorderPane, because in a BorderPane the center node will be resized to fill the available space in the middle.
In your PathTransition you only add from where to start, i. e. the MoveTo, but you don't add where it should go, e. g. a LineTo.
Additional note:
Since your example in the question contains only bits and pieces that don't work together, please read about How to create a Minimal, Complete, and Verifiable example.
What's the proposed way to add space to layouts in Xamarin.Forms?
One way would be to add a Frame with no children like so:
new Frame {
BackgroundColor = Color.White,
HeightRequest = 1,
MinimumHeightRequest = 1,
HasShadow = false
}
Unfortunately, HeightRequest and MinimumHeightRequest get ignored.
Does a better way exist?
You could put your controls inside layouts (like frame, scroll view, stack panel) and use Padding property:
this.stackPanel = new StackLayout ()
{
Padding = new Thickness (8, 8)
};
var scrollView = new ScrollView ()
{
Content = stackPanel,
Padding = new Thickness (1, 2, 3, 4)
};
var frame = new Frame ()
{
Padding = new Thickness (8)
};
If you want space between two buttons for example, I believe this would do the trick. The first one adds 10 to bottom padding, the second adds 10 to top padding for total of 20.
var frame1 = new Frame ()
{
Padding = new Thickness (0,0,0,10),
Content = new Button()
};
var frame2 = new Frame ()
{
Padding = new Thickness (0,10,0,0),
Content = new Button()
};
Most Xamarin.Forms Layouts supports adding space between elements:
StackLayout has a Spacing property,
Grid has RowSpacing and ColumnSpacing properties,
...
Now, if you want to add spacing at a particular place, the way to to it is to include a BoxView:
myStackLayout.Children.Add (new BoxView {Color = Color.Transparent, HeightRequest = 5});
You can also wrap your content in a Frame or ContentView, but it adds padding to the content instead of adding space (although the effect will be the same).
What I do worked perfectly for me:
Suppose you want to distribute 2 Labels evenly on a horizontal StackLayout:
new StackLayout
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions=LayoutOptions.CenterAndExpand,
Spacing = 0, // <- Very important!!
Children = {
new Label { Text = "Label 1" },
new BoxView { HorizontalOptions = LayoutOptions.FillAndExpand }, // <- the clever part
new Label { Text = "Label 2" }
}
};
Summary
By inserting BoxViews that fill the remaining space ("FillAndExpand") between your views, your views appear evenly distributed.
By setting Spacing = 0, you don't get extra space between your views.
Try:
myFrame.TranslateX=10;
myFrame.TranslateY=10;
I wanted to share a screenshot in conjunction with Lay González's answer but the edit queue was full->
To get dynamic spacing similar to CSS "Space-Between" in Xamarin you can insert filler views between your views that actually have content.
Here is an example:
Omit the filler view after the last "actual" view so that the view you want is at the end (the "-50" label at the bottom in the example).