Remove rounded corners from JavaFX application - javafx

I've created a calculator in JavaFX but one thing frustrates me - it seems like the scene or the primary stage has slightly rounded corners, and these are visible behind the square corners of the buttons.
Screenshot of the problem
I've played around with the background radius of the scene but can't work it out. Any ideas where this radius (if that's what it is) is set?
Here is my code and CSS:
.root
{
-fx-font-size: 12pt;
}
.label
{
-fx-background-color: #999999;
-fx-text-fill: #f9f9f9;
-fx-font-weight: 500;
}
.label-main
{
-fx-background-color: #999999;
-fx-text-fill: #f9f9f9;
-fx-font-size: 35pt;
-fx-font-weight: 500;
}
.button
{
-fx-font-weight: lighter;
-fx-border-style: solid;
-fx-border-color: gray;
-fx-background-color: #E0E0E0;
-fx-border-width: 0 1 1 0;
-fx-background-insets: 0,1,1;
-fx-background-radius: 0;
}
.del-clear
{
-fx-font-weight: lighter;
-fx-font-size: 9pt;
-fx-border-style: solid;
-fx-border-color: gray;
-fx-background-color: #E0E0E0;
-fx-border-width: 0 1 1 0;
-fx-background-insets: 0,1,1;
-fx-background-radius: 0;
}
.button-bigger
{
-fx-font-size: 14pt;
}
.button:pressed
{
-fx-background-color: #B2B2B2;
}
.button-special
{
-fx-background-color: #EA9747;
-fx-text-fill: white;
-fx-border-width: 0 0 1 0;
}
.zero-point
{
-fx-border-width: 0 1 0 0;
}
.button-equals
{
-fx-border-width: 0 0 0 0;
}
package calculator;
import java.util.ArrayList;
import java.util.List;
import javafx.application.*;
import static javafx.application.Application.launch;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.*;
import javafx.stage.*;
public class UserInterface extends Application {
private static int appWidth = 215; //230;
private static int appHeight = 295; //300;
private static int numRows = 7;
private static int numCols = 8;
private List<Button> numButList = new ArrayList();
private List<Button> functButtons = new ArrayList();
private List<Button> compButtons = new ArrayList();
private Calculator calc;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
//Screen s
Label screen2 = new Label("0");
screen2.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
screen2.setAlignment(Pos.CENTER_RIGHT);
screen2.getStyleClass().add("label-main");
Label screen1 = new Label("");
screen1.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
screen1.setAlignment(Pos.CENTER_RIGHT);
GridPane screenBox = new GridPane();
screenBox.getStyleClass().add("innerGrid");
screenBox.setPrefSize(UserInterface.appWidth, (UserInterface.appHeight / UserInterface.numRows) * 2);
//Set the row constraints
for (int i = 0; i < 4; i++) {
RowConstraints r = new RowConstraints();
r.setVgrow(Priority.ALWAYS);
r.setFillHeight(true);
r.setPercentHeight(25);
screenBox.getRowConstraints().add(r);
}
//Set the column constraints
ColumnConstraints c = new ColumnConstraints();
c.setHgrow(Priority.ALWAYS);
c.setPercentWidth(100);
screenBox.getColumnConstraints().add(c);
//screenBox.setGridLinesVisible(true);
screenBox.add(screen1, 0, 0, 1, 1);
screenBox.add(screen2, 0, 1, 1, 3);
//Create calc and pass the screen1 to it
this.calc = new Calculator(screen1, screen2);
//Create 0-9 buttons
for (int i = 0; i < 10; i++) {
Button tempButton = new Button(Integer.toString(i));
if (i == 0) {
tempButton.getStyleClass().add("zero-point");
}
final String tempVar = Integer.toString(i);
tempButton.setOnAction(e -> this.calc.setUserInput(tempVar));
tempButton.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
HBox.setHgrow(tempButton, Priority.ALWAYS);
VBox.setVgrow(tempButton, Priority.ALWAYS);
numButList.add(tempButton);
}
//Point button
//point button
Button point = new Button(".");
String tepointVarmpVar = ".";
point.setOnAction(e -> this.calc.setUserInput(tepointVarmpVar));
point.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
HBox.setHgrow(point, Priority.ALWAYS);
VBox.setVgrow(point, Priority.ALWAYS);
point.getStyleClass().add("button-bigger");
point.getStyleClass().add("zero-point");
//Equals, plus, minus, multiply, and divide buttons
Button equals = new Button("=");
this.compButtons.add(equals);
equals.setOnAction(e -> this.calc.calculate());
Button plus = new Button("+");
this.compButtons.add(plus);
String plusVar = "+";
plus.setOnAction(e -> this.calc.setUserInput(plusVar));
Button minus = new Button("-");
String minusVar = "-";
minus.setOnAction(e -> this.calc.setUserInput(minusVar));
this.compButtons.add(minus);
minus.setStyle("fx-font-size: 16");
Button multiply = new Button("x");
String xVar = "*";
multiply.setOnAction(e -> this.calc.setUserInput(xVar));
this.compButtons.add(multiply);
Button divide = new Button("/");
this.compButtons.add(divide);
String divideVar = "/";
divide.setOnAction(e -> this.calc.setUserInput(divideVar));
//Add button configs
for (int i = 0; i < 5; i++) {
this.compButtons.get(i).setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
this.compButtons.get(i).getStyleClass().add("button-special");
HBox.setHgrow(this.compButtons.get(i), Priority.ALWAYS);
VBox.setVgrow(this.compButtons.get(i), Priority.ALWAYS);
}
equals.getStyleClass().add("button-equals");
for (int i = 0; i < 4; i++) {
this.compButtons.get(i).getStyleClass().add("button-bigger");
}
//Clear and delete buttons
Button clear = new Button("CLR");
clear.setOnAction(e -> this.calc.clearUserInput());
clear.getStyleClass().add("del-clear");
this.functButtons.add(clear);
Button del = new Button("DEL");
del.setOnAction(e -> this.calc.backSpace());
del.getStyleClass().add("del-clear");
this.functButtons.add(del);
for (int i = 0; i < 2; i++) {
this.functButtons.get(i).setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
HBox.setHgrow(this.functButtons.get(i), Priority.ALWAYS);
VBox.setVgrow(this.functButtons.get(i), Priority.ALWAYS);
}
//Create GridPane
GridPane grid = new GridPane();
//Add nodes to grid pane
grid.add(numButList.get(0), 0, 6, 4, 1);
grid.add(point, 4, 6, 2, 1);
grid.add(numButList.get(1), 0, 5, 2, 1);
grid.add(numButList.get(2), 2, 5, 2, 1);
grid.add(numButList.get(3), 4, 5, 2, 1);
grid.add(numButList.get(4), 0, 4, 2, 1);
grid.add(numButList.get(5), 2, 4, 2, 1);
grid.add(numButList.get(6), 4, 4, 2, 1);
grid.add(numButList.get(7), 0, 3, 2, 1);
grid.add(numButList.get(8), 2, 3, 2, 1);
grid.add(numButList.get(9), 4, 3, 2, 1);
grid.add(equals, 6, 6, 2, 1);
grid.add(plus, 6, 5, 2, 1);
grid.add(minus, 6, 4, 2, 1);
grid.add(multiply, 6, 3, 2, 1);
grid.add(divide, 6, 2, 2, 1);
grid.add(clear, 0, 2, 3, 1);
grid.add(del, 3, 2, 3, 1);
grid.add(screenBox, 0, 0, 8, 2);
// Set row and column constraints
for (int rowIndex = 0; rowIndex < UserInterface.numRows; rowIndex++) {
RowConstraints rc = new RowConstraints();
rc.setVgrow(Priority.ALWAYS);
rc.setFillHeight(true);
rc.setPercentHeight(UserInterface.appHeight / UserInterface.numRows);
grid.getRowConstraints().add(rc);
}
for (int colIndex = 0; colIndex < UserInterface.numCols; colIndex++) {
ColumnConstraints cc = new ColumnConstraints();
cc.setHgrow(Priority.ALWAYS);
cc.setFillWidth(true);
cc.setPercentWidth(UserInterface.appWidth / UserInterface.numCols);
grid.getColumnConstraints().add(cc);
}
// Create the scene and the stage
Scene scene = new Scene(grid, appWidth, appHeight);
scene.getStylesheets().add("Simple.css");
primaryStage.setScene(scene);
//primaryStage.setTitle("Calculator");
primaryStage.setResizable(false);
primaryStage.show();
}
}
package calculator;
import java.util.ArrayList;
import java.util.List;
public class StringCalculator {
public StringCalculator() {
}
public static double calcString(final String str2) {
return new Object() {
int pos = -1, ch;
void nextChar() {
ch = (++pos < str2.length()) ? str2.charAt(pos) : -1;
}
boolean eat(int charToEat) {
while (ch == ' ') {
nextChar();
}
if (ch == charToEat) {
nextChar();
return true;
}
return false;
}
double parse() {
nextChar();
double x = parseExpression();
if (pos < str2.length()) {
throw new RuntimeException("Unexpected: " + (char) ch);
}
return x;
}
// Grammar:
// expression = term | expression `+` term | expression `-` term
// term = factor | term `*` factor | term `/` factor
// factor = `+` factor | `-` factor | `(` expression `)`
// | number | functionName factor | factor `^` factor
double parseExpression() {
double x = parseTerm();
for (;;) {
if (eat('+')) {
x += parseTerm(); // addition
} else if (eat('-')) {
x -= parseTerm(); // subtraction
} else {
return x;
}
}
}
double parseTerm() {
double x = parseFactor();
for (;;) {
if (eat('*')) {
x *= parseFactor(); // multiplication
} else if (eat('/')) {
x /= parseFactor(); // division
} else {
return x;
}
}
}
double parseFactor() {
if (eat('+')) {
return parseFactor(); // unary plus
}
if (eat('-')) {
return -parseFactor(); // unary minus
}
double x;
int startPos = this.pos;
if (eat('(')) { // parentheses
x = parseExpression();
eat(')');
} else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
while ((ch >= '0' && ch <= '9') || ch == '.') {
nextChar();
}
x = Double.parseDouble(str2.substring(startPos, this.pos));
} else if (ch >= 'a' && ch <= 'z') { // functions
while (ch >= 'a' && ch <= 'z') {
nextChar();
}
String func = str2.substring(startPos, this.pos);
x = parseFactor();
if (func.equals("sqrt")) {
x = Math.sqrt(x);
} else if (func.equals("sin")) {
x = Math.sin(Math.toRadians(x));
} else if (func.equals("cos")) {
x = Math.cos(Math.toRadians(x));
} else if (func.equals("tan")) {
x = Math.tan(Math.toRadians(x));
} else {
throw new RuntimeException("Unknown function: " + func);
}
} else {
throw new RuntimeException("Unexpected: " + (char) ch);
}
if (eat('^')) {
x = Math.pow(x, parseFactor()); // exponentiation
}
return x;
}
}.parse();
}
}

Related

Trying to deduce location of mouse drag with JavaFX Gridpane

Note: 25 years with Java, 2.5 hours (almost) with JavaFX.
I want to be able to highlight all cells of a GridPane that the mouse is dragged across - i.e. everything that intersects with the rectangle cornered by the click point and the current drag point. I can do that if all children are 1x1, but with mixed sizes I'm having no joy.
For example, if the top row has 1 1 column cell (A) and 1 2 column cell (B) and the bottom has 1 2 column cell (C) and 1 1 column cell (D), if I click in A and drag down into C I can highlight both. However, I cannot figure out when I drag into the right half of C so that B should be highlighted.
Sample Board:
Apologies for the HSCE - it's a bit long but I felt stripping it down would reduce readability.
import java.util.*;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.Node;
import javafx.stage.Stage;
import javafx.geometry.*;
public class AddTestSSCE extends Application
{
ArrayList<StackPane> sPanes = new ArrayList<StackPane>(); // selected panes
GridPane theGrid;
Node startNode = null;
int col0, col1;
int row0, row1;
#Override
public void start(Stage stage) {
theGrid = new GridPane();
ColumnConstraints col = new ColumnConstraints(300);
theGrid.getColumnConstraints().addAll(col, col, col);
RowConstraints row = new RowConstraints(200);
theGrid.getRowConstraints().addAll(row, row, row);
addGridPane();
theGrid.getStyleClass().add("bg-grid");
Scene scene = new Scene(theGrid, 1024, 768);
scene.getStylesheets().add("addtestssce.css");
stage.setScene(scene);
stage.show();
}
public void addGridPane() {
theGrid.setHgap(10);
theGrid.setVgap(10);
theGrid.setPadding(new Insets(0, 10, 0, 10));
StackPane theSP = sPAdd(new Label("A"));
theGrid.add(theSP, 0, 0, 1, 1);
theSP = sPAdd(new Label("B"));
theGrid.add(theSP, 1, 0, 2, 1);
theSP = sPAdd(new Label("C"));
theGrid.add(theSP, 0, 1, 2, 1);
theSP = sPAdd(new Label("D"));
theGrid.add(theSP, 2, 1, 1, 1);
theGrid.addEventFilter(MouseEvent.MOUSE_PRESSED, //Creating the mouse event handler
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
System.out.println("We're Moving!!");
startNode = (Node)e.getTarget();
sPanes.add((StackPane)startNode);
col0 = GridPane.getColumnIndex(startNode).intValue();
row0 = GridPane.getRowIndex(startNode).intValue();
System.out.printf("Starting at %d %d\n", col0, row0);
}
});
theGrid.addEventFilter(MouseEvent.MOUSE_DRAGGED, //Creating the mouse event handler
new EventHandler<MouseEvent>() {
Node lastNode = null;
#Override
public void handle(MouseEvent e) {
Node target = (Node)e.getTarget();
double xLoc = e.getX();
double yLoc = e.getY();
Bounds bs = target.localToScene(target.getBoundsInLocal());
Node moveTarget;
if( bs.contains(xLoc, yLoc) )
{
moveTarget = target;
}
else
{
moveTarget = getContainingNode((int)xLoc, (int)yLoc);
}
if( moveTarget != null && lastNode != moveTarget )
{
col1 = GridPane.getColumnIndex(moveTarget).intValue();
row1 = GridPane.getRowIndex(moveTarget).intValue();
doHighlighting();
lastNode = moveTarget;
}
}
});
}
void doHighlighting()
{
int c0, c1, r0, r1;
c0 = col0 > col1 ? col1 : col0;
c1 = !(col0 > col1) ? col1 : col0;
r0 = row0 > row1 ? row1 : row0;
r1 = !(row0 > row1) ? row1 : row0;
Rectangle2D rec1 = new Rectangle2D(c0, r0, c1-c0+1, r1-r0+1);
System.out.printf("Box: %d %d %d %d\n", c0, c1, r0, r1);
List<Node> nodes = theGrid.getChildren();
for( Node node : nodes )
{
StackPane sp = (StackPane)node;
unhighlight(sp);
int col = GridPane.getColumnIndex(sp).intValue();
int row = GridPane.getRowIndex(sp).intValue();
if( occupiesCell(sp, rec1) )
{
highlight(sp);
}
}
}
boolean occupiesCell(Node node, Rectangle2D r1)
{
boolean result = false;
int col = GridPane.getColumnIndex(node).intValue();
int row = GridPane.getRowIndex(node).intValue();
int wid = GridPane.getColumnSpan(node).intValue();
int hei = GridPane.getRowSpan(node).intValue();
Rectangle2D r2 = new Rectangle2D( col, row, wid, hei);
return r2.intersects(r1);
}
void unhighlight(Node node)
{
if( !(node instanceof StackPane) )
{
return;
}
StackPane label = (StackPane)node;
List<String> cList = label.getStyleClass();
cList.remove("b2");
cList.add("b1");
}
void highlight(Node node)
{
if( !(node instanceof StackPane) )
{
return;
}
StackPane label = (StackPane)node;
List<String> cList = label.getStyleClass();
cList.remove("b1");
cList.add("b2");
}
private Node getContainingNode(int xLoc, int yLoc)
{
Node tgt = null;
for( Node node : theGrid.getChildren() )
{
Bounds boundsInScene = node.localToScene(node.getBoundsInLocal());
if( boundsInScene.contains(xLoc, yLoc) )
{
return node;
}
}
return tgt;
}
private StackPane sPAdd(Label label)
{
StackPane gPPane = new StackPane();
gPPane.getChildren().add(label);
gPPane.getStyleClass().addAll("b1", "grid-element");
GridPane.setFillHeight(gPPane, true);
GridPane.setFillWidth(gPPane, true);
return gPPane;
}
public static void main(String[] args)
{
launch();
}
}
.bg-grid {
-fx-background-color: slategrey;
}
.grid-element {
-fx-border-width: 10;
-fx-border-color: rgb(225, 128, 217);
-fx-background-color: rgb(247, 146, 146);
-fx-font: 36 arial;
}
.b1 {
-fx-text-base-color: white;
-fx-border-color: rgb(225, 128, 217);
}
.b2 {
-fx-text-base-color: lightgray;
-fx-border-color: rgb(233, 228, 86);
}
After a bit of back and forth with #james_d and #slaw, finally came up with a working solution.
import java.util.*;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.Node;
import javafx.stage.Stage;
import javafx.geometry.*;
import javafx.css.PseudoClass;
public class AddTestSSCE extends Application
{
private static final PseudoClass highlight = PseudoClass.getPseudoClass("highlight");
ArrayList<StackPane> sPanes = new ArrayList<StackPane>(); // selected panes
GridPane theGrid;
Node startNode = null;
int x0, y0, x1, y1;
#Override
public void start(Stage stage) {
theGrid = new GridPane();
ColumnConstraints col = new ColumnConstraints(300);
theGrid.getColumnConstraints().addAll(col, col, col);
RowConstraints row = new RowConstraints(200);
theGrid.getRowConstraints().addAll(row, row, row);
addGridPane();
theGrid.getStyleClass().add("bg-grid");
Scene scene = new Scene(theGrid, 1024, 768);
scene.getStylesheets().add("addtestssce.css");
stage.setScene(scene);
stage.show();
}
public void addGridPane() {
theGrid.setHgap(10);
theGrid.setVgap(10);
theGrid.setPadding(new Insets(0, 10, 0, 10));
StackPane theSP = sPAdd(new Label("A"));
theGrid.add(theSP, 0, 0, 1, 1);
theSP = sPAdd(new Label("B"));
theGrid.add(theSP, 1, 0, 2, 1);
theSP = sPAdd(new Label("C"));
theGrid.add(theSP, 0, 1, 2, 1);
theSP = sPAdd(new Label("D"));
theGrid.add(theSP, 2, 1, 1, 1);
theGrid.addEventFilter(MouseEvent.MOUSE_PRESSED, //Creating the mouse event handler
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
System.out.println("We're Moving!!");
startNode = (Node)e.getTarget();
sPanes.add((StackPane)startNode);
x0 = x1 = (int)e.getX();
y0 = y1 = (int)e.getY();
doHighlighting();
System.out.printf("Starting at %d %d\n", x0, y0);
}
});
theGrid.addEventFilter(MouseEvent.MOUSE_DRAGGED, //Creating the mouse event handler
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
Node target = (Node)e.getTarget();
x1 = (int)e.getX();
y1 = (int)e.getY();
Bounds bs = target.localToScene(target.getBoundsInLocal());
Node moveTarget;
if( bs.contains(x1, y1) )
{
moveTarget = target;
}
else
{
moveTarget = getContainingNode( x1, y1);
}
if( moveTarget != null )
{
doHighlighting();
}
}
});
}
void doHighlighting()
{
int c0, c1, r0, r1;
c0 = x0 > x1 ? x1 : x0;
c1 = !(x0 > x1) ? x1 : x0;
r0 = y0 > y1 ? y1 : y0;
r1 = !(y0 > y1) ? y1 : y0;
Bounds dragged = new BoundingBox(c0, r0, c1-c0+1, r1-r0+1);
for (Node child : theGrid.getChildren())
{
child.pseudoClassStateChanged(highlight, dragged.intersects(child.getBoundsInParent()));
}
}
private Node getContainingNode(int xLoc, int yLoc)
{
Node tgt = null;
for( Node node : theGrid.getChildren() )
{
Bounds boundsInScene = node.localToScene(node.getBoundsInLocal());
if( boundsInScene.contains(xLoc, yLoc) )
{
return node;
}
}
return tgt;
}
private StackPane sPAdd(Label label)
{
StackPane gPPane = new StackPane();
gPPane.getChildren().add(label);
gPPane.getStyleClass().addAll("b1", "grid-element");
GridPane.setFillHeight(gPPane, true);
GridPane.setFillWidth(gPPane, true);
return gPPane;
}
public static void main(String[] args)
{
launch();
}
}
and the CSS:
.bg-grid {
-fx-background-color: slategrey;
}
.grid-element {
-fx-border-width: 10;
-fx-border-color: rgb(225, 128, 217);
-fx-background-color: rgb(247, 146, 146);
-fx-font: 36 arial;
}
.grid-element:highlight {
-fx-text-base-color: lightgray;
-fx-border-color: rgb(233, 228, 86);
}

Java FX ComboBox drop down list

Can anyone tell me why some items from a dropdown list are not visible when running the jar application? It seems to happen randomly. I create an ObservableList, then recursively create a Line, assign it a stroke type from the observable list through a String as line.setStyle("-fx-stroke-dash-array:" + dashString + ";"). Finally, everything works fine and the ComboBox gets the whole list of line and a certain selection. But it sometimes fail to display lines in the dropdown list. The code is:
package test;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class ComboLines extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
ComboBox<Line> dashCombo = new ComboBox<>();
initDashLineCombo(dashCombo, dashUnit, 2);
dashCombo.getStylesheets().add("test/style.css");
dashCombo.setStyle("-fx-min-width: 100; -fx-max-width: 100; -fx-pref-width: 100; -fx-min-height: 15; -fx-pref-height: 15; -fx-max-height: 15;");
StackPane root = new StackPane();
root.getChildren().add(dashCombo);
primaryStage.setScene(new Scene(root, 150, 300));
primaryStage.show();
}
public static void initDashLineCombo(ComboBox<Line> cb, ObservableList<int[]> list, int i)
{
ArrayList<Line> LinesList = new ArrayList<>(); // to store lines
// cycle over the list and generate a line with dashing defined by list
for(int j = 0; j < list.size(); j++)
{
int sum = 0;
int[] dash = list.get(j);
String dashString = " ";
for(int k : dash) // cycle over an int array which defines the dashing
{ dashString += k + " ";
sum += k; }
System.out.println("sum = " + sum);
Line line = new Line(15, 0, 1*(15+sum), 0);
System.out.print("\ndashString :" + dashString);
// apply style
line.setStrokeWidth(2);// line width
line.setStroke(Color.BLACK);
line.setStyle("-fx-stroke-dash-array:" + dashString + ";"); // line dashing
LinesList.add(line); // collect the line
}
// create the observable list
final ObservableList<Line> LinesObs = FXCollections.observableArrayList(LinesList);
// set all line items in the combo box
cb.setItems(LinesObs);
// select an item ion the combo box
cb.setValue(LinesObs.get(i-1));
}
// ... dashing ...
int[] s10 = {1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3,};
int[] s9 = {1,3,1,3,1,4,5,4,5,4, 1,3,1,3,1,4,5,4,5,4};
int[] s8 = {6,3,6,3,6,5,1,5, 6,3,6,3,6,5,1,5};
int[] s7 = {1,3,1,3,1,6,6,6, 1,3,1,3,1,6,6,6};
int[] s6 = {5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3};
int[] s5 = {5, 4, 5, 4, 1, 3, 1, 4, 5, 4, 5, 4, 1, 3, 1, 4};
int[] s4 = {5, 4, 1, 3, 1, 4, 5, 4, 1, 3, 1, 4, 5, 4, 1, 3, 1, 4};
int[] s3 = {5, 3, 1, 3, 5, 3, 1, 3, 5, 3, 1, 3, 5, 3, 1, 3};
int[] s2 = {15, 3, 15, 3, 15, 3};
int[] s1 = {60};
final ObservableList<int[]> dashUnit = FXCollections.observableArrayList(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10);
}
/* style.css */
.combo-box {
-fx-min-width: 35;
-fx-pref-width: 35;
-fx-max-width: 35;
-fx-min-height: 20;
-fx-pref-height: 20;
-fx-max-height: 20;
-fx-padding: -2 -8 -2 -5;
}
.combo-box-base > .arrow-button {
-fx-background-radius: 0 3 3 0, 0 2 2 0, 0 1 1 0;
-fx-background-color: transparent;
-fx-alignment: center-left;
}
.combo-box .cell {
-fx-font-size: 8.75pt;
-fx-font-family: "Arial";
-fx-text-fill: BLACK;
-fx-alignment: BASELINE_RIGHT;
-fx-padding: 0 3 0 -5;
}
invisible lines
UPDATE: Using cell factory a simplified version (no CSS and no dashing applied) is like this. The same problem persists and further I cannot get the initial selection applied.
package test;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ComboLines extends Application
{
public static void main(String[] args) { launch(args); }
ComboBox<Line> dashCombo = new ComboBox<>();
#Override
public void start(Stage primaryStage)
{
StackPane root = new StackPane();
root.getChildren().add(dashCombo);
dashCombo.setItems(FXCollections.observableList(DASHUNIT));
dashCombo.getSelectionModel().selectFirst();
dashCombo.setCellFactory(new Callback<ListView<Line>, ListCell<Line>>()
{
#Override
public ListCell<Line> call(ListView<Line> newLine)
{
return new ListCell<Line>()
{
#Override
protected void updateItem(Line item, boolean y)
{
super.updateItem(item, false);
setGraphic(item);
} // end updateItem
} ; // end new ListCell
} // end call()
}); // end setCellFactory
primaryStage.setScene(new Scene(root, 150, 300));
primaryStage.show();
}
Line line1 = new Line(15, 0, 50, 0), line2 = new Line(15, 0, 50, 0), line3 = new Line(15, 0, 50, 0);
final ObservableList<Line> DASHUNIT = FXCollections.observableArrayList(line1, line2, line3);
}
Finally, I got it working with the code below. Following kleopatra's comments, the insipartion came from the official Oracle page https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/ComboBox.html
ComboBox<Line> dashCombo = new ComboBox<>();
dashCombo.getStylesheets().add("style.css");
dashCombo.setStyle("-fx-min-width: 100; -fx-max-width: 100; -fx-pref-width: 100; "
+ "-fx-min-height: 15; -fx-pref-height: 15; -fx-max-height: 15;");
initDashLineCombo(dashCombo, common.General.DASHUNIT, (numberCoils - i), colCombo);
public static void initDashLineCombo(ComboBox<Line> cb, ObservableList<int[]> list, int i, ColorPicker cp)
{
for(int j = 0; j < list.size(); j++) // cycle over the list and generate a line with dashing defined by list
{
int[] dash = list.get(j);
String dashString = " ";
for(int k : dash)
dashString += k + " ";
Line line = new Line(25, 0, 95, 0);
line.setStrokeWidth(2); line.strokeProperty().bind(cp.valueProperty());
line.setStyle("-fx-stroke-dash-array:" + dashString + ";");
cb.getItems().add(line);
}
cb.getSelectionModel().clearAndSelect(i-1);
cb.setCellFactory(new Callback<ListView<Line>, ListCell<Line>>()
{
#Override public ListCell<Line> call(ListView<Line> p)
{
return new ListCell<Line>() {
private final Line line;
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
line = new Line(0, 0, 70, 0);
line.setStrokeWidth(2);
line.strokeProperty().bind(cp.valueProperty());
} // end Line
#Override protected void updateItem(Line item, boolean empty)
{
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
}
else {
line.setStyle(item.getStyle());
setGraphic(line);
setItem(line);
}
} // end updateItem()
}; // end ListCell
} // end call()
}); // end setCellFactory
}
enter image description here
enter image description here

JavaFX: How to stroke only certain areas of a GridPane (or other structure)

I want to create a table-like structure and stroke the borders and just some of the inner lines to help guide the viewer's eye. This is just a snippet of a much larger structure to help illustrate the goal:
click to view sample here
I am currently using GridPane rather than TableView because this structure is both input/output. The user will need to view the information and update some of the numbers on the screen.
The trouble is that turning gridlines on for the entire structure becomes very noisy visually. So instead I want to use CSS to only put lines around certain elements within the GridPane.
But then with CSS I run into a complex mess. For example the ward1 cell needs to be stroked on the left, top and bottom. The ward2 cell needs to be stroked on just the top and bottom, same for ward3 ... the ward7 cell needs top, right and bottom and so on.
Is there a better way to do this - either with CSS, or with a better layout, that would make it easier to stroke just the parts of the grid that I want stroked?
(currently using Java 1.7.0_40-b43 and Scene Builder 1.1)
A GridPane doesn't generate cells like a TableView or ListView. It is basically just a Pane with special constraints for the nodes you add to it. Unfortunately, this means creating your own cells and applying styles to them which can get very messy.
With some planning and some helper methods, it is possible to keep things somewhat tidy. The following generates a GridPane with styles similar to the example image provided using StackPanes as cells. I only used labels, so you would have to replace with TextFields or whatever controls you are using for input. This code is just to demonstrate one way to keep things orderly.
Note that rotating labels will not rotate their bounds and therefore will not behave as expected within GridPane constraints, so in this case, it is best to put them in a Group first:
public static void main(final String... a) {
Application.launch(a);
}
#Override
public void start(final Stage primaryStage) throws Exception {
GridPane grid = new GridPane();
grid.setPadding(Insets.EMPTY);
grid.setVgap(0);
grid.setHgap(0);
grid.setAlignment(Pos.TOP_LEFT);
ColumnConstraints column = new ColumnConstraints();
column.setHgrow(Priority.ALWAYS);
column.setHalignment(HPos.LEFT);
column.setFillWidth(true);
grid.getColumnConstraints().add(column);
for (int i = 0; i < 12; i++) {
column = new ColumnConstraints();
column.setHgrow(Priority.SOMETIMES);
column.setHalignment(HPos.CENTER);
grid.getColumnConstraints().add(column);
}
// row 0
addCell(grid, 1, 0, 7, 1, "Ward/Branch Actual", Pos.CENTER, true, false, false, false);
addCell(grid, 8, 0, 3, 1, "Current Qtr", Pos.CENTER, true, false, false, false);
addCell(grid, 11, 0, 2, 1, "Stake Totals", Pos.CENTER, true, false, false, false);
// row 1
addCell(grid, 0, 1, 1, 1, "Members/Families", Pos.BOTTOM_LEFT, true, true, false, false);
for (int i = 1; i < 8; i++) {
addVerticalCell(grid, i, 1, "Ward " + i, (i == 7));
}
addVerticalCell(grid, 8, 1, "Actual", false);
addVerticalCell(grid, 9, 1, "Potential", false);
addVerticalCell(grid, 10, 1, "%", true);
addVerticalCell(grid, 11, 1, "% 1 year ago", false);
addVerticalCell(grid, 12, 1, "% 5 years ago", true);
// row 2
addDividerRow(grid, 2);
// row 3
addCell(grid, 0, 3, 1, 1, "Total Members", Pos.CENTER_LEFT, false, true, true, true);
for (int i = 1; i < 13; i++) {
addCell(grid, i, 3, 1, 1, "78%", Pos.CENTER, false, (i == 7 || i == 10 || i == 12), true, true);
}
// row 4
addCell(grid, 0, 4, 1, 1, "Total Families", Pos.CENTER_LEFT, false, true, false, false);
for (int i = 1; i < 13; i++) {
addCell(grid, i, 4, 1, 1, "83%", Pos.CENTER, false, (i == 7 || i == 10 || i == 12), false, false);
}
// row 5
addDividerRow(grid, 5);
final Scene scene = new Scene(grid, 1000, 700);
scene.getStylesheets().add("styles/style.css"); // or wherever you put it
primaryStage.setScene(scene);
primaryStage.setTitle("Styled GridPane Test");
primaryStage.show();
}
private void addCell(GridPane grid, int col, int row, int cspan, int rspan, String text, Pos pos, boolean isBold, boolean hasRightBorder, boolean hasBottomBorder, boolean isShaded) {
Label label = new Label(text);
if (isBold) {
label.getStyleClass().add("h1");
}
StackPane spane = new StackPane(label);
spane.setAlignment(pos);
if (hasBottomBorder && hasRightBorder) {
spane.getStyleClass().addAll("bd", "bdrb");
} else if (hasBottomBorder && !hasRightBorder) {
spane.getStyleClass().addAll("bd", "bdb");
} else if (!hasBottomBorder && hasRightBorder) {
spane.getStyleClass().addAll("bd", "bdr");
}
if (isShaded) {
spane.getStyleClass().addAll("shaded");
}
grid.add(spane, col, row, cspan, rspan);
}
private void addVerticalCell(GridPane grid, int col, int row, String text, boolean hasRightBorder){
Label label = new Label(text);
Group group = new Group(label);
StackPane spane = new StackPane(group);
spane.getStyleClass().addAll("vert", "bd");
if (hasRightBorder) {
spane.getStyleClass().add("bdtr");
} else {
spane.getStyleClass().add("bdt");
}
grid.add(spane, col, row, 1, 1);
}
private void addDividerRow(GridPane grid, int row) {
StackPane stack_0_2 = new StackPane();
stack_0_2.getStyleClass().addAll("bd", "divider");
grid.add(stack_0_2, 0, row, 1, 1);
StackPane stack_1_2 = new StackPane();
stack_1_2.getStyleClass().addAll("bd", "divider");
grid.add(stack_1_2, 1, row, 7, 1);
StackPane stack_1_8 = new StackPane();
stack_1_8.getStyleClass().addAll("bd", "divider");
grid.add(stack_1_8, 8, row, 3, 1);
StackPane stack_1_11 = new StackPane();
stack_1_11.getStyleClass().addAll("bd", "divider");
grid.add(stack_1_11, 11, row, 2, 1);
}
/*
style.css
*/
.root {
-fx-background-color: rgb(255, 255, 255);
-fx-padding: 4px;
}
.label {
-fx-font-size: 12px;
-fx-padding: 2px 4px 2px 4px;
}
.h1 {
-fx-font-size: 14px;
-fx-font-weight: bold;
}
.vert {
-fx-alignment: BOTTOM_CENTER;
}
.vert .label {
-fx-rotate: -90;
}
.bd {
-fx-border-color: rgb(180, 180, 180);
-fx-border-width: 1;
}
.bdt {
-fx-border-width: 1px 0 0 0;
}
.bdtr {
-fx-border-width: 1px 1px 0 0;
}
.bdr {
-fx-border-width: 0 1px 0 0;
}
.bdrb {
-fx-border-width: 0 1px 1px 0;
}
.bdb {
-fx-border-width: 0 0 1px 0;
}
.divider {
-fx-border-width: 1px 1px 1px 0;
-fx-padding: 2px;
}
.shaded {
-fx-background-color: rgb(230, 230, 230);
}

JComboBox stops responding when focus is directed to another component

I'm having an issue with a small personal application I am puttig together. I am loading data into a JDialog. Within the JDialog, I am loading multiple JPanels that each contain a TableLayout. I am dynamically generating the rows from the data that is loaded into the JDialog. Each row contains a JComboBox and a JTextField that are use to make comments about the status of that particular set of data.
The problem I am encountering has to do with the JComboBox components that are being created. When the JDialog window opens, the JComboBox components are visable and working. Although, as soon as I direct the focus to a different type of component, the JComboBox components stop responding to the mouse clicks.
There is no special logic around the JComboBox components. They simply populate with four different string values, which the user should be able to choose from. No ChangeListener is required for this.
Also note, I wrap all the content in a ScrollPane within the JDialog.
The following is the code where I create the JComboBox components within the TableLayout of the JPanel:
private JPanel createColumnPanel() {
int columnCount = report.getColumns().size();
int rowCount = (columnCount * 2) - 1;
SpringLayout layout = new SpringLayout();
JPanel padding = new JPanel(layout);
TitledBorder border = BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Column Differences: ");
border.setTitleJustification(TitledBorder.LEFT);
double[] columns = new double[] {3, 75, 3, 175, 3, 150, 3, 100, 3, 125};
double[] rows = new double[rowCount];
for(int i = 0; i < rowCount; i++) {
rows[i] = 20;
if (i + 1 < rowCount)
rows[i + 1] = 5;
i++;
}
double size[][] = {columns, rows};
JPanel panel = new JPanel(new TableLayout(size));
columnStatus = new ArrayList<JComboBox<String>>();
for(int i = 0; i < columnCount; i++) {
JComboBox<String> comboBox = new JComboBox<String>(statusLiterals);
comboBox.setEnabled(true);
columnStatus.add(comboBox);
}
for (int i = 0; i < columnCount; i++) {
panel.add(new JLabel(report.getColumns().get(i).getSchema().toString()), 1 + ", " + (i * 2));
panel.add(new JLabel(report.getColumns().get(i).getTableName()), 3 + ", " + (i * 2));
panel.add(new JLabel(report.getColumns().get(i).getColumnName()), 5 + ", " + (i * 2));
panel.add(columnStatus.get(i), 7 + ", " + (i * 2));
panel.add(new JTextField(report.getColumns().get(i).getRequestor()), 9 + ", " + (i * 2));
}
panel.setBorder(border);
panel.setVisible(true);
panel.setAlignmentX(LEFT_ALIGNMENT);
panel.setBackground(Color.WHITE);
layout.putConstraint(SpringLayout.NORTH, panel, 10, SpringLayout.NORTH, padding);
layout.putConstraint(SpringLayout.SOUTH, padding, 10, SpringLayout.SOUTH, panel);
layout.putConstraint(SpringLayout.EAST, padding, 10, SpringLayout.EAST, panel);
layout.putConstraint(SpringLayout.WEST, panel, 10, SpringLayout.WEST, padding);
padding.add(panel, SwingConstants.CENTER);
padding.setBackground(Color.WHITE);
return padding;
}
The following is the full code for this particular JDialog:
public class ManageRequestsDialog extends JDialog {
private static final long serialVersionUID = 1L;
private ComparisonReport report;
private JPanel outerPanel;
private ScrollPane scrollPane;
private JPanel innerPanel;
private JPanel databasePanel;
private JPanel tablePanel;
private JPanel columnPanel;
private List<JLabel> databaseSchemas = null;
private List<JComboBox<String>> databaseStatus = null;
private List<JTextField> databaseRequestors = null;
private List<JLabel> tableSchemas = null;
private List<JLabel> tableTableNames = null;
private List<JComboBox<String>> tableStatus = null;
private List<JTextField> tableRequestors = null;
private List<JLabel> columnSchemas = null;
private List<JLabel> columnTableNames = null;
private List<JLabel> columnColumnNames = null;
private List<JComboBox<String>> columnStatus = null;
private List<JTextField> columnRequestors = null;
private String[] statusLiterals = DifferenceStatus.getLiterals();
public ManageRequestsDialog (ComparisonReport report) {
super();
this.report = report;
outerPanel = createOuterPanel();
add(outerPanel);
setLayout(new GridLayout(1, 1));
setModal(true);
setSize(700, 500);
setBackground(Color.WHITE);
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
}
private JPanel createOuterPanel() {
JPanel panel = new JPanel(new GridLayout(1, 1));
scrollPane = createScrollPane();
panel.add(scrollPane);
panel.setVisible(true);
panel.setBackground(Color.WHITE);
return panel;
}
private ScrollPane createScrollPane() {
ScrollPane scrollPane = new ScrollPane();
innerPanel = createInnerPanel();
scrollPane.add(innerPanel);
scrollPane.setVisible(true);
scrollPane.setBackground(Color.WHITE);
return scrollPane;
}
private JPanel createInnerPanel() {
JPanel panel = new JPanel(new BorderLayout());
if (report.getDatabases().size() > 0) {
databasePanel = createDatabasePanel();
panel.add(databasePanel, BorderLayout.NORTH);
}
if (report.getTables().size() > 0) {
tablePanel = createTablePanel();
panel.add(tablePanel, BorderLayout.CENTER);
}
if (report.getColumns().size() > 0) {
columnPanel = createColumnPanel();
panel.add(columnPanel, BorderLayout.SOUTH);
}
panel.setVisible(true);
panel.setBackground(Color.WHITE);
return panel;
}
private JPanel createDatabasePanel() {
int databaseCount = report.getDatabases().size();
int rowCount = (databaseCount * 2) - 1;
SpringLayout layout = new SpringLayout();
JPanel padding = new JPanel(layout);
TitledBorder border = BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Database Differences: ");
border.setTitleJustification(TitledBorder.LEFT);
double[] columns = new double[] {3, 75, 3, 75, 3, 150};
double[] rows = new double[rowCount];
for(int i = 0; i < rowCount; i++) {
rows[i] = 20;
if (i + 1 < rowCount)
rows[i + 1] = 5;
i++;
}
double size[][] = {columns, rows};
JPanel panel = new JPanel(new TableLayout(size));
databaseStatus = new ArrayList<JComboBox<String>>();
for(int i = 0; i < databaseCount; i++) {
JComboBox<String> comboBox = new JComboBox<String>(statusLiterals);
comboBox.setEnabled(true);
databaseStatus.add(comboBox);
}
for (int i = 0; i < databaseCount; i++) {
panel.add(new JLabel(report.getDatabases().get(i).getSchema().toString()), 1 + ", " + (i * 2));
panel.add(databaseStatus.get(i), 3 + ", " + (i * 2));
panel.add(new JTextField(report.getDatabases().get(i).getRequestor()), 5 + ", " + (i * 2));
}
panel.setBorder(border);
panel.setVisible(true);
panel.setAlignmentX(LEFT_ALIGNMENT);
panel.setBackground(Color.WHITE);
layout.putConstraint(SpringLayout.NORTH, panel, 10, SpringLayout.NORTH, padding);
layout.putConstraint(SpringLayout.SOUTH, padding, 10, SpringLayout.SOUTH, panel);
layout.putConstraint(SpringLayout.EAST, padding, 10, SpringLayout.EAST, panel);
layout.putConstraint(SpringLayout.WEST, panel, 10, SpringLayout.WEST, padding);
padding.add(panel, SwingConstants.CENTER);
padding.setBackground(Color.WHITE);
return padding;
}
private JPanel createTablePanel() {
int tableCount = report.getTables().size();
int rowCount = (tableCount * 2) - 1;
SpringLayout layout = new SpringLayout();
JPanel padding = new JPanel(layout);
TitledBorder border = BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Table Differences: ");
border.setTitleJustification(TitledBorder.LEFT);
double[] columns = new double[] {3, 75, 3, 175, 3, 100, 3, 150};
double[] rows = new double[rowCount];
for(int i = 0; i < rowCount; i++) {
rows[i] = 20;
if (i + 1 < rowCount)
rows[i + 1] = 5;
i++;
}
double size[][] = {columns, rows};
JPanel panel = new JPanel(new TableLayout(size));
tableStatus = new ArrayList<JComboBox<String>>();
for(int i = 0; i < tableCount; i++) {
JComboBox<String> comboBox = new JComboBox<String>(statusLiterals);
comboBox.setEnabled(true);
tableStatus.add(comboBox);
}
for (int i = 0; i < tableCount; i++) {
panel.add(new JLabel(report.getTables().get(i).getSchema().toString()), 1 + ", " + (i * 2));
panel.add(new JLabel(report.getTables().get(i).getTableName()), 3 + ", " + (i * 2));
panel.add(tableStatus.get(i), 5 + ", " + (i * 2));
panel.add(new JTextField(report.getTables().get(i).getRequestor()), 7 + ", " + (i * 2));
}
panel.setBorder(border);
panel.setVisible(true);
panel.setAlignmentX(LEFT_ALIGNMENT);
panel.setBackground(Color.WHITE);
layout.putConstraint(SpringLayout.NORTH, panel, 10, SpringLayout.NORTH, padding);
layout.putConstraint(SpringLayout.SOUTH, padding, 10, SpringLayout.SOUTH, panel);
layout.putConstraint(SpringLayout.EAST, padding, 10, SpringLayout.EAST, panel);
layout.putConstraint(SpringLayout.WEST, panel, 10, SpringLayout.WEST, padding);
padding.add(panel, SwingConstants.CENTER);
padding.setBackground(Color.WHITE);
return padding;
}
private JPanel createColumnPanel() {
int columnCount = report.getColumns().size();
int rowCount = (columnCount * 2) - 1;
SpringLayout layout = new SpringLayout();
JPanel padding = new JPanel(layout);
TitledBorder border = BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Column Differences: ");
border.setTitleJustification(TitledBorder.LEFT);
double[] columns = new double[] {3, 75, 3, 175, 3, 150, 3, 100, 3, 125};
double[] rows = new double[rowCount];
for(int i = 0; i < rowCount; i++) {
rows[i] = 20;
if (i + 1 < rowCount)
rows[i + 1] = 5;
i++;
}
double size[][] = {columns, rows};
JPanel panel = new JPanel(new TableLayout(size));
columnStatus = new ArrayList<JComboBox<String>>();
for(int i = 0; i < columnCount; i++) {
JComboBox<String> comboBox = new JComboBox<String>(statusLiterals);
comboBox.setEnabled(true);
columnStatus.add(comboBox);
}
for (int i = 0; i < columnCount; i++) {
panel.add(new JLabel(report.getColumns().get(i).getSchema().toString()), 1 + ", " + (i * 2));
panel.add(new JLabel(report.getColumns().get(i).getTableName()), 3 + ", " + (i * 2));
panel.add(new JLabel(report.getColumns().get(i).getColumnName()), 5 + ", " + (i * 2));
panel.add(columnStatus.get(i), 7 + ", " + (i * 2));
panel.add(new JTextField(report.getColumns().get(i).getRequestor()), 9 + ", " + (i * 2));
}
panel.setBorder(border);
panel.setVisible(true);
panel.setAlignmentX(LEFT_ALIGNMENT);
panel.setBackground(Color.WHITE);
layout.putConstraint(SpringLayout.NORTH, panel, 10, SpringLayout.NORTH, padding);
layout.putConstraint(SpringLayout.SOUTH, padding, 10, SpringLayout.SOUTH, panel);
layout.putConstraint(SpringLayout.EAST, padding, 10, SpringLayout.EAST, panel);
layout.putConstraint(SpringLayout.WEST, panel, 10, SpringLayout.WEST, padding);
padding.add(panel, SwingConstants.CENTER);
padding.setBackground(Color.WHITE);
return padding;
}
}

Cannot find class type name "Normalized"- Processing

I'm having a dilemma with this code and have no clue what to do. I'm pretty new to processing. This is a project from this link...
http://blog.makezine.com/2012/08/10/build-a-touchless-3d-tracking-interface-with-everyday-materials/
any help is massively appreciated... Thanks in advance
import processing.serial.*;
import processing.opengl.*;
Serial serial;
int serialPort = 1;
int sen = 3; // sensors
int div = 3; // board sub divisions
Normalize n[] = new Normalize[sen];
MomentumAverage cama[] = new MomentumAverage[sen];
MomentumAverage axyz[] = new MomentumAverage[sen];
float[] nxyz = new float[sen];
int[] ixyz = new int[sen];
float w = 256; // board size
boolean[] flip = {
false, true, false};
int player = 0;
boolean moves[][][][];
PFont font;
void setup() {
size(800, 600, P3D);
frameRate(25);
font = loadFont("TrebuchetMS-Italic-20.vlw");
textFont(font);
textMode(SCREEN);
println(Serial.list());
serial = new Serial(this, Serial.list()[serialPort], 115200);
for(int i = 0; i < sen; i++) {
n[i] = new Normalize();
cama[i] = new MomentumAverage(.01);
axyz[i] = new MomentumAverage(.15);
}
reset();
}
void draw() {
updateSerial();
drawBoard();
}
void updateSerial() {
String cur = serial.readStringUntil('\n');
if(cur != null) {
String[] parts = split(cur, " ");
if(parts.length == sensors) {
float[] xyz = new float[sen];
for(int i = 0; i < sen; i++)
xyz[i] = float(parts[i]);
if(mousePressed && mouseButton == LEFT)
for(int i = 0; i < sen; i++)
n[i].note(xyz[i]);
nxyz = new float[sen];
for(int i = 0; i < sen; i++) {
float raw = n[i].choose(xyz[i]);
nxyz[i] = flip[i] ? 1 - raw : raw;
cama[i].note(nxyz[i]);
axyz[i].note(nxyz[i]);
ixyz[i] = getPosition(axyz[i].avg);
}
}
}
}
float cutoff = .2;
int getPosition(float x) {
if(div == 3) {
if(x < cutoff)
return 0;
if(x < 1 - cutoff)
return 1;
else
return 2;
}
else {
return x == 1 ? div - 1 : (int) x * div;
}
}
void drawBoard() {
background(255);
float h = w / 2;
camera(
h + (cama[0].avg - cama[2].avg) * h,
h + (cama[1].avg - 1) * height / 2,
w * 2,
h, h, h,
0, 1, 0);
pushMatrix();
noStroke();
fill(0, 40);
translate(w/2, w/2, w/2);
rotateY(-HALF_PI/2);
box(w);
popMatrix();
float sw = w / div;
translate(h, sw / 2, 0);
rotateY(-HALF_PI/2);
pushMatrix();
float sd = sw * (div - 1);
translate(
axyz[0].avg * sd,
axyz[1].avg * sd,
axyz[2].avg * sd);
fill(255, 160, 0);
noStroke();
sphere(18);
popMatrix();
for(int z = 0; z < div; z++) {
for(int y = 0; y < div; y++) {
for(int x = 0; x < div; x++) {
pushMatrix();
translate(x * sw, y * sw, z * sw);
noStroke();
if(moves[0][x][y][z])
fill(255, 0, 0, 200);
else if(moves[1][x][y][z])
fill(0, 0, 255, 200);
else if(
x == ixyz[0] &&
y == ixyz[1] &&
z == ixyz[2])
if(player == 0)
fill(255, 0, 0, 200);
else
fill(0, 0, 255, 200);
else
fill(0, 100);
box(sw / 3);
popMatrix();
}
}
}
fill(0);
if(mousePressed && mouseButton == LEFT)
msg("defining boundaries");
}
void keyPressed() {
if(key == TAB) {
moves[player][ixyz[0]][ixyz[1]][ixyz[2]] = true;
player = player == 0 ? 1 : 0;
}
}
void mousePressed() {
if(mouseButton == RIGHT)
reset();
}
void reset() {
moves = new boolean[2][div][div][div];
for(int i = 0; i < sen; i++) {
n[i].reset();
cama[i].reset();
axyz[i].reset();
}
}
void msg(String msg) {
text(msg, 10, height - 10);
}
You are missing a class, in fact, more than one. Go back to the github and download, or copy and paste, all three codes, placing each one in a new tab named same name of the class (well this is not required, but is a good practice). The TicTacToe3D.pde is the main code. To make a new tab choose "new tab" from the arrow menu in Processing IDE (just below the standard button at the right). The code should run. WIll need an Arduino though to really get it working.

Resources