JFrame Selecting Multiple Objects - java

I would like to know if the multiple selections function used in list, will be workable too in the object?
The example I found was working on the list as provided from the link.
https://stackoverflow.com/questions/25691623/jlist-listselectionlistener-multiple-interval-selection-that-waits-for-cntrl-or
The current project I'm working on is to draw different shapes which is an object. After done drawing, I shall be able to select more than 1 object by holding the SHIFT key.
How can I do that?

you can not re-use the List-Selection-Model in a simple way - i really recommend to use your own implemention instead.
To do so you must add a KeyListener and a MouseListener on your Panel in order to check for Shift pressed or not.
private boolean isShiftDown = false;
KeyAdapter ka = new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if(e.getKeyCode() == KeyEvent.VK_SHIFT){
isShiftDown=false;
}
}
#Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
if(e.getKeyCode() == KeyEvent.VK_SHIFT){
isShiftDown=true;
}
}
};
use your own selection 'model' which will be a simple list (java.util.List)
private List<Shape> selectionList = new ArrayList();
MouseAdapter ma = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
Shape shape = findShapeAt(e.getX(), e.getY() ); //i guessed you had a methode like that
if (shape != null){
//check is your shift key is down
if (isShiftDown){
//add or remove on click
if (selectionList.contains(shape) ){
selectionList.remove(shape);
}else{
selectionList.add(shape);
}
}else{
//if shift is NOT down, clear the list before adding
selectionList.clear();
selectionList.add(shape);
}
}
//show the selection in your gui();
updateSelection(); //that's your part - draw a nice border around all Shapes from the selectionList
}
};
don't forget to add both keyListener(KeyAdapter) and MouseListener(MouseAdapter) to your panel...
NOTE
i would really use the ctrl-key (KeyEvent.VK_CONTROL) instead of the shift-key to add/remove shapes by single-mouse-klick...

Related

Java game involving adjacent JButtons

I'm making a small game involving a grid of JButtons (MxN) and the main premise is to click on buttonA and then on buttonB, coloring buttonB and adjacent buttons of the same color as buttonB with the color of buttonA. I have made it so you are able to choose 3 possible difficulties. The colors are randomly generated. The main problem is getting the colors to change.
This is the method that I call after selecting the difficulty of the game:
public static void gameMechanics(int m, int n) {
final String[] pickedColour = {""};
final String[] placedColour = {""};
JButton[][] picked = new JButton[m][n];
JButton[][] placed = new JButton[m][n];
picked[m][n].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pickedColour[0] = picked[m][n].getText();
}
});
placed[m][n].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
placedColour[0] = placed[m][n].getText();
}
});
if (pickedColour[0] == "R" && placedColour[0] != "R") {
placed[m][n].setBackground(Color.RED);
placed[m][n].setText("R");
}
else if (pickedColour[0] == "G" && placedColour[0] != "G") {
placed[m][n].setBackground(Color.GREEN);
placed[m][n].setText("G");
}
else if (pickedColour[0] == "B" && placedColour[0] != "B") {
placed[m][n].setBackground(Color.BLUE);
placed[m][n].setText("B");
}
}
I would consider using JPanels and painting them, using a MouseListener instead.
However, if you're set on using JButtons, try this:
button.setBackground(Color.GREEN);
button.setOpaque(true);
Note that this might not work if you're setting the look and feel using UIManager.
Also, you're doing a ton of extra work to map the color to the button - it could get confusing and cause errors down the road. Instead, you might try creating your own class:
class ColoredButton extends JButton {
private static final long serialVersionUID = 3040767030924461426L;
private Color color;
public ColoredButton(Color c) {
this.color = c;
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changeColor();
}
});
}
public void changeColor() {
this.setBackground(this.color);
this.setOpaque(true);
}
}
Now, you can construct a new ColoredButton:
// Now, this button will turn green when clicked
ColoredButton temp = new ColoredButton(Color.GREEN);

Override method that toggles 'isSelected' in getListCellRendererComponent

I would like to make my own method that controles when a component is 'isSelected'.
I have a JList containing multiple JPanel. The constructing class of the JPanel extends ListCellRenderer<>.
To show that one of the JList-component (the JPanels) is selected i use;
#Override
public Component getListCellRendererComponent(..., boolean isSelected, ...) {
if(isSelected){
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
return this;
}
I would like a method that keeps a selected item 'selected' eventhough I choose to select another. I understand this can be done by holding down CTRL, but .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); does not quite do the trick. I would rather like to select multiple by clicking on them, and deselect by clicking on them.
For this i have worked with the ListSelectionMode, but i cant find a way.
When done the above I would like to implement a method that only selects a component in the list when clicked in a certain area (instead of the whole component which is preset). I have made this method, which returns true if the correct area is clicked, else false. But since I cant figure out how to override the mouseevent that makes the components 'isSelected' this has been tricky.
Here is the code for the method I would like to override the 'isSelected' method;
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent evt) {
if(ActionHandler.mouseClickedPrebuild(evt.getPoint())){
//This code runs if that special place is clicked!
//So now the component should be 'isSelected' or
//deselected if it already was 'isSelected'.
}
}
});
This code is in the constructor of my JList
And the mouseClickedPrebuild method;
public static boolean mouseClickedPrebuild(Point point) {
int index = theJList.locationToIndex(point);
Rectangle bounds = theJList.getCellBounds(index,index);
Point p = bounds.getLocation();
return ( ... long list of greater than & less than ...);
//This gives the certain area which is accepted to return true
I solved the issue!
So I get my view showing by running this line;
// UI Class JScrollPane Custom JList
UIConstructor.listview.setViewportView(new ListView( -insert ArrayList here- ));
Here is my ListView. The custom DefaultListSelectionModel I used to solve my problem was posted by #FuryComptuers right here;
JList - deselect when clicking an already selected item
I had to make a few changes to the code, since the two methods in the selectionModel will run before my mouseevent. I saved the variabels staticly, so instead of running the code in setSelectionInterval I did it inside my mousePressed.
I then could add the boolean isSelected which returns true, if a curtain area within a specific list element is clicked.
public class ListViewd extends JList {
static boolean isSelected;
static Point point;
static boolean gS = false;
static int in0;
static int in1;
#Override
public Dimension getPreferredScrollableViewportSize() {
Dimension size = super.getPreferredScrollableViewportSize();
size.setSize(new Dimension(0,0));
return size;
}
public ListView(ArrayList<System> items) {
DefaultListModel<System> list = new DefaultListModel<System>();
for (System item : items) {
list.addElement(item);
}
this.setSelectionModel(new DefaultListSelectionModel() {
boolean gestureStarted = false;
#Override
public void setSelectionInterval(int index0, int index1) {
gS = gestureStarted;
in0 = index0;
in1 = index1;
gestureStarted = true;
}
#Override
public void setValueIsAdjusting(boolean isAdjusting) {
if (!isAdjusting) {
gestureStarted = false;
}
}
});
ListSelectionModel selectionModel = this.getSelectionModel();
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
point = e.getPoint();
isSelected = ActionHandler.mouseClickedPrebuild(point);
if(!gS && isSelected){
if (isSelectedIndex(in0)) {
selectionModel.removeSelectionInterval(in0, in1);
} else {
selectionModel.addSelectionInterval(in0, in1);
}
}
}
});
setModel(list);
setCellRenderer(new ListModelPrebuild());
}

Getting JPanel[][] coordinates by clicking on a JPanel

I've created a JPanel[][] Array.
private JPanel[][] pnlFeld;
And filled it with panels
for (int i = 0; i < world.getSize(); i++) {
for (int j = 0; j < world.getSize(); j++) {
pnlFeld[i][j] = new JPanel();
pnlFeld[i][j].setBorder(new EtchedBorder());
pnlFeld[i][j].addMouseListener(ml);
pnlFeld[i][j].setBackground(off);
add(pnlFeld[i][j]);
}
}
Now I want to get the array coordinates ([][]) by clicking on them and I have no clue how to do that.
I've only added methods to change the color of the panel I clicked on, nothing related to my problem.
MouseListener ml = new MouseListener() {
#Override
public void mouseEntered(MouseEvent e) {
if (world.getMode().equals("Malen")) {
if (e.getSource() instanceof JPanel)
e.getComponent().setBackground(on);
// check();
}
else if (world.getMode().equals("Radieren")) {
if (e.getSource() instanceof JPanel)
e.getComponent().setBackground(off);
// check();
}
}
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
if (world.getMode().equals("Setzen")) {
if (e.getSource() instanceof JPanel) {
if (e.getComponent().getBackground() == off) {
e.getComponent().setBackground(on);
} else
e.getComponent().setBackground(off);
}
// check();
}
}
}
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
};
Actually you can use getBounds() to get component location and size. If you mean the array indexes there could be multiple solutions.
Define a Map and place all your panels in the Map with String value e.g. i+":"+j (or define simple pojo class with 2 fields i and j.
Create unique listener for each JPanel to keep the i and j.
Place the panels in a containr with GridBagLayout then you can use gridBagLayoutInstance.getConstraints(theClickedPanel) and check row column of the constraint
Getting JPanel[][] coordinates by clicking on a JPanel
Use a JButton[][] with ActionListener for easier coding and a better user experience. The ActionEvent has a getSource() method that will identify the button that was activated.
This chess GUI uses buttons for the 64 places on the chessboard.
If you create your MouseListener in your loop, you can use i en j within the code of your listener. The drawback is that you'll have a bit more instances of your listener.
I could suggest that you set the name of each JPanel as i and j in the loop where you declare and initialise the panels. As illustrated
pnlFeld[i][j].setName(i + "" + j);
And in your mouseClicked event check if the event source is an instance of JPanel and parse the name to get the x and y coordinates like this:
Integer.parseInt(p.getName().subString(0,1))
Integer.parseInt(p.getName().subString(1));

moving / scrolling up and down on three JTable simultanously.

I have three different jtable on three diffenernt jscrollpane - one next to the other.
I successfuly written some code that makes them all scroll together when I scroll the mouse wheel.
I inherrited JScrollpane and overriden its processMouseWheelEvent methos as follows:
public void processMouseWheelEvent(MouseWheelEvent e) {
...
if (e.getSource() == this) {
for (BTSJScrollPane other : effected) {
other.processMouseWheelEvent(e);
}
}
}
I have canelled the pageup pagedown using
final InputMap inputMap =
comp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke("PAGE_DOWN"), EMPTY);
inputMap.put(KeyStroke.getKeyStroke("PAGE_UP"), EMPTY);
comp.getActionMap().put(EMPTY, emptyAction);
But,
my only problem now is that when the user clicks up and down, they dont go together but rather scroll indipently.
Any suggestions ?
So far I wrote in my scrollpane something like
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
#Override public boolean dispatchKeyEvent(KeyEvent e) {
if (thisIsThesourceTable) {
if (e.getKeyCode() == 38 || e.getKeyCode() == 40) {
}
}
return false;
}
});
But :
1. is there a better way?
2. maybe I should do it somehow in the actionMap?
3. how do I pass the key up/down event to the other scrollpane?
4. can I know if I am near the end of the viewing part in the scroll pane? is it needed
1, 2, & 3: You should use listeners on the scrollbars so it works with mouse, keyboard, and scrollbar interaction. That way you won't need key or mouse listeners. Here is one way:
scroll1.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
scroll2.getVerticalScrollBar().setValue(e.getValue());
}
});
4: Look at JScrollPane's getVerticalScrollBar().getMaximumSize() and getModel() to find out if you're near the end.

JButton breaks my Keylistener

JAVA USING NETBEANS
Hello stackoverflow, i have a problem i would like help with. In a nutshell, I have a mouselistener and a keylistener on a jpanel, everything works fine except when i press one of my jbuttons, then the keylistener goes AWOL. Can any1 explain the problem, is the panels focus now on the buttons instead of the keyboard, im at a lost.
Here is the code, if somethings are not reference, assume its are there the entire panel code was 500+ long so i cut quite a bit.
Thanks in advance for any help.
package tankgame;
public class TankPanel extends JPanel implements KeyListener,
MouseListener,MouseMotionListener
{
JButton back,shop, menu, health, speed, rapidfire, shootradius;
TankPanel()
{
setLayout( null );
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
setFocusable(true);
shop= new JButton("SHOP");
shop.addMouseListener(this);
shop.setBounds(400,0, 80,15);
add(shop);
}
public void keyPressed(KeyEvent k)
{
char c = k.getKeyChar();
if(c=='u')
{
u++;
System.out.println(u+" = u");
}
if(c=='i')
{
i++;
System.out.println(i+" = i");
}
if( c == 'd' )
{
if(Ptank.pic==PlayerTankE)
{
if(Ptank.move==true)
{
Pbarrel.x+=Ptank.speed;
Ptank.x+=Ptank.speed;
}
}
else
{
if(Ptank.pic==PlayerTankN || Ptank.pic==PlayerTankS)
{
Ptank.x = Ptank.x - 5;
Ptank.y=Ptank.y+5;
}
Ptank.setPic(PlayerTankE);
Ptank.width=35;
Ptank.height = 23;
}
}
setFocusable(true);
repaint();
}
public void keyReleased(KeyEvent k)
{
}
public void keyTyped(KeyEvent k)
{
}
public void mouseClicked(MouseEvent e)
{
//Invoked when the mouse button has been clicked (pressed and released)
}
public void mouseEntered(MouseEvent e)
{//Invoked when the mouse enters a component.
}
public void mouseExited(MouseEvent e)
{ //Invoked when the mouse exits a component.
}
public void mousePressed(MouseEvent e)
{//Invoked when a mouse button has been pressed on a component.
if(e.getSource()==back)
{
System.out.println(456);
System.out.println(back.getLocation().x + " "+back.getLocation().y);
}
else if(e.getSource() == menu)
{
changebuttons("menu");
System.out.println(456);
System.out.println(menu.getLocation().x + " "+menu.getLocation().y);
}
else if(e.getSource() == shop)
{
changebuttons("shop");
System.out.println(456);
System.out.println(shop.getLocation().x + " "+shop.getLocation().y);
}
else if(e.getButton() == MouseEvent.BUTTON1)
{
destpoint= new Point();
destpoint.setLocation(mousex, mousey);
origin = new Point();
}
for(int i = 0; i< Ptank.rapidfire; i++)
{
if (origin.distance(destpoint) <= 100 && origin.distance(destpoint) >= 50)
{
Bullet add = new Bullet(this,destpoint);
add.getOrigin(origin);
add.setPic(PlayerBullet);
add.width=4;
add.height=4;
bulletList.add(add);
}
}
}
}
public void mouseReleased(MouseEvent e)
{//Invoked when a mouse button has been released on a component.
}
public void mouseDragged(MouseEvent e)
{//Invoked when a mouse button is pressed on a component and then dragged.
}
public void mouseMoved(MouseEvent e)
{
//Invoked when the mouse cursor has been moved onto a component but no buttons
Cursor cursor = Cursor.getDefaultCursor();
//you have a List<Polygon>, so you can use this enhanced for loop
cursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
setCursor(cursor);
mousex=e.getX();
mousey=e.getY();
}
public void changebuttons(String x)
{
if(x.equals("shop"))
{
menu.setBounds(720, 0, 80, 15);
health.setBounds(0, 0, 125, 15);
speed.setBounds(150, 0, 125, 15);
shootradius.setBounds(300, 0, 200, 15);
rapidfire.setBounds(500, 0, 150, 15);
shop.setBounds(1000, 0, 150, 15);
}
}
KeyEvents are only generated on a component that has focus. When you click on the button is now has focus to key events won't be generated on the panel. You need to add:
panel.requestFocusInWindow()
in your ActionListener to give focus back to the panel.
However the better solution is to use Key Bindings as you can add bindings to a KeyStroke even when the component doesn't have focus.
Don't use a KeyListener which requires the component be focused to work. Instead consider using Key Bindings. You can find out how to use these guys at the Swing tutorial: How To Use Key Bindings. If you need more specific help, you will want to post a much smaller bit of code than you show above, code that is self-contained and will actually compile and run for us, an SSCCE.

Categories

Resources