I'm trying to make a battleship game.
Here's a link to the code: Battleship
Basically, when you click on one of the ship buttons(battleship, cruiser, submarine, etc.) a Rectangle pops up on the screen. You can move this rectangle around the screen by clicking on it and dragging the mouse around. The class that adds all of the event handlers to the Rectangle can be found in class MouseGestures.java.
Event Handlers are added to the GridPane in the GameGUI.java class starting at line 82.
Basically, I'm trying to find the index of whatever node you drag this object over in the GridPane. I'm able to accomplish this without dragging, by applying setOnMouseEntered to each node in the gridpane, but when I try to utilize setOnMouseDragEntered, I get nothing.
Would anyone have an idea for how to get this to work?
Just to reiterate, I want to print in the console the index of each gridpane when I drag and move a node over the nodes contained in the gridpane.
These are the event handlers I have applied to the nodes in the gridpane.
for (int i=0; i<=11; i++) {
for (int j=0; j<=11; j++) {
int colIndex = i;
int rowIndex = j;
grid2[i][j] = new Rectangle();
grid2[i][j].setStroke(Color.BLACK);
grid2[i][j].setFill(null);
grid2[i][j].setStrokeWidth(1);
grid2[i][j].setWidth(30);
grid2[i][j].setHeight(30);
//Prints index of each grid2[][] upon mouse entry.
grid2[i][j].setOnMouseEntered( e -> {
System.out.printf("Mouse entered cell [%d, %d]%n", colIndex, rowIndex);
});
//Does not work! Want to print index of each grid2[][] upon mouse drag enter.
grid2[i][j].setOnMouseDragEntered( e -> {
System.out.printf("Mouse entered cell [%d, %d]%n", colIndex, rowIndex);
});
//Does not work! Want to print index of each grid2[][] upon mouse drag over.
grid2[i][j].setOnMouseDragOver( e -> {
System.out.printf("Mouse entered cell [%d, %d]%n", colIndex, rowIndex);
});
These are the event handlers for the object you create when you push one of the buttons.
private EventHandler<MouseEvent> onMousePressedEventHandler = event -> {
if (event.getSource() instanceof Rectangle) {
shipSelected = (Rectangle) (event.getSource());
dragContext.x = shipSelected.getTranslateX() - shipSelected.getWidth()/2;
dragContext.y = shipSelected.getTranslateY() - shipSelected.getHeight()/2;
}
};
private EventHandler<MouseEvent> onMouseDragDetectedEventHandler = event -> {
shipSelected.startFullDrag();
System.out.println("startfulldrag");
};
private EventHandler<MouseEvent> onMouseDraggedEventHandler = event -> {
if (event.getSource() instanceof Rectangle) {
shipSelected = (Rectangle) (event.getSource());
shipSelected.setX(dragContext.x + event.getX());
shipSelected.setY(dragContext.y + event.getY());
}
};
You need to make the Rectangle you move around mouse transparent with setMouseTransparent(true) while you are dragging it.
private EventHandler<MouseEvent> onMouseDragDetectedEventHandler = event -> {
shipSelected.startFullDrag();
shipSelected.setMouseTransparent(true)
System.out.println("startfulldrag");
};
Otherwise, the Rectangle is always the top-most element under your mouse pointer, and you will not get dragEntered events from the elements below (i.e. the grid).
Of course, do not forget to set mouse transparency back to false, when you ended dragging.
Related
I have a combo box which shows various items. I would like to change the tooltip text depending on the item under the mouse pointer. Since I cannot set a tooltip for each item, I need to change the tooltip for the combo box.
How do I get the item under the mouse pointer? I can set up an event for tracking mouse movement, and then get the Point for the mouse, however I cannot find a method to get the item in the combo matching the Point location.
A Tree has this:
private class KeyTreeMouseMoveListener implements MouseMoveListener
{
#Override
public void mouseMove( MouseEvent event )
{
TreeItem item = tree.getItem( new Point( event.x, event.y ) );
}
}
But I cannot find a similar method for a Combo box.
Something like:
private class ComboMouseMoveListener implements MouseMoveListener
{
#Override
public void mouseMove( MouseEvent event )
{
int index = combo.getIndex( new Point( event.x, event.y ) );
}
}
would be nice :-)
Ok, it's kind of ugly, and kind of bad practice, so don't try this at home...
private class ComboModifyListener implements ModifyListener
{
#Override
public void modifyText( ModifyEvent e )
{
<code to get the selected item>
combo.setToolTipText( "item tooltip text" );
// ugly part
ivShell.getDisplay().setCursorLocation(
ivShell.getLocation().x + combo.getLocation().x + 15,
ivShell.getLocation().y + combo.getLocation().y + 35 );
}
}
So AFTER the user chooses an item, I get the item, set the combo tooltip, and then move the cursor so it is now over the combo box. The x + 15 and y + 35 are SWAG offsets from the top/left corner of the combo box.
Yes, I know its bad practice to move the cursor under program control, but it does display the tooltip of the selected item.
Background: I am trying to programmatically create a context menu on an SWT Table. I am doing it programmatically because I need to hide/show the menu based on the cell that was clicked, not the row item.
I was planning to use the x,y coordinates from the Event class to find the cell that was clicked on, so I am capturing both the untyped MouseDown event and the untyped MenuDetect event. I put logging messages into the event handlers so I could better see what was going on. Here's my code:
tree.addListener(SWT.MouseDown, new Listener() {
#Override
public void handleEvent(final Event event) {
System.out.println("Mouse down: (" + event.x + ", " + event.y + ")");
handleMouseDown(event);
}
});
tree.addListener(SWT.MenuDetect, new Listener() {
#Override
public void handleEvent(final Event event) {
System.out.println("Menu Detect: (" + event.x + ", " + event.y + ")");
handleMenuDetect(event);
}
});
With the same click, I expected to see the same results, however, my output was as follows when I clicked down a column of cells:
Mouse down: (334, 11) Menu Detect: (1270, 255)
Mouse down: (331, 37) Menu Detect: (1267, 281)
Mouse down: (329, 55) Menu Detect: (1265, 299)
Mouse down: (324, 77) Menu Detect: (1260, 321)
Mouse down: (324, 100) Menu Detect: (1260, 344)
What is going on here? Aren't they referring to the same exact point? Are they calculating the x,y from different origins?
Are they calculating the x,y from different origins?
Yes, they do.
The SWT.MenuDetect event position is the mouse position based on the whole screen, whereas the SWT.MouseDown event position is based on its composite.
That means that one tells you where on the screen the event occurred, whereas the other tells you where in the widget it occurred.
To make them use the same coordinate system (the widget's system), call Control#toControl(int, int) to map it.
tree.addListener(SWT.MouseDown, (e) -> {
System.out.println(new Point(e.x, e.y));
});
tree.addListener(SWT.MenuDetect, (e) -> {
System.out.println(tree.toControl(e.x, e.y));
});
Control#toDisplay(int, int) will do the opposite.
For reference:
MouseEvent Javadoc:
public int x
the widget-relative, x coordinate of the pointer at the time the mouse button was pressed or released
MenuDetectEvent Javadoc:
public int x
The display-relative x coordinate of the pointer at the time the context menu trigger occurred.
I am struggling with intersections i need to .getShape() on a button.
But as the API states
When null, the Region is rendered as a rounded rectangle.
that means that by default button dont have shape set.
I don't want to .setShape() on the button but to check my intersections i need to .getShape() of the button which comes back null.
Is there a way to get the default shape of the button node while .getShape() returns null ?
I have 2 .observableArrayList() buttons and circles (kind of bubbles)
private final ObservableList<Circle> circles = FXCollections.observableArrayList();
private final ObservableList<Button> buttonsList = FXCollections.observableArrayList();
private final ObjectProperty<BoundsType> selectedBoundsType = new SimpleObjectProperty<>(BoundsType.BOUNDS_IN_PARENT);
Then I add all of my buttons and circles to obs lists:
buttonsList.addAll(rootPane.getChildrenUnmodifiable()
.stream()
.filter(node -> node instanceof Button)
.map(node -> (Button) node)
.collect(Collectors.toList()));
Circles are a bit different I add them separately with a mouse click.
and then check the intersections between circles and buttons.
for (Button btn : buttonsList) {
for (Circle c : circles) {
ShapePair pair = new ShapePair(c.getShape(), btn.getShape());
if (pair.intersects(selectedBoundsType.get())) {
System.out.println("Colision");
//logic
}
}
}
but like i said the btn.getShape() gets me null ;(
Right i think it just easier to do
for (Button btn : buttonsList) {
for (Circle c : circles) {
if (btn.getBoundsInParent().intersects(b.getBoundsInParent())) {
System.out.println("Colision");
}
}
}
I'm attempting to write a GUI that presents five rectangles in a FlowPane, so that the user may click on them to select a character.
I use the following method to test whether the user has clicked inside a rectangle or not:
#FXML
private Rectangle characterA, characterB, characterC, characterD, character E;
private List<Rectangle> rects;
#FXML
private void initialize() {
rects = Arrays.asList(characterA, characterB, characterC, characterD, character E);
}
#FXML
private void onMousePressed(MouseEvent e) {
Rectangle rect;
for (int i = 0; i < rects.size(); i++) {
rect = rects.get(i);
if (rect.contains(e.getSceneX(), e.getSceneY())) {
System.out.println("Clicked in rect " + i);
}
}
}
My problem is this: although on screen, the rectangles are laid out alongside each other, their coordinates are all apparently the same. Clicking on the first rectangle results in five copies of "Clicked in rect x", whilst clicking elsewhere gives no output at all.
How can I correctly determine which rectangle the user clicked in?
Suppose I have 4 squares colored blue, white, red and green (myComponent) associated with the mouse press event. At one point, the mouse is pressed over one of them - say, the yellow one - and the event is activated.
Now, the control flux is inside the event handling function. How do I get the MyComponent - the yellow square - that caused this from here?
EDIT
I have another question. Is there a way to tell the position of the component? My problem is a bit more complicated than what I said.
Basically, I have a grid full of squares. When I click one of the squares, I have to know which one it is, so I can update my matrix. The thing is, if I calculate it myself, it only works on a given resolution.
I have a GridBagLayout, and inside it are the myComponents. I have to know which one of the components exactly - like, component[2][2] - caused the interruption.
I mean, I can tell which one of the components did it, but not where in the matrix it is located.
MouseEvent.getSource() returns the object on which the event initially occurred.
I have a GridBagLayout, and inside it
are the myComponents. I have to know
which one of the components exactly -
like, component[2][2] - caused the
interruption.
You could store the indices, e.g. (2,2), inside each myComponent when you add them to the matrix. That way, given the component, you can always identify its position in the matrix.
class MyComponent extends JButton
{
final int i; // matrix row
final int j; // matrix col
// constructor
MyComponent(String text, int i, int j)
{
super(text);
this.i = i;
this.j = j;
}
...
}
By adding a MouseListener (or alternatively, a MouseAdapter, if you don't need to override all the MouseListener' methods) to each of your colored boxes, when an event such as a mouse click occurs, theMouseListenerwill be called with a [MouseEvent`]3, which can be used to obtain the component that was clicked.
For example:
final MyBoxComponent blueBox = // ... Initialize blue box
final MyBoxComponent whiteBox = // ... Initialize white box
final MyBoxComponent redBox = // ... Initialize red box
final MyBoxComponent greenBox = // ... Initialize green box
MouseListener myListener = new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
// Obtain the Object which caused the event.
Object source = e.getSource();
if (source == blueBox)
{
System.out.println("Blue box clicked");
}
else if (source == whiteBox)
{
System.out.println("White box clicked");
}
// ... and so on.
}
};
blueBox.addMouseListener(myListener);
whiteBox.addMouseListener(myListener);
redBox.addMouseListener(myListener);
greenBox.addMouseListener(myListener);