why JPanel never calls a reapint - java

Hi I wanted to write a simple arcanoid game but for some reason my JPanel.repaint() is never called and my ball doesn't move. So in my main class extends JPanel to the JPanel I add a listener that is called when user wants to start a game and as a result a thread is fired this thread changes the position of the ball and should (ideally) call the repaint on my jpanel class. I checked the position of the ball changes but the repaint method is never called. Can someone please help? Thanks in advance here is my code:
public class test extends JPanel{
int x=250;
int y=470;
int width=100;
int height=20;
Ball b=new Ball();
public static void main(String[] args){
test t=new test();
t.draw();
}
public void draw(){
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(520, 520);
frame.setResizable(false);
this.setSize(500,500);
frame.add(this);
this.addMouseListener(new mouseL());
frame.setVisible(true);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
System.out.println("Yeah I am called");
Graphics2D g2d=(Graphics2D) g;
g2d.setColor(Color.blue);
g2d.fillRect(x, y, width, height);
g2d.setColor(b.getColor());
g2d.fillOval(b.x1, b.y1, b.width1, b.height1);
}
class Ball{
Random rand=new Random();
int x1=300;
int y1=450;
int height1=20;
int width1=20;
Color c;
public Color getColor(){
return new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255));
}
}
class mouseL implements MouseListener{
Thread t=new Thread(new MyRun());
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
t.run();
}
#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
}
}
class MyRun implements Runnable{
#Override
public void run() {
// TODO Auto-generated method stub
try{
while(true){
//System.out.println("Yeah I work");
test.this.b.x1=test.this.b.x1-1;
test.this.b.y1=test.this.b.y1-1;
System.out.println("the values are: "+test.this.b.x1+" and "+test.this.b.y1);
Thread.sleep(2000);
test.this.repaint();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}

t.run(); calls (in your case) Runnabe#run, which is executed from within the context of the Event Dispatching Thread, thereby freezing your UI for ever.
You should have used t.start()
Because Swing is single threaded, you are running the risk of race conditions and dirty read/writes between the variables. A safer and simpler solution would be to use a Swing Timer, see How to use Swing Timers, which schedules it's notifications within the EDT, making safe to update the UI from
Also, take a look at How can I set in the midst? for reasons why you shouldn't use JFrame#setSize and should instead, override the getPreferredSize method of your JPanel and call JFrame#pack instead

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.

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
}

Why does it terminate the program when its supposed to bring the main page back visible?

Button actionlistener. (r is the call method for my class i call it above Run r= new Run();. it sets the window invisible but when it's supposed to get it back visible the program closes without any errors. Tried instead of setVisible(false); dispose(); but same problem.
about.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
JFrame a=new JFrame("About");
a.addWindowListener(new WindowListener(){
#Override
public void windowActivated(WindowEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void windowClosed(WindowEvent arg0) {
}
#Override
public void windowClosing(WindowEvent arg0) {
r.gui.setVisible(true);
}
#Override
public void windowDeactivated(WindowEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void windowDeiconified(WindowEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void windowIconified(WindowEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void windowOpened(WindowEvent arg0) {
r.gui.setVisible(false);
}
});
a.setSize(400, 400);
a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
a.setVisible(true);
a.setLayout(null);
JLabel lbl=new JLabel("This game was made by your lovely neighbourhood takisp22");
lbl.setSize(500,50);
lbl.setLocation(0,0);
a.setLocation(100,50);
a.add(lbl);
}
});
Other Class which runs the program:
import javax.swing.JFrame;
public class Run {
public static GameAim gui=new GameAim();
public static void main(String[] args){
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setTitle("Aim Training");
gui.setSize(1280, 800);
gui.setVisible(true);
gui.setLocation(100,50);
gui.setResizable(false);
gui.openFile();
gui.readFile();
gui.closeFile();
}
}
Because of this:
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
when you close the gui JFrame variable, the program exits.
Don't use this, but instead use JFrame.DISPOSE_ON_CLOSE. Having said this, please read: The Use of Multiple JFrames, Good/Bad Practice?. Your user is not going to like to have multiple windows shoved at them. Swap views instead with a CardLayout -- tutorial link.
We'll also need to discuss the evils of your use of a.setLayout(null); at some time.
;)

JFrame Display - Mouse Listeners

I am currently developing a game in java.When I start my game I get to chose between Full Screen and Window Mode, by clicking somewhere in the frame.The Window Mode works perfectly, but I have some issues at the full screen mode.So if I have in my main() just a simple initialization of the game, like new FullscreenMode(), the game works perfect, the listeners are working.In the code bellow if I launch the full screen Mode frame from the constructor it works perfect, but if I launch it from a function that belongs to my class, all the listeners won't work...And when I say it's not working properly, I mean the listeners are not responding, everywhere I click I get no response from the game, but if the full screen Mode Frame is launched from the constructor everything works perfectly.Thank you in advance!
public class ResolutionChoser extends JFrame implements MouseMotionListener,
MouseListener {
private static final long serialVersionUID = 1L;
private BufferedImageLoader loader;
private BufferedImage rezImg = null;
public ResolutionChoser() {
super("Welcome!");
requestFocus();
loader = new BufferedImageLoader();
rezImg = loader.loadImage("/RezImg.png");
this.setPreferredSize(new Dimension(Game.WIDTH * Game.SCALE + 2,
Game.HEIGHT * Game.SCALE + 2));
this.setMaximumSize(new Dimension(Game.WIDTH * Game.SCALE + 2,
Game.HEIGHT * Game.SCALE + 2));
this.setMinimumSize(new Dimension(Game.WIDTH * Game.SCALE + 2,
Game.HEIGHT * Game.SCALE + 2));
this.pack();
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setVisible(true);
addMouseMotionListener(this);
addMouseListener(this);
JLabel jl = new JLabel() {
private static final long serialVersionUID = 1L;
#Override
public void paintComponent(Graphics g) {
g.drawImage(rezImg, 0, 0, null);
}
};
setContentPane(jl);
//Works Perfectly if I do it like so
// launchFullScreen();
}
//Method that launches my fullscreen game
public void launchFullScreen() {
removeMouseMotionListener(this);
removeMouseListener(this);
MultiBufferTest.main(null);
}
public static void main(String[] args) {
ResolutionChoser rc = new ResolutionChoser();
}
#Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println("CLICKED AT: " + arg0.getX() + "--" + arg0.getY());
launchFullScreen();
//not working properly, the listeners for my game aren't responding
}
#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
}
}
Well, you are removing the listeners in your launchFullScreen() method:
public void launchFullScreen() {
removeMouseMotionListener(this);
removeMouseListener(this);
MultiBufferTest.main(null);
}
How do you expect the listeners to respond?
Don't attach Mouseisteners directly to a frame, there is a JRootPane and content pane (and possibly a glass pane) between the frame the user, any one of theses could be stealing mouse events, which will prevent your frame from receiving mouse events.
Instead, attach the MouseListener to the top level component directly
Also...
JLabel jl = new JLabel() {
private static final long serialVersionUID = 1L;
#Override
public void paintComponent(Graphics g) {
g.drawImage(rezImg, 0, 0, null);
}
};
this is not only a bad idea (you've broken the paint chain), it's also not required, as JLabel is capable of displaying images.
See Painting in AWT and Swing,
Performing Custom Painting and
How to Use Labels for more details

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