Button New Game not working Java [duplicate] - java

This question already has answers here:
How to draw in JPanel? (Swing/graphics Java)
(4 answers)
Closed 9 years ago.
Hi im making a project for my studies and im new in java. I need to do a game - Arkanoid. What i wanted to do is a game manu with 2 buttons "New game" and "Quit". Someone from stackoverflow.com rebuild my menu code but it still doesnt work :( After clicking a "New Game" im getting blank frame :(. Probably becouse of Gra constructor. How constructor of Gra need to look like to make it works with my menu code.
Here is the code (i will paste all Arkanoid class code and most important parts of Gra class):
Arkanoid class:
package arkanoid;
import javax.swing.*;
import java.awt.event.*;
public class Arkanoid extends JFrame
{
private static final long serialVersionUID = 5647459635833443178L;
public Arkanoid() {
super("Arkanoid");
setSize(500,400);
setTitle("Arkanoid BETA");
setLocationRelativeTo(null);
setResizable(false);
final JPanel panel = new JPanel();
setContentPane(panel);
panel.add(new JButton(new AbstractAction("New game") {
public void actionPerformed (ActionEvent e) {
panel.removeAll();
panel.add(new Gra()); //constructor of Gra need to return some Panel i think but i dont know how to do that
panel.revalidate();
panel.repaint();
}
}));
panel.add(new JButton(new AbstractAction("Quit") {
public void actionPerformed (ActionEvent e) {
Arkanoid.this.setVisible(false);
}
}));
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Arkanoid frame = new Arkanoid();
frame.setVisible(true);
}
});
}
}
Gra class:
package arkanoid;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JOptionPane;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Gra extends JPanel
{
/*some not important variables*/
Pilka pilka;
Paletka paletka;
Cegla cegla_tab[];
Serce serce_tab[];
Timer timer;
public Gra()
{
addKeyListener(new TAdapter());
setFocusable(true);
cegla_tab = new Cegla[liczba_cegiel];
serce_tab = new Serce[max_zycia];
//setDoubleBuffered(true);
timer = new Timer();
timer.scheduleAtFixedRate(new ScheduleTask(), 1000, 10);
}
public void addNotify()
{
super.addNotify();
start_gry();
}
public void start_gry()
{
pilka = new Pilka();
paletka = new Paletka();
/* painting a bricks and lifes for game start */
}
public void koniec_gry() //end of a game
{
czas_konca = System.currentTimeMillis();
gra = 3;
timer.cancel();
}
public void paint(Graphics g)
{
super.paint(g);
//repaiting ball positions, bricks and paddle
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
private class TAdapter extends KeyAdapter
{
public void keyReleased(KeyEvent e)
{
paletka.klawisz_puszczony(e);
}
public void keyPressed(KeyEvent e)
{
paletka.klawisz_wcisniety(e);
}
}
class ScheduleTask extends TimerTask
{
public void run()
{
if(paletka.czy_pausa()==false)
{
pilka.przesun();
paletka.przesun();
czy_zderzenie();
repaint();
}
}
}
public void czy_zderzenie()
{
//checking a collisions with bricks
}
}

You need to override paintComponent, not paint.
Also, Gra's constructor does return a JPanel. The constructor will return the object you're constructing, which in this case is a Gra, which is also a JPanel. This is polymorphism at work.
Oh, and as per the comment above, you really shouldn't be disposing of the graphics object.

Related

Changing the color of frame background repeatedly

So i want my methods to change the background color of my Frame every like 0.2 seconds and i tried a lot of diferent things like new methods and Threat sleep/wait but nothing worked even though trying it with System.out.print did. I have no idea what could work now so would be ice if someone helped me out, thank you beforehand!
PS.: dont mind the variable and method names was having fun with my friends xD
public void poggersModeOn()
{
f.setTitle("Insane rainbow pogg mode!!!!1!!!11!!1!! ");
int rot = (int)(Math.random()*255+1);
int gruen = (int)(Math.random()*255+1);
int blau = (int)(Math.random()*255+1);
f.setBackground(new Color(rot, gruen, blau));
}
public void poggersModeOff()
{
f.setTitle("Navigationssystem");
f.setBackground(new Color(255, 255, 255));
}
public void pogmethode() {
while(pogmode==true)
{
poggersModeOn();
//wait function right here
}
}
Assuming your using Swing, then you should use a Swing Timer, see How to Use Swing Timers
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
Timer timer = new Timer(250, new ActionListener() {
private Random rnd = new Random();
#Override
public void actionPerformed(ActionEvent e) {
int red = rnd.nextInt(255);
int green = rnd.nextInt(255);
int blue = rnd.nextInt(255);
setBackground(new Color(red, green, blue));
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
}
Why? Because Swing is single threaded (and not thread safe). See Concurrency in Swing for more details

JProgressBar instantiate it self multiple time

I'm trying to add a JProgressBar to a simple program just to learn. So far i can display it, but it adds multiple instance while i want just one to show.
Here's the code :
package package1;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
public class Opening extends JPanel {
private JProgressBar loadingBar;
private Thread t;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
//Loading bar
bar();
}
private void bar()
{
loadingBar = new JProgressBar();
t = new Thread(new LoadMyBar());
this.add(loadingBar).setLocation(25, 600);
loadingBar.setSize(625, 25);
loadingBar.setStringPainted(true);
loadingBar.setValue(0);
loadingBar.setMinimum(0);
loadingBar.setMaximum(100);
t.start();
}
class LoadMyBar implements Runnable
{
public void run(){
for(int i = loadingBar.getMinimum(); i <= loadingBar.getMaximum(); i++)
{
loadingBar.setValue(i);
try
{
t.sleep(1000);
}catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
Any idea on what i'm doing wrong?
You're calling bar() inside of the paintComponent(Graphics g) method. This method is responsible for drawing the component and can be called potentially many times and not in your control. Don't do that, but rather call it once in a constructor or some other location where it can be called just once.
You're also setting the JProgressBar's value off of the Swing event thread, something that can be dangerous to do. Use a Swing Timer instead or use a SwingWorker's progress property together with a PropertyChangeListener.
e.g.,
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
#SuppressWarnings("serial")
public class Opening extends JPanel {
private static final int TIMER_DELAY = 1000;
private JProgressBar loadingBar;
private Timer t = new Timer(TIMER_DELAY, new TimerListener());
public Opening() {
bar();
}
private void bar() {
loadingBar = new JProgressBar();
this.add(loadingBar);
loadingBar.setStringPainted(true);
loadingBar.setValue(0);
loadingBar.setMinimum(0);
loadingBar.setMaximum(100);
t.start();
}
private class TimerListener implements ActionListener {
int value = 0;
#Override
public void actionPerformed(ActionEvent e) {
if (value <= 100) {
loadingBar.setValue(value);
value++;
} else {
// value > 100
((Timer) e.getSource()).stop(); // stop timer
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Opening");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new Opening());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You are creating the JProgressBar and adding it to your class Opening in the method paintComponent().
paintComponent() is called every time, the component needs to draw itself.
This can be after resizing the window (JFrame) or some other application overlapping your application.
You should move the initialization to the constructor of Opening.
See http://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html

Switching colors in a GUI

ok so i am trying to make a small java paint program but i am having trouble trying to get my buttons to work. I was able to get one color when i instantiated the MyPanel class, but i changed it around in an attempt to make use of my buttons. I basically have it setup to where each button activates a certain constructor in the MyPanel class and each constructor activates the appropriate methods to change the colors so I can draw. Im really new to programming so any advice you guys could give me would be much appreciated. I also have an extra class that is instantiated in the MyPanel class which i didnt bother putting in because i know the problem isnt in there. All the Red class does is set the color
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;
public class Driver
{
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable()
{
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
SwingUtilities.isEventDispatchThread();
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton red = new JButton("red");
JButton blue = new JButton("blue");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
frame.pack();
frame.setSize(1000,1000);
panel.add(red);
panel.add(blue);
blue.addActionListener( new Action() );
red.addActionListener( new Action() );
}
}//end driver class
public class Action implements ActionListener
{
public void actionPerformed( ActionEvent e )
{
MyPanel d = new MyPanel();
}
}//end Action
public class MyPanel extends JPanel
{
private int xCoord = 50;
private int yCoord = 50;
private int squareW = 20;
private int squareH = 20;
Red red = new Red();
public MyPanel()
{
setBorder(BorderFactory.createLineBorder(Color.yellow));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
moveSquarer(e.getX(),e.getY());
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
moveSquarer(e.getX(),e.getY());
}
});
}
private void moveSquare(int x, int y)
{
if ((xCoord != x) || (yCoord!= y)) {
repaint(xCoord,yCoord,squareW+1,squareH+1);
red.setX(x);
red.setY(y);
repaint(red.getX(),red.getY(),red.getWidth()+1,red.getLength()+1);
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("hi",10,20);
red.paintSquare(g);
} //end MyPanel
I basically have it setup to where each button activates a certain
constructor in the MyPanel class and each constructor activates the
appropriate methods to change the colors so I can draw.
I can't see it since your ActionListener is the same for both buttons:
private static void createAndShowGUI() {
...
blue.addActionListener( new Action() );
red.addActionListener( new Action() );
...
}
public class Action implements ActionListener {
#Override
public void actionPerformed( ActionEvent e ) {
MyPanel d = new MyPanel();
}
}
This method doesn't even add this new panel to the frame so it will never be visible.
Also what is this object?
Red red = new Red();
Suggested approach
You may follow this suggested tips to achieve your goal:
Provide MyClass with a method to set the desired color.
Add an instance of this panel (or many as needed) to the frame when you initialize your GUI. Note: this/these may be added dinamically but you need to follow the hints about adding components to a displayed container described here
Use action listener to set the panel color as you whish.
For instance:
public class MyPanel extends JPanel {
private Color color = Color.red;
// this color should be used within paintComponent() method
public void setColor(Color newColor) {
color = newColor;
repaint();
}
...
}

using a jpanel in another class? (noob issue)

I have the classes:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class MyTimer extends JFrame {
static JButton quitButton;
static JButton quit_2Button;
public MyTimer() {
initUI();
}
public static void random(){
int x = (int)(Math.random() * 100 + 1);
int y = (int)(Math.random() * 150 + 1);
System.out.println(x);
System.out.println(y);
quitButton = new JButton("Press this to quit?");
quitButton.setBounds(x, y, 200, 20);
}
public void initUI() {
random();
JPanel panel = new JPanel();
getContentPane().add(panel);
panel.setLayout(null);
JButton quit_2Button = new JButton("Or maybe press this to quit!");
quit_2Button.setBounds(50, 100, 200, 20);
quit_2Button.setRolloverEnabled(true);
quit_2Button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
quitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
finder.main(null);
}
});
panel.add(quitButton);
panel.add(quit_2Button);
setTitle("Java");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
, and
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class timer_run {
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.remove(); //error here
}
};
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyTimer ex = new MyTimer();
ex.setVisible(true);
new timer_run();
}
});
}
public timer_run() {
Timer timer = new Timer(1000, al);
timer.start();
}
}
and I am trying to make it so that when actionlistener al is activated, jpanel.remove(quit_2Button) is called. The problem is, that whenever i try and do this it gives me the error "panel cannot be resolved". I assume the reason this is happening is because timer_run does not have access to the JPanel frame, but through various trial and error have not been able to fix this. Does anybody have any suggstions about what I could possibly do to let timer_run see the JPanel frame? thanks in advance, and please note I am a java noob, so make the answer as simple as you can, if possible?
Recommendations:
One class should not try to directly manipulate variables of another class.
Instead have one class call public methods of the other class.
To allow your second class to do that, you need to pass a reference of the first class's object into that of the second class. I suggest you do this via a constructor parameter.
For example
// class name should begin with an upper case letter
public class TimerRun {
private MyTimer myTimer;
public TimerRun(MyTimer myTimer) {
this.myTimer = myTimer;
}
//....
}
Now the TimerRun class can call public methods on the MyTimer object held by myTimer by calling, myTimer.someMethod()

JLabel mouse click on icon or text

When it is clicked on JLabel, I want to understand if the click was on "Icon part", or "Text part" of the JLabel, so that different action can be taken. Is there a clever way to do that? Or just I have to solve it relatively with the coordinates of the icon and text?
+1 to #aymeric comment.
What about having two different JLabels
However I do understand why you might be hesitating
negative: requires maintenance of 2 labels.
My clever (:P) solution to this is create your own abstract component - which accepts icon and text as parameters for constructor - by extending JPanel and than adding 2 JLabels to the JPanel, each label has its on MouseAdapter which calls abstract method xxxClicked() (thus any implementing class must override these methods).
Here is an example I made:
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImageIcon ii = null;
try {
//I dont remmend getScaledInstance just used it for speed of code writing
ii = new ImageIcon(ImageIO.read(new URL("http://www.candonetworking.com/java.gif")).getScaledInstance(32, 32, Image.SCALE_SMOOTH));
} catch (Exception ex) {
ex.printStackTrace();
}
MyLabel ml = new MyLabel(ii, "Something") {
#Override
void iconClicked() {
System.out.println("Icon clicked");
}
#Override
void textClicked() {
System.out.println("Text clicked");
}
};
frame.add(ml);
frame.pack();
frame.setVisible(true);
}
});
}
}
abstract class MyLabel extends JPanel {
JLabel iconLabel;
JLabel textLabel;
MouseAdapter iconMA;
MouseAdapter textMA;
public MyLabel(ImageIcon icon, String text) {
iconLabel = new JLabel(icon);
textLabel = new JLabel(text);
iconMA = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
super.mouseClicked(me);
iconClicked();
}
};
textMA = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
super.mouseClicked(me);
textClicked();
}
};
iconLabel.addMouseListener(iconMA);
textLabel.addMouseListener(textMA);
add(iconLabel);
add(textLabel);
}
abstract void iconClicked();
abstract void textClicked();
public JLabel getIconLabel() {
return iconLabel;
}
public JLabel getTextLabel() {
return textLabel;
}
}

Categories

Resources