JavaFX z-buffer issues - java

I'm filling a container with a lot of small boxes and the problem is that you can see trough them from some angles. I've already enabled the depth buffer, but that doesn't work.
The code that handles this part is split into 3. setupUIPreElements sets everything up, setupUIElements adds the boxes and setupUIPostElements adds the container and some camera stuff.
public static void setupUIPreElements(Stage stage){
//Setup grids, groups, scenes, camera and such so that the scene is made from scratch
topGrid = new GridPane();
twoDGroup = new Group();
threeDGroup = new SmartGroup();
root = new HBox();
mainScene = new Scene(root, SCREEN_WIDTH, SCREEN_HEIGHT, true, SceneAntialiasing.BALANCED);
twoD = new SubScene(twoDGroup, SCREEN_WIDTH*.2, SCREEN_HEIGHT);
threeD = new SubScene(threeDGroup, SCREEN_WIDTH*.8, SCREEN_HEIGHT);
anchorAngleX = 0;
anchorAngleY = 0;
angleX = new SimpleDoubleProperty(0);
angleY = new SimpleDoubleProperty(0);
camera = new PerspectiveCamera();
pins = new ProgressIndicator[1];
pin = pins[0] = new ProgressIndicator();
parcels = new ArrayList<UIParcel>();
//add subscenes to scene
root.getChildren().addAll(twoD, threeD);
root.setSpacing(10);
root.setPadding(new Insets(20, 20, 20, 20));
/*START Setup top menu*/
//Setup grid
topGrid.setHgap(10);
topGrid.setVgap(10);
//Setup items
//Add scoring label
scoringLabel = new Label("Score: " + Wrapper.score);
startButton = new Button("Start");
modeSelection = new ChoiceBox(FXCollections.observableArrayList(
"Parcels", "Pentominoes"
));
modeSelection.setValue("");
//Parcel selection UI
ParcelAAmountLabel = new Label("Amount of parcel A: ");
ParcelBAmountLabel = new Label("Amount of parcel B: ");
ParcelCAmountLabel = new Label("Amount of parcel C: ");
ParcelAAmountTextField = new TextField();
ParcelBAmountTextField = new TextField();
ParcelCAmountTextField = new TextField();
ParcelAValueLabel = new Label("Value of parcel A: ");
ParcelBValueLabel = new Label("Value of parcel B: ");
ParcelCValueLabel = new Label("Value of parcel C: ");
ParcelAValueTextField = new TextField();
ParcelBValueTextField = new TextField();
ParcelCValueTextField = new TextField();
//Pentominoe selection UI
LPentominoAmountLabel = new Label("Amount of L pentominoes: ");
PPentominoAmountLabel = new Label("Amount of P pentominoes: ");
TPentominoAmountLabel = new Label("Amount of T pentominoes: ");
LPentominoAmountTextField = new TextField();
PPentominoAmountTextField = new TextField();
TPentominoAmountTextField = new TextField();
LPentominoValueLabel = new Label("Value of L pentominoes: ");
PPentominoValueLabel = new Label("Value of P pentominoes: ");
TPentominoValueLabel = new Label("Value of T pentominoes: ");
LPentominoValueTextField = new TextField();
PPentominoValueTextField = new TextField();
TPentominoValueTextField = new TextField();
//-1 will make it display an animated disk, set to 1 to show that it's done
//pin is the progress indicator
pin.setProgress(-1);
topGrid.add(scoringLabel, 0, 0);
topGrid.add(modeSelection, 0, 1);
topGrid.add(startButton, 0, 8);
twoDGroup.getChildren().add(topGrid);
/*END*/
//Set materials
container_material.setDiffuseColor(CONTAINER_COLOR);
edge_material.setDiffuseColor(EDGE_COLOR);
}
public static void setupUIElements(Stage stage, int[][][] resultBoxesArray){
//TODO check if I can assume the IDs to be either 1, 2 or 3 if filled in or 0 if not
int colorStart = 0;
int colorEnd = 0;
//give every filled in field a box representation and keep color in mind
//create all the boxes
for(int x=0; x<resultBoxesArray.length; x++){
for(int y=0; y<resultBoxesArray[x].length; y++){
for(int z=0; z<resultBoxesArray[x][y].length; z++){
int currentValue = resultBoxesArray[x][y][z];
//if this field is filled
if(currentValue!=0){
//update color range
if(currentValue==1){
colorStart = 0;
colorEnd = 70;
} else if (currentValue==2){
colorStart = 85;
colorEnd = 155;
} else {
colorStart = 170;
colorEnd = 255;
}
//50 is used because that is the size that is given for each cell in the array
UIParcel cellBox = new UIParcel(x*50, y*50, z*50, 50, 50, 50, colorStart, colorEnd);
parcels.add(cellBox);
}
}
}
}
//show them
threeDGroup.getChildren().addAll(parcels);
}
public static void setupUIPostElements(Stage stage){
//Create container (note: Has to be created after adding all the other objects in order to use transparency (I know, javaFX can be crappy))
Box container = new Box(Wrapper.CONTAINER_WIDTH, Wrapper.CONTAINER_HEIGHT, Wrapper.CONTAINER_DEPTH);
container.setTranslateX(Wrapper.CONTAINER_WIDTH/2);
container.setTranslateY(Wrapper.CONTAINER_HEIGHT/2);
container.setTranslateZ(Wrapper.CONTAINER_DEPTH/2);
container.setMaterial(container_material);
threeDGroup.getChildren().add(container);
//Setup camera (so that you can have the container at the origin and can still see it well
//The +threeDOffsetLeft comes from the compensation for the 2D subscene on the left
camera.setTranslateX(-SCREEN_WIDTH/2+Wrapper.CONTAINER_WIDTH/2+threeDOffsetLeft);
camera.setTranslateY(-SCREEN_HEIGHT/2+Wrapper.CONTAINER_HEIGHT/2);
camera.setTranslateZ(-Wrapper.CONTAINER_DEPTH/0.5);
//Setup mouse rotation
initMouseControl(threeDGroup, mainScene, stage);
//Set eventListener for mode selection
modeSelection.getSelectionModel().selectedItemProperty().addListener((v, oldValue, newValue) -> {
//check what mode was selected and show the corresponding options
if(newValue.equals("Parcels")){
//remove other option
if(oldValue.equals("Pentominoes")){
topGrid.getChildren().removeAll(LPentominoAmountLabel, PPentominoAmountLabel, TPentominoAmountLabel, LPentominoAmountTextField, PPentominoAmountTextField, TPentominoAmountTextField, LPentominoValueLabel, PPentominoValueLabel, TPentominoValueLabel, LPentominoValueTextField, PPentominoValueTextField, TPentominoValueTextField);
}
//add labels
topGrid.add(ParcelAAmountLabel, 0, 2);
topGrid.add(ParcelBAmountLabel, 0, 4);
topGrid.add(ParcelCAmountLabel, 0, 6);
topGrid.add(ParcelAValueLabel, 0, 3);
topGrid.add(ParcelBValueLabel, 0, 5);
topGrid.add(ParcelCValueLabel, 0, 7);
//add text fields
topGrid.add(ParcelAAmountTextField, 1, 2);
topGrid.add(ParcelBAmountTextField, 1, 4);
topGrid.add(ParcelCAmountTextField, 1, 6);
topGrid.add(ParcelAValueTextField, 1, 3);
topGrid.add(ParcelBValueTextField, 1, 5);
topGrid.add(ParcelCValueTextField, 1, 7);
} else if (newValue.equals("Pentominoes")){
//remove other option
if(oldValue.equals("Parcels")){
topGrid.getChildren().removeAll(ParcelAAmountLabel, ParcelBAmountLabel, ParcelCAmountLabel, ParcelAAmountTextField, ParcelBAmountTextField, ParcelCAmountTextField, ParcelAValueLabel, ParcelBValueLabel, ParcelCValueLabel, ParcelAValueTextField, ParcelBValueTextField, ParcelCValueTextField);
}
//add labels
topGrid.add(LPentominoAmountLabel, 0, 2);
topGrid.add(PPentominoAmountLabel, 0, 4);
topGrid.add(TPentominoAmountLabel, 0, 6);
topGrid.add(LPentominoValueLabel, 0, 3);
topGrid.add(PPentominoValueLabel, 0, 5);
topGrid.add(TPentominoValueLabel, 0, 7);
//add text fields
topGrid.add(LPentominoAmountTextField, 1, 2);
topGrid.add(PPentominoAmountTextField, 1, 4);
topGrid.add(TPentominoAmountTextField, 1, 6);
topGrid.add(LPentominoValueTextField, 1, 3);
topGrid.add(PPentominoValueTextField, 1, 5);
topGrid.add(TPentominoValueTextField, 1, 7);
}
});
//Set evenListener for start button
startButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event-> {
//Show loading circle (that was created at the start)
topGrid.add(pin, 0, 9);
//TODO use values from the textFields as input
//TODO start calculations
//TODO remove after testing
test.giveInput();
});
threeD.setCamera(camera);
stage.setTitle("Filling 3D objects");
threeD.setFill(BACKGROUND_COLOR);
stage.setScene(mainScene);
stage.show();
}
From the angle that works as desired is looks like this:
From the angle that doesn't work properly it looks like this:
Note that the boxes are added as UIParcel, this is just a class that extends the regular Box with some extra info, it doesn't effect any 3D stuff.

The solution was to also enable depth buffering for the SubScene that contained the 3D elements, it doesn't just follow the settings from the mainScene.
threeD = new SubScene(threeDGroup, SCREEN_WIDTH*.8, SCREEN_HEIGHT);
becomes
threeD = new SubScene(threeDGroup, SCREEN_WIDTH*.8, SCREEN_HEIGHT, true, SceneAntialiasing.BALANCED);
Setting the SceneAntialiasing is also required by the SubScene constructor.

Related

JavaFX animation on canvas

I'm a newbie of Java. I tried to make a simple 'binary search tree' program. I have a problem during making so I'm looking for the answer.
When the program was looking for correct place where I added a number in, I wanted to put 'flickering' function during processing, but it works like this. enter image description here
(It's not flickering but just multiplying.)
How can I figure this problem out?
Here is 'add' method that I wrote in controller.
public void handleAddAction(ActionEvent event) {
System.out.println("add ? ?");
String key = addfield.getText();
int length = key.length();
if ( length > 0 ) {
boolean integerornot = isStringInteger(key, 10);
if ( integerornot == true ) {
int intkey = Integer.parseInt(key);
if (bst.size() > 10) {
Alert maxerror = new Alert(Alert.AlertType.WARNING);
maxerror.setTitle("Message");
maxerror.setHeaderText("The maximum number of nodes is 10.");
maxerror.showAndWait();
}else if(bst.contains(intkey)!=null) {
Alert duperror = new Alert(Alert.AlertType.WARNING);
duperror.setTitle("Message");
duperror.setHeaderText("Duplicated numbers cannot be added.");
duperror.showAndWait();
}else if (intkey>=0 && intkey <= 9) {
bst.insert(intkey);
addfield.setText("");
DoubleProperty x = new SimpleDoubleProperty();
DoubleProperty y = new SimpleDoubleProperty();
compareNode(bst.root,intkey);
gc.setStroke(Color.rgb(15, 76, 129));
gc.setFill(Color.WHITE);
gc.fillOval(width-10, height-15, 25, 25);
gc.strokeOval(width-10, height-15, 25, 25);
gc.setFill(Color.rgb(15, 76, 129));
gc.fillText(key, width, height);
if(bst.size()>1) {
gc.strokeLine(width-ratiowidth, height-50 +(25/2), width-ratiowidth, height -50 +(25/2) +10);
gc.strokeLine(width-ratiowidth, height-50 +(25/2)+10, width, height -50 +(25/2) +10);
gc.strokeLine(width, height-50 +(25/2) +10, width, height -(25/2));
gc.fillPolygon(new double [] {width-5, width, width+5}, new double[] {height -(25/2) -10, height -(25/2), height -(25/2)-10}, 3);
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0),
new KeyValue(x, width-ratiowidth),
new KeyValue(y, height-50)
),
new KeyFrame(Duration.millis(10),
new KeyValue(x, width),
new KeyValue(y, height)
)
);
// timeline.setCycleCount(Timeline.INDEFINITE);
AnimationTimer timer = new AnimationTimer() {
public void handle(long now) {
gc.setStroke(Color.BLUE);
gc.strokeOval(x.doubleValue(), y.doubleValue(), 30, 30);
}
} ;
timer.start();
timeline.play();
}
prekey = intkey;
height = 20;
width = 740;
ratiowidth = 740;
} else {
Alert inerror = new Alert(Alert.AlertType.WARNING);
inerror.setTitle("Message");
inerror.setHeaderText("Only numbers from 0 to 9 can be added.");
inerror.showAndWait();
}
}else {
Alert string = new Alert(Alert.AlertType.WARNING);
string.setTitle("Message");
string.setHeaderText("Please insert integer.");
string.showAndWait();
}
}else {
Alert noinput = new Alert(Alert.AlertType.WARNING);
noinput.setTitle("Message");
noinput.setHeaderText("You did not input anything! Please insert value.");
noinput.showAndWait();
}
addfield.setText("");
}
Thank you in advance :)

Firing a Bullet Towards Mouse when Mouse is Clicked

I'm creating a top-down dungeon game and I need to fire a bullet at the mouse location when the mouse is clicked. I know how to get the coordinates of the mouse, but I am unsure of how to fire a bullet towards that location when the mouse is clicked.
public void paint(Graphics g)
{//opens paint method
super.paint(g);//allows for painting and
g.drawImage(background, xBackground, yBackground, 1380, 720, this); //Background
myCharacter(x, y, g); //Character Sprite
spriteObjectX = x; //Sets the object x of the sprite equal to the 8 bit of the sprite
spriteObjectY = y; //Sets the object y of the sprite equal to the 8 bit of the sprite
sprite(g);
wallOne(g);
wallTwo(g);
wallThree(g);
wallFour(g);
wallOneTop(g);
wallOneBottom(g);
wallOneLeft(g);
wallOneRight(g);
wallTwoTop(g);
wallTwoBottom(g);
wallTwoLeft(g);
wallTwoRight(g);
wallThreeTop(g);
wallThreeBottom(g);
wallThreeLeft(g);
wallThreeRight(g);
wallFourTop(g);
wallFourBottom(g);
wallFourLeft(g);
wallFourRight(g);
//
sprite = new Rectangle(spriteObjectX, spriteObjectY, spriteObjectW, spriteObjectH);
//
wallOne = new Rectangle(wallOneX, wallOneY, wallOneW, wallOneH);
wallTwo = new Rectangle(wallTwoX, wallTwoY, wallTwoW, wallTwoH);
wallThree = new Rectangle(wallThreeX, wallThreeY, wallThreeW, wallThreeH);
wallFour = new Rectangle(wallFourX, wallFourY, wallFourW, wallFourH);
//
wallOneTop = new Rectangle(wallOneX, wallOneY, wallOneW, 1);
wallOneBottom = new Rectangle(wallOneX, (wallOneY + wallOneH), wallOneW, 1);
wallOneLeft = new Rectangle(wallOneX, wallOneY, 1, wallOneH);
wallOneRight = new Rectangle((wallOneX + wallOneW), wallOneY, 1, wallOneH);
wallTwoTop = new Rectangle(wallTwoX, wallTwoY, wallTwoW, 1);
wallTwoBottom = new Rectangle(wallTwoX, (wallTwoY + wallTwoH), wallTwoW, 1);
wallTwoLeft = new Rectangle(wallTwoX, wallOneY, 1, wallTwoH);
wallTwoRight = new Rectangle((wallTwoX + wallTwoW), wallTwoY, 1, wallTwoH);
wallThreeTop = new Rectangle(wallThreeX, wallThreeY, wallThreeW, 1);
wallThreeBottom = new Rectangle(wallThreeX, (wallThreeY + wallThreeH), wallThreeW, 1);
wallThreeLeft = new Rectangle(wallThreeX, wallThreeY, 1, wallThreeH);
wallThreeRight = new Rectangle((wallThreeX + wallThreeW), wallThreeY, 1, wallThreeH);
wallFourTop = new Rectangle(wallFourX, wallFourY, wallFourW, 1);
wallFourBottom = new Rectangle(wallFourX, (wallFourY + wallFourH), wallFourW, 1);
wallFourLeft = new Rectangle(wallFourX, wallFourY, 1, wallFourH);
wallFourRight = new Rectangle((wallFourX + wallFourW), wallFourY, 1, wallFourH);
mouseX = MouseInfo.getPointerInfo().getLocation().x; //Finding the x of the mouse
mouseY = MouseInfo.getPointerInfo().getLocation().y; //Finding the y of the mouse
g.setColor(Color.red);
g.drawLine(x + 90, y + 50, MouseInfo.getPointerInfo().getLocation().x - 8, MouseInfo.getPointerInfo().getLocation().y - 30); //Drawing a line from the player's gun to the mouse
repaint();//allows for repainting to look normal
}//close paint method
Here's my paint method
Here's how you calculate the trajectory from the bullet to the mouse.
Point get_trajectory(Point mouse,Point bullet){
return new Point(mouse.getX()-bullet.getX(),mouse.getY()-bullet.getY());
}
And in your game loop you should call this
void bullet_go_to(Point point){
Point trajectory=get_trajectory(mouseLocation,bullet);
bullet.x+=trajectory.getX();
bullet.y+=trajectory.getY();
}
You know how to find mouseLocation so in essence this is it.

Vaadin add Grid in table

I have the following code:
GridLayout grid = new GridLayout(3, 3);
grid.addComponent(btnRemove, 0, 0);
grid.addComponent(lblIstMenge, 1, 0);
grid.addComponent(btnAdd, 2, 0);
int i = 0;
if (vList != null && vList.size() > 0)
{
for (VTr component : vList)
{
String transactionTypeName = component.getTransactionTypeName();
transaktionTable.addItem(new Object[]{++transaktionTableCounter + "",
transactionTypeName,
"123123123123123", grid, "Bemerkung^^^"},
transaktionTableCounter);
// System.out.println("Grid: " + grids.get(i));
}
}
Which gives me something like this:
So the grid is added only in the last column. I have tried creating different grids for each column in a list but this did not work for me.
If you have any ideas or recommendations it would be nice.
When I move the instantiation of the buttons and grids inside the for loop it is working as expected.
int i = 0;
if (vList != null && vList.size() > 0)
{
for (VTr component : vList)
{
btnAdd = new Button();
btnAdd.setIcon(new ThemeResource("images/btnIncrease.png"));
btnRemove = new Button();
btnRemove.setIcon(new ThemeResource("images/btnDescrease.png"));
GridLayout grid = new GridLayout(3, 3);
grid.addComponent(btnRemove, 0, 0);
grid.addComponent(lblIstMenge, 1, 0);
grid.addComponent(btnAdd, 2, 0);
String transactionTypeName = component.getTransactionTypeName();
transaktionTable.addItem(new Object[]{++transaktionTableCounter + "", transactionTypeName,
"123123123123123", grid, "Bemerkung^^^"}, transaktionTableCounter);
}
}

Java: implementing if statement with switch cases, ArrayIndexOutOfBoundsException

Stack Trace Hi i'm working on a GUI for monopoly and i've reached a stage where i need to get user input that would ask for a specific number of players and would provide a certain number of tokens (monopoly pieces) based on the number of players specified. I've currently hit a problem i feel really shouldn't be as serious as it is where if i do try to specify the number of players for the game i'm hit with a an ArrayIndexOutOfBoundsException and i can't seem to identify where or what is wrong and how to fix it. Thanks for the help in advance and any edits or tips for my code to make it more efficient are also welcome. I will attach all necessary program files.
P.s i posted the full source code as i felt it was necessary as a shortened version wouldn't make things as clear. Thanks again. P.p.s the code does work when i specify the number of players in the source code without asking for user input but stops working when i do specify user input. Monopoly Board Image
package sprint_One;
/*
* Code written by: lagosBoys A layered pane was used to place all components on the frame at the
* desired locations
*/
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
public class UI_Monopoly_Board extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
// Array of coordinates for the position of each square on the board
Point[] locations = {new Point(630, 643), new Point(570, 643), new Point(510, 643),
new Point(450, 643), new Point(390, 643), new Point(330, 643), new Point(270, 643),
new Point(210, 643), new Point(150, 643), new Point(95, 643), new Point(60, 643),
new Point(60, 573), new Point(60, 503), new Point(60, 433), new Point(60, 383),
new Point(60, 323), new Point(60, 273), new Point(60, 213), new Point(60, 153),
new Point(60, 93), new Point(60, 33),
new Point(120, 13), new Point(180, 13), new Point(230, 13), new Point(280, 13),
new Point(340, 13), new Point(400, 13), new Point(460, 13), new Point(520, 13),
new Point(580, 13), new Point(660, 60), new Point(660, 120), new Point(660, 160),
new Point(660, 220), new Point(660, 280), new Point(660, 340), new Point(660, 400),
new Point(660, 460), new Point(660, 520), new Point(660, 580), new Point(660, 640)};
// The default position or starting point which is go
Point defaultPosition = new Point(600, 603);
private int players;
private Token[] token;
private static JPanel infoPanel;
private static JPanel commandPanel;
// creates a fixed length for the text field used by the command field
final static int field_Width = 20;
private static JTextField commandField = new JTextField(field_Width);
private static JLabel commandLabel = new JLabel("Enter Command: ");
private Border blackLineBorder;
private final int ROWS = 35;
private final int COLUMNS = 40;
private JTextArea textArea = new JTextArea(ROWS, COLUMNS);
private static JLabel echoed_Text_Label = new JLabel();
private JLayeredPane layeredPane = getLayeredPane(); // The use of a JLayeredPane allows easier
// and more flexible specification of
// component positions
private static JLabel monopolyImageLabel;
public UI_Monopoly_Board() {
String playerNumber = JOptionPane.showInputDialog("Please enter the number of players");
// int tokenNumber = Integer.parseInt(playerNumber);
// players = 6;
players = Integer.parseInt(playerNumber);
int offset = 10;
// Initialise tokens depending on number of players and spaces them out with offset
if(players >= 2 || players <= 6)
{
token = new Token[players];
switch (players) {
case 2:
token[0] = new Token();
token[0].setBounds(10, 10, 700, 700);
token[0].setPosition(600, 603);
token[1] = new Token(Color.red, null);
token[1].setBounds(10, 10, 700, 700);
token[1].setPosition(600 + offset, 603 + offset);
break;
case 3:
token[0] = new Token();
token[0].setBounds(10, 10, 700, 700);
token[0].setPosition(600, 603);
token[1] = new Token(Color.red, null);
token[1].setBounds(10, 10, 700, 700);
token[1].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[2] = new Token(Color.blue, null);
token[2].setBounds(10, 10, 700, 700);
token[2].setPosition(600 + offset, 603 + offset);
break;
case 4:
token[0] = new Token();
token[0].setBounds(10, 10, 700, 700);
token[0].setPosition(600, 603);
token[1] = new Token(Color.red, null);
token[1].setBounds(10, 10, 700, 700);
token[1].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[2] = new Token(Color.blue, null);
token[2].setBounds(10, 10, 700, 700);
token[2].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[3] = new Token(Color.green, null);
token[3].setBounds(10, 10, 700, 700);
token[3].setPosition(600 + offset, 603 + offset);
break;
case 5:
token[0] = new Token();
token[0].setBounds(10, 10, 700, 700);
token[0].setPosition(600, 603);
token[1] = new Token(Color.red, null);
token[1].setBounds(10, 10, 700, 700);
token[1].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[2] = new Token(Color.blue, null);
token[2].setBounds(10, 10, 700, 700);
token[2].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[3] = new Token(Color.green, null);
token[3].setBounds(10, 10, 700, 700);
token[3].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[4] = new Token(Color.yellow, null);
token[4].setBounds(10, 10, 700, 700);
token[4].setPosition(600 + offset, 603 + offset);
break;
case 6:
token[0] = new Token();
token[0].setBounds(10, 10, 700, 700);
token[0].setPosition(600, 603);
token[1] = new Token(Color.red, null);
token[1].setBounds(10, 10, 700, 700);
token[1].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[2] = new Token(Color.blue, null);
token[2].setBounds(10, 10, 700, 700);
token[2].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[3] = new Token(Color.green, null);
token[3].setBounds(10, 10, 700, 700);
token[3].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[4] = new Token(Color.yellow, null);
token[4].setBounds(10, 10, 700, 700);
token[4].setPosition(600 + offset, 603 + offset);
offset = offset + 10;
token[5] = new Token(Color.cyan, null);
token[5].setBounds(10, 10, 700, 700);
token[5].setPosition(600 + offset, 603 + offset);
break;
default:
System.out.println("Invalid number of players");
}
}
// The location of the image should be specified here
monopolyImageLabel =
new JLabel(new ImageIcon(this.getClass().getResource("Monopoly_board.jpg")));
monopolyImageLabel.setBounds(-50, -30, 800, 750);
// The image and the tokens are added to the pane at different levels allowing them to overlap
layeredPane.add(monopolyImageLabel);
layeredPane.add(token[0], new Integer(1));
layeredPane.add(token[1], new Integer(2));
layeredPane.add(token[2], new Integer(3));
layeredPane.add(token[3], new Integer(4));
layeredPane.add(token[4], new Integer(5));
layeredPane.add(token[5], new Integer(6));
setSize(1500, 750);
setExtendedState(JFrame.MAXIMIZED_BOTH); // Sets the default window for the JFrame as a
// maximised
this.setResizable(false);
setTitle("Welcome to Monopoly");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Ensures the JFrame operation ends completely
// upon exiting the window
setVisible(true);
}
// This method displays the information panel and adds it to the pane
public void information_Panel() {
infoPanel = new JPanel();
JScrollPane scrollPane = new JScrollPane(textArea);
blackLineBorder = BorderFactory.createLineBorder(Color.BLACK);
TitledBorder title = BorderFactory.createTitledBorder(blackLineBorder, "Information Panel");
infoPanel.setBorder(title);
infoPanel.add(echoed_Text_Label, BorderLayout.NORTH);
// prevents any information from being added or deleted from the information panel.
textArea.setEditable(false);
infoPanel.add(scrollPane);
infoPanel.setBounds(750, 0, 600, 600); // specifies the desired coordinates of the panel being
// added to the layered pane
layeredPane.add(infoPanel);
}
// This method displays the command panel and adds it to the pane
public void command_Panel() {
commandPanel = new JPanel();
blackLineBorder = BorderFactory.createLineBorder(Color.BLACK);
JButton button = new JButton("Enter");
/*
* implements the actionlistener interface on the button to help execute a command when the
* button is clicked
*/
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (commandField.getText().isEmpty()) {
String command = null;
textArea.append(command);
}
else {
String command = commandField.getText();
textArea.append(command + "\n");
commandField.setText("");
}
}
});
// This invokes the actionListeners interface for actionPerformed (quick way to implement a key
// listener on the keyboards Enter button)
getRootPane().setDefaultButton(button);
commandPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
button.setPreferredSize(new Dimension(65, 20));
commandPanel.add(commandLabel);
commandPanel.add(commandField);
commandPanel.add(button);
commandPanel.setBounds(800, 630, 500, 50); // specifies the desired coordinates of the panel
// being added to the layered pane
layeredPane.add(commandPanel);
}
// Method which moves the tokens round the board one at a time
public void moveTokens() throws InterruptedException {
int i, j, offset;
offset = 0;
for (i = 0; i < token.length; i++) {
for (j = 0; j < locations.length; j++) {
token[i].setPosition(locations[j].x, locations[j].y);
repaint();
// controls the movement speed of the tokens across the board allowing for easy detection of
// their movement
Thread.sleep(300);
}
token[i].setPosition(defaultPosition.x + offset, defaultPosition.y + offset);
offset = offset + 15;
}
}
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
UI_Monopoly_Board obj = new UI_Monopoly_Board();
obj.information_Panel();
obj.command_Panel();
obj.moveTokens();
[enter image description here][1]
}
}
package sprint_One;
import java.awt.*;
import javax.swing.JComponent;
/*
* Each token has variables for location, dimension and shape, there's a constructor that allows the
* user to specify the colour of the shape the necessary accessor and mutator functions are provided
*/
public class Token extends JComponent {
/**
*
*/
private static final long serialVersionUID = 1L;
private int length;
private int breadth;
private int x;
private int y;
private Shape shape;
private Color color;
private String name;
private int balance;
public Token() {
super();
setVisible(true);
this.length = 15;
this.breadth = 15;
this.x = 5;
this.y = 5;
this.shape = new Rectangle(this.x, this.y, this.length, this.breadth);
this.color = Color.BLACK;
this.name = "";
this.balance = 20;
}
public Token(Color color, String name) {
this();
this.color = color;
this.name = name;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
// Method which specifies the x and y coordinates of the tokens
public void setPosition(int x, int y) {
this.x = x;
this.y = y;
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g);
g2.setColor(color);
g2.fill(shape); // fills the shape with the colour specified
g2.draw(this.shape);
}
public Shape getShape() {
// TODO Auto-generated method stub
return this.shape;
}
}
Ok, you should learn how to use a debugger...
This is the line that causes your error:
layeredPane.add(token[2], new Integer(3));
And you initialise tokenlike this:
if(players >= 2 || players <= 6)
{
token = new Token[players];
So, what if players is 2? You will get an ArrayIndexOutOfBoundsException.
Another tip:
layeredPane.add(token[0], new Integer(1));
is not as readable as
layeredPane.add(token[0], 1);

Sash becomes lost after resize

I have an application that I have created a sash for, so that users can resize the Styled Text objects as they choose. I have a bug though that if the application is maximized, the sash is moved very low on the application, and then the user un-maximizes the application, the sash is then still beyond the bounds of the screen.
How can I make it so that when the user changes the application from maximized, to a smaller size, the sash automatically moves within the bounds of the application size; as in the first picture?
Also, is there a better (more dynamic) way to control the position limits for the sash?
separator.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
double height = shlPstmKnowledgeCatalogue.getBounds().height;
double qpBtnHeight = btnQuickParts.getBounds().height;
double workLblHeight = lblWorkInstructions.getBounds().height;
if (!shlPstmKnowledgeCatalogue.getMaximized()) {
if (event.y < workLblHeight + 30) {
event.y = (int) workLblHeight + 30;
}
else if (event.y > height - qpBtnHeight - 90) {
event.y = (int) (height - qpBtnHeight - 90);
}
}
else {
if (event.y < workLblHeight + 30) {
event.y = (int) (workLblHeight + 30);
}
else if (event.y > height - qpBtnHeight - 90) {
event.y = (int) (height - qpBtnHeight - 90);
}
}
separator.setBounds(event.x, event.y, event.width, event.height);
FormData formData = new FormData();
formData.top = new FormAttachment(0, event.y);
formData.left = new FormAttachment(lblScript, 6);
formData.right = new FormAttachment(script, 0, SWT.RIGHT);
formData.height = 5;
separator.setLayoutData(formData);
/*
* Used to move the script label with the movement of the script
* text box. Otherwise, the label gets lost behind the text boxes.
*/
FormData lblScriptData = new FormData();
lblScriptData.top = new FormAttachment(0, event.y - 5);
lblScriptData.bottom = new FormAttachment(0, event.y + 12);
lblScriptData.left = new FormAttachment (workInstructions,2, SWT.LEFT);
lblScript.setLayoutData(lblScriptData);
shlPstmKnowledgeCatalogue.layout(true);
}
});
/*
* Attaches the Work Instuction text box to the sash for dynamic resizing
* The resizing is done in relation to the Script text box
*/
FormData workInstForm = new FormData();
workInstForm.left = new FormAttachment(0, 194);
workInstForm.right = new FormAttachment(100, -6);
workInstForm.bottom = new FormAttachment(separator, -15);
workInstForm.top = new FormAttachment(lblWorkInstructions, 7);
workInstructions.setLayoutData(workInstForm);
formToolkit.adapt(workInstructions, true, true);
/*
* Attaches the Script text box to the sash for dynamic resizing
* The resizing is done in relation to the work instruction text box
*/
FormData scriptForm = new FormData();
scriptForm.top = new FormAttachment(separator, 15);
scriptForm.right = new FormAttachment(workInstructions, 0, SWT.RIGHT);
scriptForm.left = new FormAttachment(workInstructions, 0, SWT.LEFT);
scriptForm.bottom = new FormAttachment(btnQuickParts, -6);
script.setLayoutData(scriptForm);
formToolkit.adapt(script, true, true);
I ended up writing a separate method to constantly check the position of the sash. Maybe it is not the most efficient way of doing it, but it does work!
/**
* Check the sash position to verify that it is within the bounds of the shell.
* This is primarily used when the user maxmimizes the application, moves the
* sash, then minimizes the application.
*/
private void checkSashPosition() {
if (!shlPstmKnowledgeCatalogue.isDisposed() && separator.getBounds().y > shlPstmKnowledgeCatalogue.getBounds().height) {
separator.setLocation(235, shlPstmKnowledgeCatalogue.getBounds().height - 248);
workInstructions.setSize(455, 100);
script.setSize(455, 130);
script.setLocation(194, 167);
lblScript.setLocation(194, 143);
}
}
The method is called inside of a while-loop, and the objects that are relative to the sash are also adjusted.

Categories