I'm creating a drawing application, where the user clicks on a button to select which shape to draw - node for example - and then the shape is placed where the mouse is clicked .
I want the user to be able to click on two different "shapes" on the screen to create a link between them.
Every node I create is added to an ArrayList of Nodes. I have a for-loop to iterate through the nodes, and I created a function contains in my class NODE:
boolean contains(Point point) {
if((point.x >= centerX-radius) && (point.x <= centerX+radius) &&
(point.y <= centerY+radius) && (point.y>=centerY-radius))
return true;
else
return false;
}
because component.contains(point) did not work, and I think I'm able to get the first node that's clicked, but I'm still struggling with identifying to two clicks the other node.
Any help would be appreciated.
I think you need to keep an additional variable, to know if the click is first or second.. In this case, it might be useful to keep the Node selected with first click..
So, in pseudo-code:
Node selected;
onClick() {
Node clicked = findNode();
if (clicked == null || clicked == selected) {
selected = null;
} else
if (selected == null) {
selected = clicked;
} else {
createLine(selected, clicked);
selected = null;
}
}
To get mouse coordinates, getX() and getY() functions are used inside the onmouseClicked(MouseEvent me) function.
Related
So for a school project, I have to create a game with a program called 'Processing'.
I am creating a main menu with the switch statement. For that I want to use the buttons 'Start', 'Help', and 'exit'.i would like to use those buttons to change the variables of the switch statement. Therefore I'm using "mousePressed". The problem is that which button I'm pressing, is giving me the same result as the 'exit' button. Could somebody give me tips on how I can structure my menu better or even make my button work? I am using a library on Processing called 'ControlP5' to make my buttons.
here is my code so far:
int mode; // 1: intro screen, 2: game , 3: game over
final int INTRO = 1;
final int PLAY = 2;
final int GAMEOVER = 3;
//==============================================================
void setup(){
size(1920,1080);
mode = 1;
}
//========================================================
void draw(){
if(mode == 1){
introScreen();
}
else if (mode == 2){
gameItself();
}
else if (mode == 3){
gameOver();
}
else println("mode error");{
}
}
void introScreen(){
mode = 1;
static int Page = 0;
import controlP5.*;
ControlP5 cp5;
cp5= new ControlP5(this);
switch(Page){
case 0: // main menu
cp5.addButton("Start").setValue(0).setPosition(1420,250).setSize(400,100);
cp5.addButton("Exit").setValue(0).setPosition(1420,650).setSize(400,100);
cp5.addButton("Help").setValue(0).setPosition(1420,450).setSize(400,100);
break;
case 1: //help menu
cp5.addButton("Back").setValue(0).setPosition(1420,450).setSize(400,100);
break;
}
public void Start(){
if(mousePressed){
mode = 2; // switching to the game itself
}
println("Start");
}
public void Exit(){
if(mousePressed){
exit(); }
println("Exit");
}
public void Help(){
Page = 1;
println("Help");
}
public void Back(){
if(mousePressed){
Page = 0;
}
println("Back");
}
void gameItself(){
// game and stuff
}
void gameOver(){
//gameover
}
Take a look at how the mousePressed event works. You may use this information useful.
To achieve your goal as to change the Page variable by clicking buttons, there are multiple options. First, I'll go with the easier one, the one which doesn't need an import but just check for coordinates. Then I'll do the same thing, but with controlP5.
1. Just checking where the clicks lands
I'll go with the most basic one: detecting the "click" and checking if it's coordinates are inside a button.
First, we'll add the mouseClicked() method. This method is called every time a mouse button is pressed.
// I'm typing this out of IDE si there may be some quirks to fix in the code
void mouseClicked() {
switch(Page) {
case 0:
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 250 && mouseY < 250+100) {
// You're in the main menu and Start was clicked
}
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 650 && mouseY < 650+100) {
// You're in the main menu and Exit was clicked
}
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 450 && mouseY < 450+100) {
// You're in the main menu and Help was clicked
}
// You should use 'else if' instead of 3 different if, but I coded it like that so it would be easier to see the small differences between the coordinates
case 1:
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 450 && mouseY < 450+100) {
// You're un the help menu and Back was clicked
}
}
}
As you can see, I just used the coordinates and size of your buttons to check if the click was located inside one. That's kind of ninja-ing my way out of this issue. I don't know how far into programming you are, or else I would recommand to build a class to handle user inputs, but this way is easy to manage for small exercises like homework.
2. Designing controlP5 buttons
I'm not a ControlP5 expert, so we'll keep close to the basics.
I'll be blunt, the code you provided is ripe with problems, and it's not so many lines, so instead of pointing where it goes wrong I'll give you some skeleton code which will work and on which you can build some understanding. I'll give you the tools and then you can make your project work.
When you design your buttons, if you design them all in the same object, they'll share some properties. For an example, all your buttons will be visible or invisible at the same time. You don't need to redraw them all the time, because they already handle this, so you need to manage them with another method.
You should design your buttons as global objects (as you did), and add them to the ControlP5 object which makes the most sense. You can have one button per object if you want, or many if they are linked together, for an example all the "menu" buttons which appears at the same time could be owned by the same object. Design your buttons in the setup() method if you design them only one time for the whole program. Of course, if this was more than an homework, you may want to avoid the buttons being globals, but it'll be much easier to keep them in memory for a short project.
The "name" of the button is also the name of the method that it'll try to call if you click on it. Two buttons cannot share the same "name". Buttons can have a set value which will be sent to the method that they call.
You don't need to use Processing's mouse events for the buttons to work. They are self-contained: they have their own events, like being clicked on or detecting when the mouse is over them. Here's the documentation for the full list of the methods included in the ControlP5 buttons.
You don't need to manage the buttons in the draw() loop. They manage themselves.
Here's some skeleton code to demonstrate what I just said. You can copy and paste it in a new Processing project and run it to see what's going on.
ControlP5 cp5;
ControlP5 flipVisibilityButton;
int Page = 0;
void setup() {
size(1920, 800);
textAlign(CENTER, CENTER);
textSize(60);
fill(255);
cp5 = new ControlP5(this); // this is ONE object, which will own buttons.
cp5.addButton("MenuButton0") // this is the name of the button, but also the name of the method it will call
.setValue(0) // this value will be sent to the method it calls
.setPosition(1420, 250)
.setSize(400, 100);
cp5.addButton("MenuButton1")
.setValue(1)
.setPosition(1420, 450)
.setSize(400, 100);
cp5.addButton("MenuButton2")
.setValue(2)
.setPosition(1420, 650)
.setSize(400, 100);
flipVisibilityButton = new ControlP5(this); // this is a different object which own it's own controls (a button in this case)
flipVisibilityButton.addButton("flipVisibility")
.setValue(2)
.setPosition(200, height/2)
.setSize(200, 100);
}
void draw() {
// No button management to see here
background(0);
// showing which button has been pressed while also keeping watch to see if the mouse is over one of the cp5 buttons
text(Page + "\n" + cp5.isMouseOver(), width/2, height/2);
}
void MenuButton0(int value) {
ChangePage(value);
}
void MenuButton1(int value) {
ChangePage(value);
}
void MenuButton2(int value) {
ChangePage(value);
}
void ChangePage(int value) {
Page = value;
}
void flipVisibility(int value) {
// When the buttons are invisible, they are also unclickable
cp5.setVisible(!cp5.isVisible());
}
You should be able to expand on this example to do your project, but if you have difficulties don't hesitate to comment here and ask further questions. Have fun!
My method some reason doesnt work I want it so when I click tab it grabs the mouse and moves the player but when clicked again I want it to release the mouse and stop the players rotation I tried putting a print statement into the movePlayerWithMouse method but it just returns true the only thing that does change is the mouse each time I click tab it releases and grabs any help?
Heres the method I use:
boolean movePlayerWithMouse = false;
while(Keyboard.next()) {
if(!Keyboard.getEventKeyState()) {
if(Keyboard.getEventKey() == Keyboard.KEY_TAB) {
movePlayerWithMouse = !movePlayerWithMouse;
Mouse.setGrabbed(!Mouse.isGrabbed());
}
}
}
if(movePlayerWithMouse = !movePlayerWithMouse) {
rotY -= Mouse.getDX() / SENSITIVITY;
}
I am making a chess game and need to figure out how to move the pieces. I have my pieces stored in an array squaresGrid[][] and I want to use the method moveTo to move the pieces. Currently this method simply marks a piece selected but I need it to take a second mouse click to choose the square to move the selected piece to but am not sure how best to do this.
public void actionPerformed(ActionEvent e)
{
for(int x = 0; x < 8; x++)
{
for(int y = 0; y < 8; y++)
{
if(e.getSource() == squaresGrid[x][y])
{
moveTo(e, squaresGrid[x][y]);
}
}
}
}
public void moveTo(ActionEvent e, JButton clicked)
{
clicked.setIcon(selected);
}
You don't do a "second actionPerformed". What you do is keep around state, and when a click happens, look at the state, and decide what the action should be.
For example, keep around a field called currentlySelected, pointing to the currently selected square (containing its coordinates, for example).
In the actionPerformed, when you receive a click, you look at currentlySelected.
If it is null, it means you are supposed to select the clicked square and put it in currentlySelected.
If it is not null, and the current click is in the same square, the user probably wants to de-select it. De-select and clear (put null) in currentlySelected.
If it is not null and not the same square, it means that you have to check if the move is legal. If it is legal, you can do the move, and clear currentlySelected. If it is not legal, you do what you think is the proper thing to do: perhaps de-select the original place and select the new one. Or just de-select and tell the user the move is not legal. Or keep it selected.
Remember to always clear your currentlySelected in the appropriate situations.
You don't need a second ActionListener or actionPerformed method, but rather you need a state-ful ActionListener, one that knows whether the button push represents the first push or the 2nd. A boolean variable could be all that is required for this. Another option is to use a variable to represent the first pushed location, set it equal to null initially and then set it equal to the position on the first push. On the 2nd push check if it is null or non-null and if non-null, the button push represents the 2nd push. Then set it back to null.
For example
public void actionPerformed(ActionEvent e) {
for(int x = 0; x < 8; x++) {
for(int y = 0; y < 8; y++) {
if(e.getSource() == squaresGrid[x][y]) {
if (gridLocation == null) {
// class to hold x and y location
gridLocation = new GridLocation(x, y);
} else {
// use gridLocation here
int firstX = gridLocation.getX();
int firstY = gridLocation.getY();
moveTo(e, x, y, firstX, firstY);
gridLocation = null;
}
}
}
}
}
I'm trying to stop the tree from collapsing or expanding when the user double clicks a column on a tree. It should only be allowed if the user clicks on the first column.
See, if a user double clicks the checkbox on node2 world1, the tree expands or collapses. I don't want that to happen. My tree needs SWT.FULL_SELECTION to detect the clicks on each of the columns, so that's not the way to go.
My listener looks like this
tree.addTreeListener(new TreeListener() {
#Override
public void treeExpanded(TreeEvent e) {
TreeItem parent = (TreeItem) e.item;
Point p = new Point (e.x, e.y);
int column = CheckboxClickListener.getColumn(p,parent);
if (column > 0) {
e.doit = false;
}
}
#Override
public void treeCollapsed(TreeEvent e) {
TreeItem parent = (TreeItem) e.item;
Point p = new Point (e.x, e.y);
int column = CheckboxClickListener.getColumn(p,parent);
if (column != 0) {
e.doit = false;
}
}
});
Problem is, the mouse event that generated the click is not the same as the TreeEvent that expands the tree. Thus, the e.x and e.y are both zero, making my Point detection useless. Listening to the mouse event and maintaining the last x and y to check here in the TreeExpand event seems bug-prone since the user may also expand the tree using the keyboard (thus the x and y may not reflect the user action). I also considered adding a time constraint to check that but seems like a bad way to handle the issue.
How can I detect which mouse event triggered the expand event?
PS: e.doit=false does nothing, even outside the if condition, so help with stopping the tree from expanding/collapsing would be appreciated as well :)
Thank you!
I found someone saying this is a bug at this link http://www.eclipse.org/forums/index.php/t/257325/
The following code stops the tree from expanding on doubleclick but I'm not sure why or what are the side effects.
tree.addListener (SWT.MeasureItem, new Listener(){
#Override
public void handleEvent(Event event) {}
});
This stops the expanding when doubleclicking ANY column. Clicking on the small arrow at the left of the TreeItem still expands the tree (as it should).
I am working on doing a word finder puzzle game. When I am trying to get to happen is a user clicks on a letter then moves his mouse across other letters to create a word. I am having some problems with the listeners. I have been going back and fourth using mouseDragged and mouseMoved. So far mouseMoved seems to work better because it dynamically grabs values. The problem is I can't figure out how to get it only grab one value. In an ideal world it would move of a Button or label grab that value once and ignore the value till it reaches a new button or label. Currently it just grabs values at every instant a mouse is on that container. The logic for my Mouse method is below:
public void mouseMoved(MouseEvent e) {
int count = countClicked;
int num = 0;
for(JToggleButton row : puzzleGrid){
if(e.getComponent() == row && count == 1) {
if(num == 0){
num++;
for(JLabel l: solWords)
{
sb.append(row.getText());
System.out.println(l.getText()+" = "+ sb.toString());
if(l.getText().contentEquals(row.getText()))
System.out.println(row.getText());
}
}
}
}
}
I am using the value gathered from the containers to check against an array of JLabels containing the solution values.
You could store the last letter in a static variable:
static String lastLetter = null;
mouseMoved(...) {
if(row.getText().equals(lastLetter)) {
continue;
}
lastLetter = row.getText();
}