Check location of each button - java

I have a frame that contains 81 buttons, lets say all the buttons contain no name, are all equal in size, and are all set automatically. So when I click one I would like to know which one is clicked. If I use a class that implements MouseListener and with this method
mouseClicked(MouseEvent e){
temp[0]= e.getX();
temp[1]= e.getY();
}
How can I check with these coordinates?
Do I have to set each of the buttons with its own location to do that?

I believe this is what you are looking for.
public static final int BUTTONS_WIDTH_COUNT = 9;
public static final int BUTTONS_HEIGHT_COUNT = 9;
public static final Button[][] BUTTONS = new Button[BUTTONS_WIDTH_COUNT][BUTTONS_HEIGHT_COUNT]
...
// I'll assume that the buttons are taking up the entire frame so no offsets are taken into account
frame.addMouseListener(
new MouseAdaptor() {
mouseClicked(MouseEvent e) {
// The X Y coordinates are relative to the component so
int frameWidth = frame.getBounds().getWidth();
int frameHeight = frame.getBounds().getHeight();
Button buttonClicked = buttons[e.getX()/(frameWidth/BUTTONS_WIDTH_COUNT)][e.getY()/(frameHeight/BUTTONS_HEIGHT_COUNT)];
}
}
EDIT: Actually it will be a lot better to assign the same MouseAdaptor to all the buttons and use e.getSource() to know which button was invoking in the listener.

Related

How to use the resetButton to reset parameters

Im writing a program that deals with creating a house and rearranging the neighbors (similar to game of life)
It is written in Java and it as a Reset button to restart with the current parameters.
The problem is that when i click the resetButton the whole window closes.
You can find the code at the and of the question.
These are other involved fields, so you might be able to understand the code better:
TextField to set the size of the city (number of squares on an edge).
TextFild to set the maximum percentage of neighbors not-like-you that a household will tolerate before they move. I.e., if the number is set to 70, a red house hold with 6 blue neighbors will move; a red household with 5 blue neighbors is ok according to this.
TextField to set a minimum percentage of neighbors not-like-you that a household will tolerate before they move. Make this greater than 0 for a person who LIKES diversity TextField to set the percentage of red households. Note: you can do this with probability. You do not need to have this exact percentage of red households.
TextField to set the percentage of blue households. White will be what is left over. Single step button gives every household one chance to move. You do not need to be careful about that fact that, as you progress through the city, a person early in the move chances may move to a place that later gets a chance (i.e., some households really get two or more turns).
Go button, to start and stop the program from doing steps on its own.
So my questions is how do i let those field and buttons restart with the current parameters ( restart it with what i have originally after playing a few times)
As you can see I added the resetButton to do its job but somehow it is not.
Ok it is like I run the program I have a set of numbers for red and blue as you can see in my, then when I run it it starts with those numbers. And so I keep on changing as i play, and then there is a reset button that lets me reset what I did and should bring back what it originally started with:
public final static int size = 5 and so on
This is my main program
public class Ghetto extends JFrame implements ActionListener, MouseListener,MouseMotionListener
{
protected Grids theGrid;
JButton resetButton;
javax.swing.Timer timer; // generates ticks that drive the animation
public final static int SIZE = 5;
public final static int BLUE = 10;
public final static int RED = 8;
public final static int DIVERSITY_PERCENTAGE = 70;
public static void main(String[] args)
{
new Ghetto();
}
public Ghetto() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
addMouseListener(this);
addMouseMotionListener(this);
setLayout(new FlowLayout());
theGrid = new Grids(SIZE, BLUE, RED, DIVERSITY_PERCENTAGE);
add(theGrid);
resetButton = new JButton("Reset");
add(resetButton);
resetButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
resetWithCurrent();
}
});
setSize(new Dimension(550, 600));
setVisible(true);
}
public void resetWithCurrent()
{
//this.dispose();
}
#Override
public void actionPerformed(ActionEvent e)
{
timer.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
performStep();
//if (e.getSource() == resetButton )
//{
//resetWithCurrent();
//}
}
});
}
}
Also I added this part
public class Observable{
int state = 0;
int additionalState = 0;
public final void updateState(int increment)
{
doUpdateState(increment);
notifyObservers();
}
private void notifyObservers() {
// TODO Auto-generated method stub
}
public void doUpdateState(int increment)
{
state = state + increment;
}
}
public class ConcreteObservable extends Observable{
public void doUpdateState(int increment){
super.doUpdateState(increment); // the observers are notified
additionalState = additionalState + increment; // the state is changed after the notifiers are updated
}
}
But it didnt make any difference.

changing Jpanels

i'm trying to make it display one JPanel and remove the other depended on which timer is off in java. here is the snip it of code. mainMenu and pongField are the JPanels and this is inside a timer that acts every millisecond;
if (SwingUtilities.getAncestorOfClass(JFrame.class, pongField) != null){
if (!pongField.getTimer().isRunning())
{
mainMenu = new MainMenu(screenX, screenY, myColor, background, contentPane);
contentPane.remove(pongField);
}}
if (SwingUtilities.getAncestorOfClass(JFrame.class, mainMenu) != null){
if (!mainMenu.getTimer().isRunning())
{
switch(mainMenu.getButton())
{
case 1:
pongField = new PongField(screenX, screenY, 0, moderator, player1UpControl, player2UpControl, player1DownControl, player2DownControl, myColor, background, contentPane, speed);
mainMenu.setButton(0);
contentPane.remove(mainMenu);
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
}}
let me be a little more specific.
I am trying to make Pong, and one JPanel is the actual game while the other is the main menu. if the game ends the timer stops and if i press a button on the main Menu the timer stops and set getButton() to a number depending on which is pressed. for example if button single player is pressed it creates the game and gets rid of the current Jpanel. but if the game ends it get rid of the current JPanel and displays the main menu. Also each JPanel when created set it's own bounds, background color, and adds itself to the JFrame.
The problem is when i run it and the game ends it doesn't change back unless i minimize it and bring it back up but then the button won't work. here is the code for MainMenu. PongField's code is too long but i think i summed up what it did good enough but i can post it too if you want.
public class MainMenu extends JPanel
{
private static final long serialVersionUID = 1L;
//JButtons
private JButton singleJButton, multiJButton, settingsJButton, exitJButton;
//timer if game is still on
private Timer runningTimer;
//JLabel for title
private JLabel titleJLabel;
//screen size
int screenX, screenY;
//color of text and background
private Color myColor, background;
//Container of the JFrame
private Container contentPane;
//which button was clicked
private int buttonPressed;
public MainMenu(int x, int y, Color myC, Color backg, Container contentP)
{
super();
//Initialize all given variables
screenX = x;
screenY = y;
myColor = myC;
background = backg;
contentPane = contentP;
setBounds(0,0,screenX,screenY);
setBackground(background);
contentPane.add(this);
setFocusable(true);
requestFocusInWindow();
singleJButton = new JButton();
singleJButton.setBounds(100, 100, 100, 50);
singleJButton.setText("Single Player");
singleJButton.setFocusable(false);
contentPane.add(singleJButton);
singleJButton.addActionListener(new ActionListener()
{public void actionPerformed( ActionEvent event )
{singleJButtonAction(event);}});
runningTimer = new Timer( 30, new ActionListener()
{public void actionPerformed( ActionEvent event )
{}});
runningTimer.start();
}
public Timer getTimer()
{
return runningTimer;
}
public int getButton()
{
return buttonPressed;
}
public void setButton(int val)
{
buttonPressed = val;
}
private void singleJButtonAction(ActionEvent e)
{
runningTimer.stop();
buttonPressed = 1;
}
//make this panel have focus
public void focus()
{
requestFocusInWindow();
}
What, is it not working? I'm just guessing because you don't say.
The first thing I see if you're creating and removing panes dynamically. It would be more efficient to just hide them. Of course, I don't know what your layout looks like. The other option is to just construct them on startup with all your other GUI stuff and go ahead and add and remove them, but don't recreate them based on the timer. Just show them and hide them as needed. Like this:
mainMenu.setVisible( true );
mainMenu.setVisible( false );
Every millisecond if also pretty fast. I look at ratcheting down, to say one second or so. Of course, it depends on what you're doing.
HTH
I still have problem understanding what your question is?
One thing that seems to be missing in the code is where you add the mainMenu and pongField you create. You remove them from the contentPane by contentPane.remove(pongField); and contentPane.remove(mainMenu); is that your problem?

How to implement shape manipulation on a drawing canvas?

I have a vector (_storedShapes) to store the painted rectangles (_rect). I also plan on adding ellipses. What I am trying to do is add a shape to the spot on the screen that I click and be able to resize it. Here is a website with a demo of what I am trying to do http://code.google.com/p/tangram-canvas/downloads/detail?name=TangramCanvas-1.2.zip.
The only difference from this demo is that I want my shape to expand on all sides from its center as I drag it.
From my code right now, a pre-sized rectangle pops up on the canvas where I click and then when I drag, just follows the cursor on the screen.
private class DrawSListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
_preX = (int) (_rect.getX() - e.getX());
_preY = (int) (_rect.getY() - e.getY());
DrawingPanel dp = new DrawingPanel();
_rect = new SketchyRectangle(dp);
System.out.println("new rec");
// if (_rect.contains(e.getPoint())) {
_rect.setLocation(e.getX(), e.getY());
System.out.println("setLocation");
repaint();
System.out.println("paint");
//}
}
}
/**
* Private class DrawListener is called when the DrawEllipse or DrawRectangle radio buttons are selected.
*
*/
private class DrawListener implements MouseMotionListener {
public void mouseDragged(MouseEvent e) {
if (_rect.contains(e.getPoint())) {
_rect.setLocation(_preX, _preY);
_storedShapes.add(_rect);
repaint();
}
}
#Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
}
I would keep two coordinates in the object (or wherever makes sense): prevDragCoord, shapeCenter. On mouse click store the coordinate of the event in both members. On mouse drag, update the rectangle size by adding to it the difference of the current event coordinate minus the coordinate stored in the object. Set the rectangle's location by setting the difference between the shapeCenter member and the rectangle size divided by 2 (e.g. shapeCenter.x - rect.xLength/2). Store the current coordinate in the object's coordinate member so it's ready to update on any subsequent calls to your handler.
I'll leave the implementation up to you. Maybe you can do it with only one variable, or maybe no variables because the event object has some sort of awesome data in it to get this done. This should be the general idea anyway.

Generating JLabels on demand

I would like to be able to generate a map, of sorts, which places small JLabels at coordinate locations on a panel. The problem is that I need them to be randomly generated, so I don't know in advance how many I will have. Is there a way to do that?
I hope this isn't breaking any Java coding taboos - I'm self-taught.
*Edit:
I know I was vague - my program is huge and cumbersome and I have developed my own conventions (which I'm sure would raise the hackles of real java coders :-P) I should have specified that I have a class Location, and I can easily generate random locations. The trouble I have is in creating a new jLabel for each of those locations. Here's what I have:
//Method called after a new Location has been created, to add it to the map
public void addLocation(Location newLocation)
{
int xx = newLocation.getXloc();
int yy = newLocation.getYloc();
for (int i=0;i<1;i++)
{
JLabel tempLabel = new JLabel(); //tempLabel instantiated elsewhere (is that a problem?)
tempLabel.setBackground(Color.BLACK);
tempLabel.setBounds(xx,yy,3,3);
Map.add(tempLabel); //Map is a JPanel with null layout manager
tempLabel.setVisible(true);
}
}
The problem is that it doesn't seem to do anything. No black dots appear on the map. Maybe now it's as simple as incorrect implementation of adding a label to a panel?
but do you happen to know if it's possible to add a mouselistener to each of these jlabels as they're created?
Sure its possible. You don't even need to create a new listener every time. You can create one listener that is used by all labels. Then inside the listener code you use:
JLabel label = (JLabel)event.getSource();
and you have access to the label that generated the MouseEvent.
Here is some code that might help you in some way, your question was a little vague on the details but i think this is what you are looking for.
public void generate(JPanel panel)
{
int panelWidth = 500;
int panelHeight = 500;
JLabel label;
Random random = new Random(Calendar.getInstance().getTimeInMillies());
int numberOfLabels = random.nextInt(100);
for(int x=0;x<numberOfLabels;x++)
{
int locX = random.nextInt(panelWidth);
int locY = random.nextInt(panelHeight);
label = new JLabel("Hello World!!");
label.setLocation(locX,locY);
label.setVisible(true);
panel.add(label);
}
}
If this is not the answer you are looking for or you need more help, let me know ill be glad to help. Hope this helped!!
Update: This is the way you would do it with a MouseListener:
public void generate(JPanel panel)
{
int panelWidth = 500;
int panelHeight = 500;
JLabel label;
Random random = new Random(Calendar.getInstance().getTimeInMillies());
int numberOfLabels = random.nextInt(100);
for(int x=0;x<numberOfLabels;x++)
{
int locX = random.nextInt(panelWidth);
int locY = random.nextInt(panelHeight);
label = new JLabel("Hello World!!");
label.setName("World Label");
// If some of your labels have the same Text then you should set a different
// name to each one so that you can tell the difference between them
// when you handle the mouse events.
label.addMouseListener(new PlayerListener());
// PlayerListener would be the class that implements MouseListener
label.setLocation(locX,locY);
label.setVisible(true);
panel.add(label);
}
}
This would be your MouseListener:
public void mousePressed(MouseEvent e)
{
JLabel label = (JLabel)e.getSource();
if(label.getName().equalsIgnoreCase("World Label"))
{
System.out.println("Hello World!!");
}
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
This MouseListener should only be added to JLabels because of the type cast. Hopefully this helped!

how can i increase/decrease size of window on click event?

I am developing a simple swing app in which I have a main window with three buttons. When I click on the first button it opens new window of (200,200) dimension. When I click on the second button, the newly opened window's height should get increased and when I click on third button height should get decreased. Can you help me with code....
thanks in advance.
you could do the following on the newly opened windows which you want to resize:
JFrame fr=getNewlyOpenendWindowReference(); // get a reference to the JFrame
fr.setSize(fr.getSize().getWidth() + 10,fr.getSize().getHeight() + 10);
fr.repaint();
this should increase the size of the JFrame length and widthwise by 10 pixels per call.
Create a Controller class to handle the action events.
Define a FramePanel extends JPanel and add your buttons to it. Set up constants in the class with action event values and set them on your buttons. Then, you can instantiate this FrameController and add it as the listener to those buttons using JButton.addActionListener(). Or, you can do this in the constructor of the FrameController class.
public class FrameController implements ActionListener {
private JFrame openedFrame;
public static final int MINIMUM_HEIGHT = 200;
public FrameController(FramePanel panel) {
this.panel.getOpenFrameButton().addActionListener(this);
this.panel.getIncreaseHeightButton().addActionListener(this);
this.panel.getDecreaseHeightButton().addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
if (action.equals(FramePanel.ACTION_OPEN_FRAME)) {
this.openedFrame = new JFrame();
// set it up how you want it
} else if (action.equals(FramePanel.ACTION_INCREASE_HEIGHT)) {
this.openedFrame.setSize(this.openedFrame.getWidth(), this.openedFrame.getHeight() + 10);
} else if (action.equals(FramePanel.ACTION_INCREASE_HEIGHT)) {
int newHeight = this.openedFrame.getHeight() - 10;
if (newHeight < FrameController.MINIMUM_HEIGHT)
newHeight = FrameController.MINIMUM_HEIGHT;
this.openedFrame.setSize(this.openedFrame.getWidth(), newHeight);
}
}
}

Categories

Resources