Keeping a MouseListener always running - java

I have this constructor:
public Board(final boolean[][] board) {
this.board = board;
height = board.length;
width = board[0].length;
setBackground(Color.black);
button1 = new JButton("Run");
add(button1);
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
isActive = !isActive;
button1.setText(isActive ? "Pause" : "Run");
}
});
button2 = new JButton("Random");
add(button2);
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setBoard(randomBoard());
}
});
button3 = new JButton("Clear");
add(button3);
button3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setBoard(clearBoard());
}
});
addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
board[e.getY() / multiplier][e.getX() / multiplier] = !board[e.getY() / multiplier][e.getX() / multiplier];
}
#Override
public void mouseReleased(MouseEvent e) {
}
});
}
The ActionListeners are always 'listening'; however the MouseListenerstops 'listening' after I click Run (button1). Why is this and how do I make MouseListener remain listening?
If it's any use, I also have this paintComponent class:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
g.setColor(board[i][j] ? Color.green : Color.gray);
g.fillRect(j * multiplier, i * multiplier, multiplier - 1, multiplier - 1);
}
}
if (isActive) {
timer.start();
}
else {
timer.stop();
repaint();
}
}

A MouseListener will continue to work as long as the object you added it to is still alive and assuming you haven't called removeMouseListener() on it. As your program runs and changes data and such, the behavior of the code inside your listener may change (e.g., a flag is set causing it to ignore a call to another method), but the listener will be "always running" and its methods will be called.
(As I mentioned in my comment, your problem likely has to do with the strange things you are doing in your paintComponent() method.)

Related

How to get the scroll button to zoom in and out an object using java

Beginner here,
I am trying to make a simple application using java where a rectangle is created and can be moved using the keys "w,a,s,d". And also to increase or decrease size of the rectangle using the scroll button in a mouse. Now the object can be moved using the keys but I don't know how to do the scroll function. Somebody Help?
import java.awt.*;
import java.awt.event.*;
public class Animation extends Frame implements KeyListener, MouseWheelListener {
int x, y, a, b;
char choice1;
Animation() {
setSize(500, 500);
setVisible(true);
x = 50;
y = 50;
a = 20;
b = 50;
addKeyListener(this);
addWindowListener(new WindowListener() {
#Override
public void windowOpened(WindowEvent e) {
}
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
#Override
public void windowClosed(WindowEvent e) {
}
#Override
public void windowIconified(WindowEvent e) {
}
#Override
public void windowDeiconified(WindowEvent e) {
}
#Override
public void windowActivated(WindowEvent e) {
}
#Override
public void windowDeactivated(WindowEvent e) {
}
});
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
choice1 = e.getKeyChar();
if (choice1 == 'w') {
y = y - 1;
}
if (choice1 == 's') {
y = y + 1;
}
if (choice1 == 'a') {
x = x - 1;
}
if (choice1 == 'd') {
x = x + 1;
}
repaint();
}
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
}
public void paint(Graphics g) {
g.drawRect(x, y, a, b);
g.setColor(Color.red);
g.fillRect(x, y, 20, 50);
}
public static void main(String[] args) {
Animation animation = new Animation();
}
}
To be specific I want to know what should be written inside the mouseWheelMoved() method and how using that I can make the rectangle bigger or smaller.
Thanks
If somebody faces the same problem.
Use the getPreciseWheelRotation() method to get values. If the value is greater than 0, the scroller is being scrolled towards you and vice versa.
I'm entering the code also here,
double p = e.getPreciseWheelRotation();
if(p>0){
a=a+5;
b=b+5;
} else{
a=a-5;
b=b-5;
}
repaint();

Start timer on keypress, java

I want to, when i click the "d" button, start a timer. This is to animate a player walking. The timer doesn't start when i press the key, how do i do that?
The code I have is this:
public class Game extends JPanel implements KeyListener {
//Player variables
private BufferedImage playerStanding;
private BufferedImage playerWalking;
private BufferedImage playerFrame;
private boolean walking = false;
private final int PLAYER_HEIGHT = 100;
private final int PLAYER_WIDTH = 100;
private final int INITIAL_X = 0;
private final int INITIAL_Y = 500;
private int x = INITIAL_X;
private int y = INITIAL_Y;
//The timer I want to start on keypress-> "d"
private Timer playerAnimationTimer;
public Game() {
setPreferredSize(new Dimension(800, 800));
setBackground(Color.CYAN);
//Player
try {
playerStanding = ImageIO.read(getClass().getResource("player1.gif"));
playerWalking = ImageIO.read(getClass().getResource("player2.gif"));
playerFrame = playerStanding;
}
catch (IOException ex) {
ex.printStackTrace();
}
playerAnimationTimer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
walking = !walking;
playerFrame = walking ? playerWalking : playerStanding;
x += 10;
if (x > getWidth() - PLAYER_WIDTH) {
x = INITIAL_X;
}
repaint();
}
});
playerAnimationTimer.setRepeats(true);
}
public Dimension setPreferredSize() {
return new Dimension(800, 800);
}
#Override
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D graphics2D = (Graphics2D) graphics;
if (playerFrame != null) {
graphics2D.drawImage(playerFrame, x, y, PLAYER_WIDTH, PLAYER_HEIGHT, this);
}
graphics2D.dispose();
}
#Override
public void keyTyped(KeyEvent e) {
//This doesn't work
playerAnimationTimer.start();
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
//The class to hold the gamepanel
public class StartGame extends JFrame implements ActionListener {
private static JButton startGame = new JButton();
StartGame() {
setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
setSize(200, 100);
setVisible(true);
setBackground(Color.BLUE);
setLocationRelativeTo(null);
startGame.setText("Play!");
startGame.setSize(100, 25);
startGame.addActionListener(this);
add(startGame);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == startGame) {
this.setVisible(false);
new GameWindow();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new StartGame();
}
});
}
}
How could I make the timer start when I click the "d" button?
Your KeyListener doesn't work because you never add the KeyListener to anything much less to a component that has focus, which is needed for a KeyListener to work.
I suggest that you instead use Key Bindings as a cleaner safer way to capture the desired key press.
As an aside, never dispose of a Graphics object that is given to you from the JVM.
For a better answer, please edit your code to make it comply with the mcve standard. You should use no images files, and it should compile and run for us unaltered.
You could set the private Timer like you did and start it like this...
public void startTimer(){
timer.start();
timer.setRepeats(true);
}

Java - JFrame keeps freezing after I type some Letters into a JTextField

I have no Idea why my JFrame keeps freezeing after I type Letters into the JTextField "Username" and "Password" :/ Could anyone look thru my code and tell my why and fix it please ?
public class Main
{
public static void main(String [ ] args)
{
LoginWindow loginframe = new LoginWindow();
loginframe.setVisible(true);
loginframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loginframe.initialize();
while(true)
{
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
loginframe.Repaint();
}
}
}
FrameClass:
public class LoginWindow extends JFrame implements MouseListener, KeyListener, MouseMotionListener{
public LoginWindow(){
setSize(806, 629);
setResizable(false);
setLayout(new BorderLayout());
background = new JLabel(ResourceLoader.Iconload("/main_01.jpg"));
background.setBounds(0, 0, 800, 600);
add(background);
background.setLayout(null);
Username = new JTextField("", 20);
Username.setForeground(Color.WHITE);
Username.setBounds(312, 433, 170, 40);
Username.setFont(new Font("Impact", Font.BOLD, 25));
Username.setBackground(Color.BLACK);
Username.setBorder(BorderFactory.createMatteBorder(0, 0, 5, 0, Color.BLACK));
background.add(Username);
Password = new JPasswordField("", 20);
Password.setForeground(Color.WHITE);
Password.setBounds(312, 489, 170, 40);
Password.setBackground(Color.BLACK);
Password.setBorder(BorderFactory.createMatteBorder(0, 0, 5, 0, Color.BLACK));
Password.setFont(new Font("Serif", Font.BOLD, 25));
background.add(Password);
}
public void initialize()
{
makestrat();
addKeyListener(this);
requestFocus();
addMouseListener(this);
addMouseMotionListener(this);
}
public void makestrat()
{
createBufferStrategy(2);
strat = getBufferStrategy();
}
public void Repaint()
{
//System.out.println(mouseX + " " + mouseY);
Graphics g = strat.getDrawGraphics();
paintComponents(g);
Draw(g);
g.dispose();
strat.show();
}
public void Update()
{
}
public void Draw(Graphics g)
{
if(((mouseX >= 499) && (mouseX <= 669)) && ((mouseY >= 433)&&( mouseY <= 530))){
g.drawImage(ResourceLoader.ImageLoad("/login_02.jpg"), 502, 459, null);
}else{
g.drawImage(ResourceLoader.ImageLoad("/login_01.jpg"), 502, 459, null);
}
}
private class thehandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent event) {
}
}
public void mouseMoved(MouseEvent event)
{
mouseY = event.getY()-26;
mouseX = event.getX()-3;
}
#Override
public void mouseClicked(MouseEvent e) {
PointerInfo a = MouseInfo.getPointerInfo();
Point point = new Point(a.getLocation());
SwingUtilities.convertPointFromScreen(point, e.getComponent());
double mouseX = (int) point.getX();
double mouseY = (int) point.getY();
System.out.println("(ContainerPos) Mouse clicked! X: " + mouseX + " Y: " + mouseY);
}
#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) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
You don't need the while loop with the Thread.sleeap(). It's screwing with your program.
What you're trying to achieve here, a call to repaint continuously, can easily be accomplished with a javax.swing.Timer
Don't explicitly call paintComponent. An actual call to the real repaint() method will do that for you. No need to create an imitation Repaint()
Use a JPanel for painting instead of trying to paint on a JFrame
I would initialize, then set visible
Your code doesn't even compilable, so I can try and make fixes for you.
Use Java naming convention: methods and variable start with lower case letters.
Here's an example of a simple Login Window, using a modal JDialog
Learn how to use Layout Managers instead of relying on setBounds()
Point 2. Your main should look like this
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
LoginWindow loginframe = new LoginWindow();
loginframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loginframe.initialize();
loginframe.setVisible(true);
}
});
}
And in your constructor, have a javax.swing.Timer instead of your while loop
private Timer timer = null;
private DrawPanel drawPanel = new DrawPanel(); // see below for DrawPanel
public LoginWindow() {
// add drawPanel somewhere
...
timer = new Timer (50, new ActionListener(){
public void actionPerformed(ActionEvent e) {
drawPanel.repaint();
}
});
timer.start();
}
Point 4. Have an inner JPanel class that you do all your painting in, and add that component to the frame. You'll need to override the paintComponent method.
private DrawPanel extends JPanel {
#Override
protected void paintComponent(Graophics g) {
super.paintComponent(g);
Draw(g);
}
}
The obvious thing is that you shouldn't use Swing (or AWT really) off of the AWT Event Dispatch Thread (EDT). Fix with java.awt.EventQueue.invokeLater and java.swing.Timer (not java.util!). Diagnose with jstack(and jps) or the relevant key sequence in the terminal window (um, ctrl-break in Windows, ctrl-3 in Linux).

Java panel interface

Im trying to make a pline drawing program. when I try to repaint all of the lines(after creating a new one) only the last one is draw out.The problem might be in repainting.
Can someone see what I am doing wrong?
Code is here:
public class Kimp extends JFrame {
private ArrayList<Point[]> pointsArray = new ArrayList<>();
private Point points[] = new Point[10000];
private int pointCounter = 0;
public Kimp () {
panel paintArea = new panel();
add(paintArea, BorderLayout.CENTER);
}
private class panel extends JPanel {
public panel () {
HandlerClass handler = new HandlerClass();
this.addMouseListener(handler);
this.addMouseMotionListener(handler);
}
#Override
void paintComponent(Graphics g) {
super.paintComponent(g);
try {
for (Point[] p : pointsArray) {
for(int i = 0; i < p.length; i++) {
if (p[i].x == 0) {
continue;
} else {
if (p[i + 1].x == 0) {
g.setColor(Color.BLUE);
g.drawLine(p[i].x, p[i].y, p[i].x, p[i].y);
} else {
g.setColor(Color.BLUE);
g.drawLine(p[i].x, p[i].y, p[i + 1].x, p[i + 1].y);
}
}
}
}
points = preFill(points);
} catch (NullPointerException e) {
}
}
}
private class HandlerClass implements MouseListener , MouseMotionListener {
#Override
public void mouseDragged(MouseEvent e) {
points[pointCounter++] = e.getPoint();
}
#Override
public void mousePressed(MouseEvent e) {
points[pointCounter] = e.getPoint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
public static Point[] preFill (Point[] points) {
for (int i = 0; i < points.length; i++) {
points[i] = new Point(-999,-999);
}
return points;
}
}
I quickly rewrote your code to simplify it as much as possible. You may be able to better understand the concepts behind it.
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Color;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class Kimp {
public static void main(String[] args) {
JFrame frame = new JFrame("Kimp!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.add(new CanvasPanel());
frame.setVisible(true);
}
}
class CanvasPanel extends JPanel {
private final List<List<Point>> lines = new LinkedList<List<Point>>();
private List<Point> points = new LinkedList<Point>();
public CanvasPanel() {
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
for (List<Point> line : lines)
drawLine(line, g);
drawLine(points, g);
}
private void drawLine(List<Point> points, Graphics g) {
if (points.size() < 2) return;
Point p1 = points.get(0);
for (int i=1, n=points.size(); i<n; i++) {
Point p2 = points.get(i);
g.setColor(Color.BLUE);
g.drawLine(p1.x, p1.y, p2.x, p2.y);
p1 = p2;
}
}
private MouseAdapter mouseAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
if (points.size() > 1) {
lines.add(points);
points = new LinkedList<Point>();
}
}
};
}
private ArrayList<Point[]> pointsArray = new ArrayList<>();
This is a list of Point[]. Here only one private Point points[] = new Point[10000]; is allocated. Which means that each time you add points into pointArray, you are adding the same instance of points.
When you change the elements of points, all the existing Point[] in pointArray is updated. Since all the elements are referring to the same points.
Allocate new Point[] when drawing a new line.
You are resetting your points array every time you painted it (preFillPoints() is called in paint()). Your pointsArray (which should be called pointsList for gods sake) is completely meaninless, you add the same points[] array each time the mouse is released.
The code makes no sense. You only need the list or the array. Not both. Declare a List<Point> (not Point[]) and just add a new Point every time the mouse moves.

Why are only the co-ordinates of the mouse displayed?

when the Thread thread is running, (after clicking record) it only displays the position the mouse was in when the thread started? how can i make it constantly update, displaying where the mouse is even if i move it around the frame?
#Override public void actionPerformed(ActionEvent e)
{
thread = new Thread(this);
if(e.getSource() == record)
{
thread.start();
System.out.println("record");
}
if(e.getSource() == stopRecording)
{
setVisible(false);
System.out.println("stop recording");
}
}
#Override public void run()
{
setTitle("979");
setSize(screen.width, screen.height);
addMouseListener(this);
setLocationRelativeTo(null);
setLayout(transFlo);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(stopRecording);
setOpacity(0.50f);
setVisible(true);
while(true)
{
repaint();
}
}
#Override public void paint(Graphics g)
{
g.drawString(mousePOS + x + space + y, 250, 250);
}
Okay, just to reiterate; PLEASE read The Event Dispatching Thread,
then read Concurrency in Swing
and finally have a read of How to Write a Mouse Listener
ADDINTIONAL
If you want to monitor the global mouse events (all mouse events that pass through the system), then you will want to take a look at Toolkit.addAWTEventListener
This will allow you to monitor all the mouse events without the need to attach mouse listeners to all the components
SIMPLE MOUSE EXAMPLE
Here is a simple example of a panel that monitors the mouse :P
public class CrayPanel extends javax.swing.JPanel implements MouseMotionListener, MouseListener {
private List<Point> lstPoints;
/**
* Creates new form CrayPanel
*/
public CrayPanel() {
lstPoints = new ArrayList<Point>(25);
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (lstPoints.size() > 1) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
Point startPoint = lstPoints.get(0);
for (int index = 1; index < lstPoints.size(); index++) {
Point toPoint = lstPoints.get(index);
g2d.drawLine(startPoint.x, startPoint.y, toPoint.x, toPoint.y);
startPoint = toPoint;
}
}
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
lstPoints.add(e.getPoint());
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
lstPoints.clear();
lstPoints.add(e.getPoint());
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
lstPoints.add(e.getPoint());
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
lstPoints.add(e.getPoint());
repaint();
}
}
I put together another example. This is essentially a mouse monitor, it shows that, if done correctly, you don't need the Thread
public class MouseFrame extends javax.swing.JFrame implements AWTEventListener, ActionListener {
private boolean monitor = false;
private Point mousePoint;
/**
* Creates new form MouseFrame
*/
public MouseFrame() {
setLayout(new GridBagLayout());
JButton btnToggle = new JButton("Start");
add(btnToggler);
btnToggle.addActionListener(this);
setSize(400, 400);
}
public void actionPerformed(java.awt.event.ActionEvent evt) {
monitor = !monitor;
if (monitor) {
btnTrigger.setText("Stop");
Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.MOUSE_MOTION_EVENT_MASK);
} else {
btnTrigger.setText("Start");
Toolkit.getDefaultToolkit().removeAWTEventListener(this);
}
}
#Override
public void paint(Graphics grphcs) {
super.paint(grphcs);
Graphics2D g2d = (Graphics2D) grphcs;
if (monitor) {
g2d.setColor(Color.RED);
FontMetrics fm = g2d.getFontMetrics();
g2d.drawString(mousePoint.x + "x" + mousePoint.y, 25, fm.getHeight() + 25);
}
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/*
* Create and display the form
*/
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MouseFrame().setVisible(true);
}
});
}
#Override
public void eventDispatched(AWTEvent evt) {
if (evt instanceof MouseEvent) {
MouseEvent me = (MouseEvent) evt;
mousePoint = SwingUtilities.convertPoint(me.getComponent(), me.getPoint(), this);
repaint();
}
}
}

Categories