Java mouse listener lacking responsiveness - java

I made a little color selector using JPanels and mouse listeners, but for some reason the result isn't as responsive as expected and I don't know why.
in order to do so I created a modified JPanel I called ColorPanel, to add it a few properties like color and color name, built in mouse listener, background color defined when instanciated etc:
public class ColorPanel extends JPanel{
private Color color;
private String sColor;
public ColorPanel(Color color, String sColor){
this.color = color;
this.sColor = sColor;
this.setBackground(color);
this.setBorder(BorderFactory.createLineBorder(Color.white));
this.addMouseListener(new appMouseListener());
ColorSelector.panSelector.add(this);
ColorSelector.vPanel.add(this);
}
public Color getColor(){
return this.color;
}
public String getScolor(){
return this.sColor;
}
class appMouseListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
ColorSelector.select((ColorPanel)e.getSource());
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
}
this is linked to another object I made meant to instanciate all the panels I need and their countainer, as well as the method to change the selected colorpanels border color and store its coulour into a global variable.
While it works, every so often I got to click several times to select a colorpanel. The program had no responsiveness problem before and that selector is the only thing behaving this way.
public static void select(ColorPanel colorPanel) {
IhmMap.SelectedColor = colorPanel.getColor();
IhmMap.SelectedScolor = colorPanel.getScolor();
for(int i = 0 ; i<vPanel.size(); i++ ){
vPanel.elementAt(i).setBorder(BorderFactory.createLineBorder(Color.white));
}
colorPanel.setBorder(BorderFactory.createLineBorder(Color.red.darker().darker()));
}
This is the method, all the panels are added to a vector upon creation, so I can manipulate them easily.

MouseClicked event only fires if you didn't move the mouse at all between pressing and releasing the mouse. That way if you press the mouse button and move the mouse slightly just by 1 pixel, the mouseClicked won't get called.
I suggest using mouseReleased or a combination of mousePressed, mouseReleased and/or mouseExited. e.g.
private boolean pressed;
#Override
public void mouseExited(MouseEvent arg0) {
pressed = false;
}
#Override
public void mousePressed(MouseEvent arg0) {
pressed = true;
}
#Override
public void mouseReleased(MouseEvent arg0) {
if (pressed) {
//your code here
}
}
That way you can press on the ColorPanel and as long as you don't leave the ColorPanel it will register a click.

Related

Why is the mousedrag and mousepress being used together in the same time ? I want to stop the mouse drag when I'm using mouse press and vice versa

When I press the free button I can draw in the bottom pane but when I press the rectangle button I can draw a rectangle in the panel but I can also draw anything in the same time. My goal is that when I press one of the functions I want the other to stop functioning.
public class MyFrame extends JFrame implements ActionListener, MouseListener , MouseMotionListener{
JPanel top;
JPanel bottom ;
JButton btn1,btn4;
int freebtn,rectanglebtn;
Graphics g;
public MyFrame(){
this.setTitle("car");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(700,700);
this.setLayout(null);
this.setResizable(false);
top = new JPanel();
bottom = new JPanel();
top.setBounds(0, 0, 700, 100);
top.setBackground(Color.blue);
bottom.setBounds(0, 100, 700, 600);
bottom.setBackground(Color.white);
btn1 = new JButton("free");
btn4 = new JButton("rectangle");
btn1.addActionListener(this);
btn4.addActionListener(this);
top.add(btn1);top.add(btn4);
this.add(top);
this.add(bottom);
bottom.addMouseMotionListener(this);
bottom.addMouseListener(this);
this.setVisible(true);
g=bottom.getGraphics();
}
// action listener-------------------------------
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getActionCommand() =="free") {
System.out.println("free button");
freebtn=11;
}
else if(e.getActionCommand() =="rectangle") {
System.out.println("rectangle button");
rectanglebtn=12;
}
}
// mouse listener-----------------------------
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println(rectanglebtn);
if(rectanglebtn==12) {
g.setColor(Color.BLUE);
g.drawRect(e.getX(),e.getY(), 100, 50);
}
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
// mouse motion listener---------------------------
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println(freebtn);
if(freebtn==11) {
g.setColor(Color.BLUE);
g.fillOval(e.getX(),e.getY(),20,20);
}
}
#Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
}
I tried to to set one of them to null when I'm using the other but it didnt work
Let's start with...
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getActionCommand() =="free") {
System.out.println("free button");
freebtn=11;
}
else if(e.getActionCommand() =="rectangle") {
System.out.println("rectangle button");
rectanglebtn=12;
}
}
Apart from the fact that you are using e.getActionCommand() =="rectangle" instead of "rectangle".equals(e.getActionCommand()) (see How do I compare strings in Java?, for more details) , once either freebtn or rectanglebtn are actioned, the values they set never change.
So, for example, if I press the rectangle button, rectanglebtn is set to 12. If I then press free button, rectanglebtn is still 12
Instead of using two different (and somewhat unrelated) variables, you should be using a single "state" variable. Now, if you have more than two states, I would use a enum, for example...
enum State {
FREE, RECTANGLE, CIRCLE
}
And then update the action handler to something like...
private State state = null;
// action listener-------------------------------
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if ("free".equals(e.getActionCommand())) {
System.out.println("free button");
state = State.FREE;
} else if ("rectangle".equals(e.getActionCommand())) {
System.out.println("rectangle button");
state = State.RECTANGLE;
}
}
Now, whenever either button is actioned, the state is changed to a single state.
Then your mouse listener begins to look something more like...
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println(state);
if (state == State.RECTANGLE) {
g.setColor(Color.BLUE);
g.drawRect(e.getX(), e.getY(), 100, 50);
}
}
// mouse motion listener---------------------------
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println(state);
if (state == State.FREE) {
g.setColor(Color.BLUE);
g.fillOval(e.getX(), e.getY(), 20, 20);
}
}
and there is no way that they could become cross wired.
Now, onto the "other" issues... g = bottom.getGraphics(); is NOT how custom painting works. At best, this will return a "snapshot" of what was last painted and at worst, it will return null.
You need to look at Painting in AWT and Swing and Performing Custom Painting to get a better understanding of how painting in Swing works and how you should work with it.

JTabbedPane action performed

Im looking for way where an action can be performed while using a tabbed pane whenever new tab is opened.
Something like formwindowopenned
Im looking for way where an action can be performed while using a tabbed pane whenever new tab is opened.
I assume you mean when a user clicks on an existing tab to switch to that tab. If so, then you can add a ChangeListener to the tabbedPane and listen for the stateChanged event.
If you are talking about adding a new tab to the tabbed pane, then you would just manage that in your application logic.
All actions on tabs (this will get you extra actions, not only mouse clicks, for example, if you change tab by code using selected index, this code will be executed):
ChangeListener changeListener = new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent) {
JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent.getSource();
int index = sourceTabbedPane.getSelectedIndex();
System.out.println("Tab changed to: " + sourceTabbedPane.getTitleAt(index));
}
};
myJTabbedPanel.addChangeListener(changeListener);
Only mouse clicks on tabs:
/**
* Detects clicks when user click tab inside tabbed pane
*/
private void addMouseEventToPanel(){
this.myJTabbedPanel.addMouseListener(new MouseListener()
{
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("You clicked on tab number "+this.myJTabbedPanel.getSelectedIndex());
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
});
}

MouseListener not triggering for custom JLabel

I want to make a Swing program with icon tiles that play certain sounds when you click on them. For this I created the class:
public class Item extends JLabel implements MouseListener {
public Item(String s) {
// constructor setting background icon and private field with the sound to play
}
public void playSound(); //plays the sound
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Clicked");
this.playSound();
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("Pressed");
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
Then I create a custom JFrame class:
public class Frame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 9221468315661092752L;
public static final int DEFAULT_FRAME_WIDTH=400;
public static final int DEFAULT_FRAME_HEIGHT=400;
private GridLayout gridLayout;
private ArrayList<Item> tiles=new ArrayList<Item>();
public Frame() {
super("Title");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(new Dimension(DEFAULT_FRAME_WIDTH,DEFAULT_FRAME_HEIGHT));
gridLayout=new GridLayout(4,4,10,10);
setLayout(gridLayout);
addItems();
}
public void addItems() {
Item item=new Item("name");
Item item2=new Item("name");
tiles.add(item);
tiles.add(item2);
this.add(item);
this.add(item2);
}
public static void main(String[] args) {
Frame frame=new Frame();
frame.setVisible(true);
}
The tiles show normally in the grid layout, however the problem is that the mouse listener doesn't work. The println() I put at mouseClicked() and mousePressed() is not called.
I could try to add a MouseListener to the Item class, so that Item has a MouseListener, but I wonder what is wrong with the above code.
You have two problems. One, your JLabels do not show (although I'm not sure if that was intentionally left out). Two, you never add a mouse listener. You can accomplish this by adding two statements to the constructor, without making any extra classes:
public Item(String s) {
super(s); //initializes the text and display using JLabel's constructor
addMouseListener(this); //uses the reference of this Item as a MouseListener
}

Java KeyListener does not fire?

Normally I don't program in JAVA but for this project I need to. I got everything working except of the key listener. I want the program to react whenever a Key is pressed (doesn't matter wich one).
public class fullscreen extends JPanel implements MouseListener, MouseMotionListener, KeyListener {
public fullscreen() {
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
}
and then the KeyListener methods:
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
System.out.println("Key Pressed!");
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
The MouseListener methods work without any problem. What did I do wrong with the KeyListener?

Action Listener detects multiple Events for a Single Event

I have designed a panel that includes some buttons with it. Buttons are attached with an ActionListener. When ever i click on that buttons this ActionListener detects 4 events for this single click. Whereas it should detect only one. Does anybody know what exactly the reason is?
public class Buttons extends JPanel
{
private JButton undo=new JButton("Undo");
private JButton replay=new JButton("Replay");
public void paint(Graphics g)
{
super.paint(g);
super.setSize(new Dimension(560,30));
super.add(replay);
super.add(undo);
undo.setBorder(new LineBorder(Color.WHITE,3));
replay.setBorder(new LineBorder(Color.WHITE,3));
undo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
Controler.pieces.undo();
Controler.reDraw();
}
});
replay.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
System.out.println("Dastiii");
}
});
}
}
and these events are being used here
public void undo()
{
System.out.print(Controler.allMoves.size());
if(Controler.allMoves.size()<=1)
{
init_board();
return;
}
Piece temp[][]=Controler.allMoves.get(Controler.allMoves.size()-2);
for(int i=0;i<8;i++)
{
for(int j=0;j<8;j++)
{
board[i][j].set_name(temp[i][j].get_name());
board[i][j].set_oneWay(temp[i][j].get_oneWay());
}
}
Controler.allMoves.remove(Controler.allMoves.size()-2);
}
Your registering you ActionListeners within the paint method!!
Let's not even worry about the fact that it's un-recommended to override paint
Never change or modify the state of the component or any of it's child components within in any paint method, these will be called multiple times during the execution of your application. For example, it's not unusual for a paint method to be called 2-4 times just when the main window is made visible...
public void paint(Graphics g)
{
super.paint(g);
/** All this should be done within the constructor
// If you are using a layout manager, this is pointless, if your not
// then that's another problem
super.setSize(new Dimension(560,30));
super.add(replay);
super.add(undo);
undo.setBorder(new LineBorder(Color.WHITE,3));
replay.setBorder(new LineBorder(Color.WHITE,3));
undo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
Controler.pieces.undo();
Controler.reDraw();
}
});
replay.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
System.out.println("Dastiii");
}
});
**/
}
Take a look at:
Performing Custom Painting
Painting in AWT and Swing
For more details about how and what painting is in Swing

Categories

Resources