Painting shapes in JavaFX [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I created a simple paint program which allows the user to choose between 4 shapes(line,circle,rectangle,ellipse) , the user can change the width height and stroke width , he can save the design he makes , undo and redo , the user can also choose the stroke type (solid or dashed) , I'm facing one problem , when the user picks dashed as the stroke type , I want him to be able to choose the thickness of the stroke , it works perfectly fine with the solid , but with the dashed it's just increasing or decreasing the number of dashed lines , any idea on how I can fix the number of dashed lines and increase the thickness of the dashed lines.
NOTE : I'm using the rectangle shape in the code to make the code small.
Here's the CODE :
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
public class GFG extends Application {
#Override
public void start(Stage primaryStage) {
Image image2 = new
Image("C:\\Users\\Mhamd\\Desktop\\laol\\src\\resources\\pngegg.png",100,100,false,false);
ImageView view2 = new ImageView(image2);
view2.setFitHeight(40);
view2.setPreserveRatio(true);
ToggleButton rectbtn = new ToggleButton();
rectbtn.setGraphic(view2);
ToggleButton[] toolsArr = {rectbtn};
ToggleGroup tools = new ToggleGroup();
for (ToggleButton tool : toolsArr) {
tool.setMinWidth(50);
tool.setToggleGroup(tools);
tool.setCursor(Cursor.HAND);
}
ColorPicker cpLine = new ColorPicker(Color.BLACK);
ColorPicker cpFill = new ColorPicker(Color.TRANSPARENT);
TextField textWidth = new TextField("32");
TextField textHeight = new TextField("32");
TextField contouring = new TextField("2");
Label line_color = new Label("Line Color");
Label fill_color = new Label("Fill Color");
Label line_width = new Label("3.0");
Label imgWidth = new Label("Width");
Label imgHeight = new Label("Height");
String week_days[] =
{ "Solid", "Dotted"};
ChoiceBox choiceBox = new ChoiceBox(FXCollections
.observableArrayList(week_days));
VBox btns = new VBox(10);
btns.getChildren().addAll(imgWidth,textWidth,imgHeight,textHeight, line_color, cpLine,
fill_color, cpFill, line_width, contouring,choiceBox);
btns.setPadding(new Insets(5));
btns.setStyle("-fx-background-color: #999");
btns.setPrefWidth(100);
Canvas canvas = new Canvas(1080, 790);
GraphicsContext gc;
gc = canvas.getGraphicsContext2D();
gc.setLineWidth(1);
Rectangle rect = new Rectangle();
canvas.setOnMouseClicked(e->{
if(rectbtn.isSelected()){
double widthSize = Double.parseDouble(textWidth.getText());
double heightSize = Double.parseDouble(textHeight.getText());
double strokeWidth = Double.parseDouble(contouring.getText());
gc.setStroke(cpLine.getValue());
if(choiceBox.getSelectionModel().isSelected(0)){
gc.setLineWidth(strokeWidth);
}
else if(choiceBox.getSelectionModel().isSelected(1)){
//gc.setLineDashes(strokeWidth);
gc.setLineDashOffset(10);
}
gc.setFill(cpFill.getValue());
rect.setX(e.getX() - 20);
rect.setY(e.getY() - 20);
rect.setWidth(widthSize);
rect.setHeight(heightSize);
gc.fillRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
gc.strokeRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
undoHistory.push(new Rectangle(rect.getX(), rect.getY(), rect.getWidth(),
rect.getHeight()));
}
});
}
public static void main(String[] args) {
launch(args);
}
}

You have to set a width for the dashed line too. Setting line dashes to the line width does not make much sense unless you want something that looks more like a dotted line. And you need the dash offset only in specific cases but not in general.

Related

Fan Orientation Animation Javafx

import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Arc;
import javafx.scene.paint.Color;
import javafx.scene.control.Button;
import javafx.scene.Group;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.animation.PathTransition;
import javafx.util.Duration;
import javafx.scene.shape.Ellipse;
public class MovingFourFans extends Application
{
private Button btPause = new Button("Pause");
private Button btResume = new Button("Resume");
private Button btReverse = new Button("Reverse");
private Circle fanPanel;
private Ellipse fanPath;
private Arc fan1;
private Arc fan2;
private Arc fan3;
private Arc fan4;
private BorderPane uiContainer;
private HBox buttonContainer;
private PathTransition pt = new PathTransition();
#Override
public void start(Stage primaryStage)
{
BorderPane pane = new BorderPane();
Scene scene = new Scene(pane, 400, 500);
buttonContainer = new HBox(btPause, btResume, btReverse);
buttonContainer.setAlignment(Pos.CENTER);
Group group = new Group();
pane.setCenter(group);
pane.setBottom(buttonContainer);
// include a path transition with a circle inside instead
fanPanel = new Circle(Math.min(pane.getWidth(), pane.getHeight()) / 4);
fanPanel.setFill(Color.WHITE);
fanPanel.setStroke(Color.BLACK);
fanPath = new Ellipse(fanPanel.getRadius() / 100, fanPanel.getRadius() / 100);
fanPath.setVisible(true);
fanPath.setFill(Color.WHITE);
fanPath.setStroke(Color.BLACK);
fan1 = new Arc();
fan1.setType(ArcType.ROUND);
fan1.setRadiusX(fanPanel.getRadius() - 10);
fan1.setRadiusY(fanPanel.getRadius() - 10);
fan1.setStartAngle(80);
fan1.setLength(-10);
fan1.setFill(Color.RED);
group.getChildren().addAll(fanPanel, fanPath, fan1);
pt.setPath(fanPath);
pt.setNode(fan1);
pt.setCycleCount(Timeline.INDEFINITE);
pt.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
pt.setDuration(Duration.seconds(3));
pt.setAutoReverse(false);
pt.play();
btPause.setOnAction(e -> pt.pause());
btResume.setOnAction(e -> pt.play());
primaryStage.setTitle("Control Moving Fan");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
}
I'm having a problem trying to create an animation of a fan with four wings with Javafx. I know how to make the buttons work but for the animation every time I start it, the fans moving along the circle path that I created with its middle section not the tip of the section. Because of this the animation doesn't look correct. Does anyone know a fix to this or what method I can use to create the correct animation for this? In this code I only made one wing for test and there are 3 wings left. The screenshot for what I currently have is below.

Can I create dynamic grid view with code for each element in java? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm new to java, I was working on VB.NET but it's not suitable for my new project. I'm trying to make a POS system and I want to ask about a specific thing. If I have a DB table with 10 rows and I need to put them in 10 panels like a grid view, in vb.net I need to make the 10 panels and repeat the code for each one and use hide and show attributes which is exhausting specialty if the table has more rows.
In PHP, I just need to use foreach statement to display the whole table without repeating any codes.
So can I create a dynamic grid view in java? And what exactly should I learn in java? Thank you and sorry for my bad language.
Here's an example of what I think you're trying to do:
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.Window;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
GridPane grid = new GridPane();
grid.setPadding(new Insets(20));
grid.setVgap(15);
grid.setHgap(15);
buildGrid(grid, getPanelNames());
primaryStage.setScene(new Scene(grid));
primaryStage.setTitle("Example App");
primaryStage.show();
}
private void buildGrid(GridPane grid, List<String> panelNames) {
int row = 0;
int col = 0;
for (String name : panelNames) {
Label label = new Label(name);
Button btn = new Button("Click Me!");
btn.setOnAction(event -> {
event.consume();
showAlert(grid.getScene().getWindow(), name);
});
VBox box = new VBox(10, label, btn);
box.setPadding(new Insets(10));
box.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, null, null)));
box.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
grid.add(box, col, row);
if (++col > 3) {
col = 0;
row++;
}
}
}
private List<String> getPanelNames() {
return IntStream.rangeClosed(0, 13)
.mapToObj(i -> "Panel #" + i)
.collect(Collectors.toList());
}
private void showAlert(Window owner, String panelName) {
Alert alert = new Alert(AlertType.INFORMATION);
alert.initOwner(owner);
alert.setTitle(panelName);
alert.setHeaderText(null);
alert.setContentText("Hello from \"" + panelName + "\"!");
alert.show();
}
}

Java3D: I can't see my triangle

I'm very new to Java3D and try to show a triangle, but it does not show up, the frame is completely black.
If i add
bg.addChild(new ColorCube(0.3));
it shows a red square in the middle (so generally showing shapes should work, shouldn't it?)
I don't really know if the problem is with the construction of the triangle itself or with some other part of the View, e.g. the triangle is not in focus, too small, not lit, etc. Do polygons from TriangleArray have to be lit by a source, or do they appear as matt objects?
Here is the code:
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.geometry.GeometryInfo;
import com.sun.j3d.utils.geometry.NormalGenerator;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.universe.SimpleUniverse;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import javax.swing.JFrame;
import javax.media.j3d.*;
import javax.vecmath.Color3f;
import javax.vecmath.Color4f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
public class Simulator extends Frame {
Point3f[] testTrianglePoints = {
new Point3f(0.0f ,0.0f, 1.0f),
new Point3f(0.0f, 0.0f, 1.2f),
new Point3f(0.2f, 0.2f, 1.2f)};
Simulator() {
System.out.println("Simulator window initiated");
}
public void run() {
SimpleUniverse u = new SimpleUniverse();
BranchGroup bg = new BranchGroup();
//bg.addChild(new ColorCube(0.3));
TriangleArray t_geo = new TriangleArray(9, TriangleArray.COORDINATES);
t_geo.setCoordinates(0,testTrianglePoints);
GeometryArray t_geoArray = (new GeometryInfo(t_geo)).getGeometryArray();
Shape3D t_shape = new Shape3D(t_geoArray,new Appearance());
bg.addChild(t_shape);
u.addBranchGraph(bg);
u.getViewingPlatform().setNominalViewingTransform();
}
}
`

JavaFX Using TimeLine to Pause Program

I need to set my background colour of my Pane for one second and then switch it to transparent. I have this set up to change the background colour, use a TimeLine with a duration of 1000ms to pause it, and then switch to transparent.
The Timeline is not pausing and the program is flying past it and setting the background to transparent too quickly. Anyone know how to fix this?
I can not use thread.sleep or anything like that because of the scope of this project.
package assign3;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import javafx.animation.FillTransition;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Question2 extends Application
{
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLUE = 3;
public static final int ORANGE = 4;
#Override
public void start( Stage obPrimeStage ) throws Exception
{
boolean runGame = true;
int level = 1;
BorderPane obBorder = new BorderPane();
HBox obPane = new HBox();
HBox obStart = new HBox();
Button btRed = new Button("Red");
Button btGreen = new Button("Green");
Button btBlue = new Button("Blue");
Button btOrange = new Button("Orange");
Button btStart = new Button("Start");
Timeline pause = new Timeline();
pause.setCycleCount(1);
pause.getKeyFrames().add(new KeyFrame(Duration.millis(1000)));
obStart.getChildren().add(btStart);
obPane.getChildren().addAll(btRed, btGreen, btBlue, btOrange);
obBorder.setCenter(obPane);
obBorder.setBottom(obStart);
obPane.setAlignment(Pos.CENTER);
obStart.setAlignment(Pos.CENTER);
Scene obScene = new Scene(obBorder, 400, 400);
obPrimeStage.setTitle("Question 2");
obPrimeStage.setScene(obScene);
obPrimeStage.show();
ArrayList<Integer> colours = new ArrayList<>();
ArrayList<Integer> guesses = new ArrayList<>();
btStart.setOnAction((ActionEvent start) -> {
for(int i = 0; i <= level; i++)
{
int randomColour = (int)((Math.random() * 4) + 1);
randomColour = 1;
if(randomColour == RED)
{
obBorder.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
pause.play();
obBorder.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)));
colours.add(RED);
}
You are using Timeline as a substitute for Thread.sleep. That is not how Timeline works.
When you call play() on an Animation, it starts the animation in the background and returns immediately.
Have a look at the constructors of the KeyFrame class. You need to pass a KeyValue to your KeyFrame, so a change occurs at the point in time represented by the KeyFrame:
pause.getKeyFrames().add(new KeyFrame(Duration.ZERO,
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)))));
pause.getKeyFrames().add(new KeyFrame(Duration.millis(1000),
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)))));
As you can see, a KeyValue consists of two parts: a property, and the new value you want assigned to that property at some point during the animation.
The first at Duration.ZERO (the start), which sets the background property to your starting color.
The second occurs after 1000 milliseconds have passed, and sets the background property to transparent again.
By the way, you might find Duration.seconds(1) a little more readable.

Moving circle changing color in javafx

I want my ball to change color everytime i click on it, but i wont get it to work. Also im wondering about the movement of my ball. I wonder how you can change the path its going. so it can down up and down and other ways instead of just from left to right.
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.Bloom;
import javafx.scene.effect.Effect;
import javafx.scene.effect.Glow;
import javafx.scene.effect.Light;
import javafx.scene.effect.Lighting;
import javafx.scene.effect.MotionBlur;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TimelineSample extends Application {
Timeline timeline;
private void init(Stage primaryStage) {
Group root = new Group();
primaryStage.setResizable(false);
primaryStage.setScene(new Scene(root, 280, 120));
Circle circle = new Circle(25, 25, 20, Color.BLUE);
Light.Distant light = new Light.Distant();
light.setAzimuth(-135.0);
Lighting lighting = new Lighting();
lighting.setLight(light);
lighting.setSurfaceScale(5.0);
circle.setEffect(lighting);
timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.setAutoReverse(true);
timeline.getKeyFrames().addAll
(new KeyFrame(Duration.ZERO, new KeyValue(circle.translateXProperty(),
0)),
new KeyFrame(new Duration(4000), new KeyValue(circle
.translateXProperty(), 205)));
root.getChildren().add(circle);
root.requestFocus();
root.setOnKeyPressed(e -> {
if (e.getCode().equals(KeyCode.ENTER)) {
timeline.play();
circle.setFill(Color.PINK);
}
});
root.setOnMousePressed(event -> {
if (circle.contains(event.getX(), event.getY())) {
circle.setFill(Color.BLACK);
if (circle.getFill().equals(Color.BLACK))
circle.setFill(Color.YELLOW);
else if (circle.getFill().equals(Color.BLUE))
circle.setFill(Color.BROWN);
else if (circle.getFill().equals(Color.YELLOW))
circle.setFill(Color.BROWN);
else if (circle.getFill().equals(Color.BROWN))
circle.setFill(Color.BLACK);
}
});
}
#Override
public void stop() {
timeline.stop();
}
#Override
public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
It does not change the color (just once to yellow) because before your check you set it to black and then it is converted to yellow.
if (circle.contains(event.getX(), event.getY())) {
circle.setFill(Color.BLACK); // <-- so it is black
if (circle.getFill().equals(Color.BLACK)) // <-- uhh..it is black..let's change to yellow
circle.setFill(Color.YELLOW);
else if (circle.getFill().equals(Color.BLUE))
circle.setFill(Color.BROWN);
else if (circle.getFill().equals(Color.YELLOW))
circle.setFill(Color.BROWN);
else if (circle.getFill().equals(Color.BROWN))
circle.setFill(Color.BLACK);
}
And it is getting from left to right because your using the X-Property instead of the Y-Property.

Categories