I'm making a tank game and to avoid redundancy I'm making classes to extend. My MenuPanel looks like this atm (I've only written the code that matters for the question) (knop = dutch for button)
public class MenuPanel extends JPanel implements ActionListener
{
private JButton playKnop, highScoreKnop, quitKnop, HTPKnop;
private ImageIcon play, HS, quit, HTP;
private Tanks mainVenster;
public MenuPanel(Tanks mainVenster)
{
this.mainVenster = mainVenster;
this.setLayout(null);
int x = 95;
int width = 200;
int height = 50;
play = new ImageIcon(PlayPanel.class.getResource(/buttons/PLAY.png));
playKnop = new JButton(play);
playKnop.setBounds(x, y, width, height);
playKnop.addActionListener(this);
HS = new ImageIcon(PlayPanel.class.getResource(/buttons/HS.png));
highScoreKnop = new JButton(HS);
highScoreKnop.setBounds(x, 460, width, height);
highScoreKnop.addActionListener(this);
HTP = new ImageIcon(PlayPanel.class.getResource(/buttons/HTP.png));
HTPKnop = new JButton(HTP);
HTPKnop.setBounds(x, 515, width, height);
HTPKnop.addActionListener(this);
quit = new ImageIcon(PlayPanel.class.getResource(/buttons/QUIT.png));
quitKnop = new JButton(quit);
quitKnop.setBounds(x, 570, width, height);
quitKnop.addActionListener(this);
this.add(playKnop);
this.add(quitKnop);
this.add(HTPKnop);
this.add(highScoreKnop);
validate();
}
}
because the code to make the buttons is exactly the same (except for the backgroundPath and the y-coordinate) I made a class button:
package menu;
import java.awt.Image;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
public class button
{
public JButton button;
public ImageIcon buttonImage;
public int x = 95;
public int width = 200;
public int height = 50;
public String backgroundPath;
public int y;
public button(String backgroundPath, int y)
{
this.backgroundPath = backgroundPath;
this.y = y;
buttonImage = new ImageIcon(PlayPanel.class.getResource(backgroundPath));
button = new JButton();
button.setBounds(x, y, width, height);;
button.addActionListener(this);
}
}
that way, my menuPanel COULD look like this:
package menu;
@SuppressWarnings("serial")
public class MenuPanel extends JPanel implements ActionListener
{
private button playKnop, highScoreKnop, quitKnop, HTPKnop;
private JTextField naam;
private Tanks mainVenster;
public MenuPanel(Tanks mainVenster)
{
this.mainVenster = mainVenster;
this.setLayout(null);
playKnop = new button("/buttons/PLAY.png", 350);
highScoreKnop = new button("/buttons/HS.png", 460);
quitKnop = new button("/buttons/QUIT.png", 515);
HTPKnop = new button("/buttons/HTP.png", 570);
this.add(playKnop);
this.add(quitKnop);
this.add(HTPKnop);
this.add(highScoreKnop);
validate();
}
}
I don't know why, but when I do this the buttons won't appear, although the code from the button class is correct (bc when I use the code in the menuPanel itself it works)
I don't know how to fix this problem and I have multiple problems like this in my whole JavaProject, but if someone could explain me how to fix this I could get rid of all the redundancy in my project.
Thanks in advance, Lola
Thank you all so much! a combination of your answers helped me to let the buttons appear, but for some kind of reason the images don't load with them. my code now looks like:
public class MenuPanel extends JPanel implements ActionListener {
private Button playKnop, highScoreKnop, quitKnop, HTPKnop;
private Tanks mainVenster;
int x = 95, width = 200, height = 50;
public MenuPanel(Tanks mainVenster)
{
this.mainVenster = mainVenster;
this.setLayout(null);
playKnop = new Button("/buttons/PLAY.png", 350, this);
highScoreKnop = new Button("/buttons/HS.png", 460, this);
quitKnop = new Button("/buttons/QUIT.png", 515, this);
HTPKnop = new Button("/buttons/HTP.png", 570, this);
this.add(playKnop);
this.add(quitKnop);
this.add(HTPKnop);
this.add(highScoreKnop);
validate();
}
public class Button extends JButton
{
JButton button;
ImageIcon buttonImage;
String backgroundPath;
int y;
public Button(String backgroundPath, int y, MenuPanel menuPanel)
{
super();
this.backgroundPath = backgroundPath;
this.y = y;
buttonImage = new ImageIcon(PlayPanel.class.getResource(backgroundPath));
this.setBounds(x, y, width, height);;
this.addActionListener(menuPanel);
}
}
}
(all the buttons do work!)
Firstly, all class names should begin with a capital letter as a convention, this does not affect compilation but is good practice.
Now, for your actual problem, the first thing that stands out to me is that your Button
Class does not extend anything. This to me seems to be the reason why it does not appear on the screen. I would suggest making Button
extend JButton
:
public class Button extends JButton {
// Implementation Code
}
This is similar to how your MenuPanel
extends JPanel
. The JPanel
cannot render a custom Button
that you wrote. By extending JButton
it will be able to render it as it knows how to interact with a JButton
I think you can better let your Button class extend JButton. In that way you can just add your own button class to the menupanel.
public class Button extends JButton
{
public JButton button;
public ImageIcon buttonImage;
public int x = 95;
public int width = 200;
public int height = 50;
public String backgroundPath;
public int y;
public Button(String backgroundPath, int y, MenuPanel menuPanel)
{
super()
this.backgroundPath = backgroundPath;
this.y = y;
buttonImage = new ImageIcon(PlayPanel.class.getResource(backgroundPath));
this.setBounds(x, y, width, height);;
this.addActionListener(menuPanel);
}
}
Can you observe the difference between the line:
playKnop.addActionListener(this);
and the one in later code:
playKnop = new button("/buttons/PLAY.png", 350);
I believe you want to add MenuPanel
as action listener but you are not passing the reference to it in later code. You should rather have: playKnop = new button("/buttons/PLAY.png", 350, this);
And then set this reference in your Button
class like:
public button(String backgroundPath, int y, MenuPanel menuPanel)
{
this.backgroundPath = backgroundPath;
this.y = y;
buttonImage = new ImageIcon(PlayPanel.class.getResource(backgroundPath));
button = new JButton();
button.setBounds(x, y, width, height);;
button.addActionListener(menuPanel);
}
The difference is that you are no longer adding JButtons to the JPanel.
For this code to work, your "button" class must extend JPanel.
Another way to extract the shared code would be to create a "Button creator method" instead of a class, something like:
public class MenuPanel extends JPanel implements ActionListener
{
int y = 95, width = 200, height = 50;
private JButton playKnop, highScoreKnop, quitKnop, HTPKnop;
public MenuPanel()
{
this.setLayout(null);
playKnop = createButton("/buttons/PLAY.png", 350);
highScoreKnop = createButton("/buttons/HS.png", 460);
quitKnop = createButton("/buttons/QUIT.png", 515);
HTPKnop = createButton("/buttons/HTP.png", 570);
this.add(playKnop);
this.add(quitKnop);
this.add(HTPKnop);
this.add(highScoreKnop);
validate();
}
private JButton createButton(String path, int x) {
ImageIcon icon = new ImageIcon(MenuPanel.class.getResource(path));
JButton button = new JButton(icon);
button.setBounds(x, y, width, height);
button.addActionListener(this);
return button;
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
In the existing MenuPanel
, when you do
this.add(playKnop);
you are adding a JButton
to your JPanel
In the new MenuPanel
you are adding a button
to your JPanel
.
You need to add a JButton
to a JPanel
.
Also choose Button
rather than button
for class names.
The solution is to rewrite this code so that you are adding JButton
s rather than button
s to your panel. There may be other issues with the code too.
There is a difference in what you are adding . In the new code you are adding instances of your button
class to the JPanel. In the old code you added JButtons
. buttons
can't be displayed as they're not swing classes, the old JButtons could.
Extending button from JButton should do the trick:
public class button extends JButton {
// public JButton button; // this line is depreceted now
public ImageIcon buttonImage;
...
Also, learn about code formatting and style in Java . This will help you write clearer code and prevent confusions as above. Eg you have a class named button
with a field named button
and a method named button
. Use different names as Button
(classes are always upper case!), button
and createButton
.
Try adding a getButton in the class button to return the button for adding
public JButton getJButton(){
retun this.button
}
then add use this on adding on the menu panel
this.add(playKnop.getJButton());
There is nothing wrong with your code. The only problem that I can see is that your Class button
extend Object
instead of JButton
. So just do the following change and I feel it should work:
Instead of :
public class button
write
public class button extends JButton
Perhaps you want to make your button class inherit JButton instead of keeping a button field. That way, you could add the button to the panel.
I am not very familiar with the JButton class. You need to set the buttonImage as background. Maybe there is some function like:
this.setBackground(buttonImage);
If there is no function liek this, you can set the background in the Constructor. Similar to your examples above. You always created a new Button with:
JButton b = new JButton(buttonImage);
You can give the same parameters to the super()-methode in your own Constructor. The result will look liek this:
public class Button extends JButton
{
String backgroundPath;
int y;
public Button(String backgroundPath, int y, MenuPanel menuPanel)
{
super(new ImageIcon(PlayPanel.class.getResource(backgroundPath)));
this.backgroundPath = backgroundPath;
this.y = y;
this.setBounds(x, y, width, height);
this.addActionListener(menuPanel);
}
}
This code is not tested.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.