For a game I'm making, I want the player to begin at a menu screen(Panel05), and then click a button to start the actual game(Panel00). And, when playing the game, if they win or lose, when they click another button they either go back to the menu or go onto another level. Right now, the panels are all separate programs, with their own drivers, and I'm unsure on how to get one panel to work inside another, if that is at all possible. I would appreciate any and all advice, answers, or criticism given. Below is the panel for the menu
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
public class Panel05 extends JPanel
{
private BufferedImage myImage;
private Graphics myBuffer;
public JButton button1;
public Panel05()
{
myImage = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
myBuffer = myImage.getGraphics();
setLayout(null);
button1 = new JButton();
button1.setSize(100, 100);
button1.setLocation(500,500);
button1.setForeground(Color.WHITE);
button1.setFont(new Font("Serif", Font.BOLD, 30));
button1.setText("Start");
button1.addActionListener(new B1Listener());
button1.setBorder(null);
button1.setOpaque(false);
button1.setContentAreaFilled(false);
button1.setBorderPainted(false);
add(button1);
setFocusable(true);
}
public void paintComponent(Graphics g)
{
ImageIcon Nintendo = new ImageIcon("trumpL.png");
g.drawImage(Nintendo.getImage(), 0, 0, 1000, 1000, null);
}
private class B1Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
}
}
}
And here is the panel for the actual first level of the game.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.swing.Timer;
public class Panel00 extends JPanel
{
private BufferedImage myImage;
private Graphics myBuffer;
public Timer timer;
public JButton button1;
public JButton button2;
public JLabel label1 = new JLabel("Good Choice!");
public JLabel label2 = new JLabel("You're Fired!!");
public int x = 5; //CountDown from 5
public int delay = 1000; //milliseconds
boolean drawWin = false;
boolean drawLose = false;
public Panel00()
{
myImage = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
myBuffer = myImage.getGraphics();
setLayout(null);
button1 = new JButton();
button1.setSize(300, 200);
button1.setLocation(100,150);
button1.setFont(new Font("Serif", Font.BOLD, 18));
button1.setText("<html><center>"+"Until we are able to determine and understand this problem"+"<br>"+" and the dangerous threat it poses, our country cannot be the victims of horrendous attacks"+"<br>"+"by people that believe only in Jihad, and have no sense of reason or respect for human life"+"</center></html>");
button1.addActionListener(new B1Listener());
button1.setBorder(null);
button1.setOpaque(false);
button1.setContentAreaFilled(false);
button1.setBorderPainted(false);
add(button1);
button2 = new JButton();
button2.setSize(300, 200);
button2.setLocation(600,150);
button2.setFont(new Font("Serif", Font.BOLD, 18));
button2.setText("<html><center>"+"If ISIS wants to fight, fine with us. "+"<br>"+"We have wanted that fight for a long time. There is no room in the world for ISIS any more."+"<br>"+"The Muslims or us, one of us will have to go."+"</center></html>");
button2.addActionListener(new B2Listener());
button2.setBorder(null);
button2.setOpaque(false);
button2.setContentAreaFilled(false);
button2.setBorderPainted(false);
add(button2);
ActionListener counter =
new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
repaint();
x--;
if (x == 0)
{
timer.stop();
}
}
};
timer = new Timer(delay, counter);
timer.start();
setFocusable(true);
}
public void paintComponent(Graphics g)
{
ImageIcon Nintendo = new ImageIcon("trump speech.jpg");
g.drawImage(Nintendo.getImage(), 0, 0, 1000, 1000, null);
ImageIcon N = new ImageIcon("happy.JPG");
g.setColor(Color.WHITE);
g.fillOval(90,100,320,320);
g.setColor(Color.WHITE);
g.fillOval(590,100,320,320);
g.setColor(Color.WHITE);
g.setFont(new Font("Serif",Font.BOLD, 50));
g.drawString(""+x,500,50);
if (drawWin)
{
g.drawImage(N.getImage(), 0, 0, 1000, 1000, null);
}
ImageIcon L = new ImageIcon("loser.JPG");
if (drawLose)
{
g.drawImage(L.getImage(), 0, 0, 1000, 1000, null);
}
}
private class B1Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
repaint();
drawWin = true;
label1.setLocation(250,650);
label1.setSize(1000, 400);
label1.setForeground(new Color(212, 175, 55));
label1.setFont(new Font("Serif", Font.BOLD, 100));
add(label1);
button1.setEnabled(false);
button2.setEnabled(false);
button1.setText("");
button2.setText("");
timer.stop();
}
}
private class B2Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
repaint();
drawLose = true;
label2.setLocation(500,700);
label2.setSize(400, 400);
label2.setForeground(Color.RED);
label2.setFont(new Font("Serif", Font.BOLD, 40));
add(label2);
button1.setEnabled(false);
button2.setEnabled(false);
button1.setText("");
button2.setText("");
timer.stop();
}
}
}
Suggestions:
First and foremost, swap JPanels using a CardLayout. You'll need another JPanel, one that uses the CardLayout, you'll add your two JPanels above to this first JPanel with an appropriate String constant, and then you can swap JPanels at will. The CardLayout Tutorial will show you how. I have posted some code that can be found in some of these links. Here's a nice one.
Other serious issues in your code -- first and foremost, never read in images or any other files within a paintComponent method. This method is what mostly determines the perceived responsiveness of your GUI, and you never want to slow it down. But also, why do this? Why not read in the image once, store it in a variable, and be done with it?
Also call the super.paintComponent(...) method within your override, else you may not rid your GUI of dirty pixels.
Also Avoid using null layouts like the plague. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 months ago.
Improve this question
Question: Write JFrame that when you press the "start" button draws, and keep drawing random colored and sized filled ovals until the "stop" button is pressed.
Problem: loop inside the actionPerformed method() Doesn't Work.
The Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class p6 extends JFrame implements ActionListener
{
String str;
JButton start,stop;
int h=0,w=0;
p6()
{
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(1500,1000);
start= new JButton("Start");
stop= new JButton("Stop");
setLayout(null);
start.setBounds(500, 50, 100,30);
stop.setBounds(610, 50, 100,30);
add(start);
add(stop);
start.addActionListener(this);
stop.addActionListener(this);
}
public void actionPerformed(ActionEvent ae)
{
String c=ae.getActionCommand();
if(c=="Start")
{
while(c!="Stop")
{
h+=20;
w+=20;
}
repaint();
}
str=" "+h+" "+w;
}
public void paint(Graphics g)
{
super.paintComponents(g);
g.drawString(str, 100, 100);
//g.drawOval(100, 100, 100, 100);
g.drawOval((int)Math.random()*2000,(int) Math.random()*2000, w,h);
}
public static void main(String[] args)
{
new p6();
}
}
Let's start with How do I compare strings in Java?. This is pretty basic Java 101 and something you REALLY need to understand.
The move onto Concurrency in Swing. Swing is a single threaded. This means that any long running or blocking operations executed within the context of the Event Dispatching Thread will cause the app to "hang" and prevent any further possible updates or interaction.
Swing is also not thread safe, which means that you should only ever update the UI or state the UI depends on, from within the context of the Event Dispatching Thread.
This might seem like a dilemma, but Swing also provides a useful tool to help work with these constraints, see How to user Swing Timer for more details.
Swing also has a well defined and documented painting process, see Painting in AWT and Swing and Performing Custom Painting to get a better understand of how painting works in Swing and how you're suppose to work with it
It is generally recommended not to override the paint method of top level containers (like JFrame). These tend to be composite components and trying to paint on them tends to end up not working very well.
Image from How to Use Root Panes
And you really should make the time to learn how to use layout managers, see Laying Out Components Within a Container. They will save many hours of frustration. The following examples makes use of both a BorderLayout and CardLayout.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 {
private CardLayout cardLayout;
private JPanel showPane;
private DrawingPane drawingPane;
public TestPane() {
setLayout(new BorderLayout());
cardLayout = new CardLayout();
showPane = new JPanel(cardLayout);
showPane.add(new EmptyPane(), "Empty");
drawingPane = new DrawingPane();
showPane.add(drawingPane, "Drawing");
cardLayout.show(showPane, "Empty");
add(showPane);
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
stopButton.setEnabled(false);
JPanel actionsPane = new JPanel();
actionsPane.add(startButton);
actionsPane.add(stopButton);
add(actionsPane, BorderLayout.SOUTH);
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
startButton.setEnabled(false);
stopButton.setEnabled(true);
drawingPane.start();
cardLayout.show(showPane, "Drawing");
}
});
stopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
startButton.setEnabled(true);
stopButton.setEnabled(false);
drawingPane.stop();
cardLayout.show(showPane, "Empty");
}
});
}
}
public class EmptyPane extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public class DrawingPane extends JPanel {
private int h = 0, w = 0;
private Timer timer;
private Random rnd = new Random();
public DrawingPane() {
}
public void start() {
if (timer == null) {
timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
h += 20;
w += 20;
repaint();
}
});
}
timer.start();
}
public void stop() {
if (timer != null) {
timer.stop();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
int x = 0;
int y = 0;
if (w < getWidth() && h < getHeight()) {
x = rnd.nextInt(0, getWidth() - w);
y = rnd.nextInt(0, getHeight() - w);
}
g2d.drawOval(x, y, w, h);
g2d.dispose();
}
}
}
Why make use of CardLayout?
Based on the original code, when not painting, nothing is shown. So I made use of a CardLayout to switch to an "empty" state. Now, it wouldn't be very hard to derive a model to hold the state information and share that between the "empty" and "running" states and show something different on the "empty" state. Equally, we could make use of the glassPane, but I think we're drifting of course.
The purpose is to demonstrate ONE possible solution for showing different states.
Why use two different panes?
First, we don't "need" EmptyPane, we could get away with just an instance of JPanel, but, if you wanted to display something else when not drawing, this is one approach you could take.
The original code had a if statement which means that when not drawing, nothing is painted, so why waste the time and instead just show a "empty" pane instead.
Again, this is just a demonstration of one possible solution.
You have to add these lines before actionPerformed method,
start.setActionCommand("start");
stop.setActionCommand("stop");
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TowerDefence extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
ImageIcon EasyImage = new ImageIcon("WelcomeImage.png");
Image Image = EasyImage.getImage();
Image newimg = Image.getScaledInstance(1000, 700, java.awt.Image.SCALE_SMOOTH);
EasyImage = new ImageIcon(newimg);
EasyImage.paintIcon(this, g, 0, 0);
JButton button = new JButton("Click Button");
button.setBounds(100, 100, 100, 100);
super.add(button);
}
public static void main(String[] args) throws Exception {
TowerDefence T = new TowerDefence();
JFrame frame = new JFrame("Sam");
frame.setVisible(true);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setBounds(150, 20, 1000, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(T);
}
}
Why is this printing out 2 JButtons? I literally don't know how this works and it would be nice to know. The idea is to literally print out a picture and a button and I can't even get that to work lol. The main issue is I don't know how to use the paint component as I am quite new to java.
First don't use setBounds unless you have a null type layout.
Second don't use a null layout unless you want to handle everything about the layout.
ImageIcon easyImage;
public TowerDefense(){
EasyImage = new ImageIcon("WelcomeImage.png");
Image Image = EasyImage.getImage();
Image newimg = Image.getScaledInstance(1000, 700, java.awt.Image.SCALE_SMOOTH);
JButton button = new JButton("Click Button");
add(button);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
EasyImage.paintIcon(this, g, 0, 0);
}
I've re-arranged the code to try to separate the painting and the initialization. I strongly recommend checking out the link provided by Abra because you'll save quite a few headaches.
I'm new here. Been reading questions and answers for aeons. Recently I found time to start studying Java, and I'm seriously enjoying the process. Until I started to write some code. The getting stuck is killing me. So I've come to seek advice on something extremely simple but I cannot crack it.
The code below attempts to create a frame, maximize it, and place elements inside. I was just fooling around. First the button1, I tried to change its size (so I got it into a FlowLayout). Then a button in the mainPanel, just to... try. Then an oval. I tried for 2 hours to get the oval to display but it is Impossible. When I found about "drawOval" I thought that was it but it made no difference. And to think that I was planning for the button1 to create Moving Balls. I'm so, So far away from that.
Please, why does the silly Oval refuse to display itself. Help.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MainClass {
JFrame frame = new JFrame();
JPanel mainPanel = new JPanel();
JPanel southPanel = new JPanel();
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
Oval oval = new Oval();
public static void main(String[] args) {
MainClass program = new MainClass();
program.go();
}
public void go() {
buildGUI();
}
public void buildGUI() {
button1.setBorder(BorderFactory.createMatteBorder(2,2,2,2, Color.BLACK));
button1.addActionListener(new Button1Listener());
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
button1.setPreferredSize(new Dimension(200, 50));
frame.getContentPane().add(BorderLayout.SOUTH, southPanel);
southPanel.add(button1);
mainPanel.add(button2);
mainPanel.add(oval);
frame.setSize(400, 400);
frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
class Button1Listener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
//What the button will do.
}
}
}
And the Oval part
import java.awt.*;
import javax.swing.*;
public class Oval extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.orange);
g.fillOval(20, 50, 100, 100);
}
}
JPanel uses a FlowLayout by default. Since you Oval class doesn't provide any sizing hints, then it's set to a default size of 0x0.
Start by updating your class to something more like...
public class Oval extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(120, 150);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.orange);
g.fillOval(20, 50, 100, 100);
}
}
to create Moving Balls.
Ok, you might want to have a look at:
java bounceBall mouse escape
paintComponent not working
I'm fairly new to Java, and I have totally self taught my self to this point.
Right now I am trying to add a KeyListener to my JFrame class, I have no idea what I'm doing wrong and need some help. Any other tips are welcome.
My JFrame class:
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class TestJavaFrame implements ActionListener, KeyListener {
private static JFrame frame = new JFrame();
// Componenets
JLabel timeinmslabel = new JLabel("Enter the time in miliseconds:");
JTextField timeinms = new JTextField();
JRadioButton checkBox = new JRadioButton();
JRadioButton checkBox2 = new JRadioButton();
private boolean amountoftimes = false;
public TestJavaFrame(String windowname) {
frame.setName(windowname);
frame.setResizable(true);
frame.setSize(900, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(150, 50);
// JPanel
JPanel panel = new JPanel();
panel.setLayout(null);
panel.setBounds(frame.getBounds());
// Bounds for components
timeinmslabel.setBounds((int) (frame.getBounds().getX() / 2), 125, 200, 25);
timeinms.setBounds((int) (frame.getBounds().getX() / 2 + 185), 125, 200, 25);
checkBox.setBounds((int) (frame.getBounds().getX() / 2 + 185), 40, 200, 25);
checkBox2.setBounds((int) (frame.getBounds().getX() / 2 + 185), 70, 200, 25);
// Action Listeners
checkBox.addActionListener(this);
frame.addKeyListener(this);
// edit components
checkBox.setText("Use clicked amount of times.");
// add components
panel.add(timeinmslabel);
panel.add(timeinms);
panel.add(checkBox);
panel.add(checkBox2);
frame.add(panel);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
System.out.println(e);
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyChar());
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println(e.getKeyChar());
}
#Override
public void keyTyped(KeyEvent e) {
System.out.println(e.getKeyChar());
}
}
If you need my main, I'm perfectly fine with posting it, all it does right now is create this gui though.
So when the user hits the specific key it stops the auto clicker
Yes you can add the Key Binding to the panel.
A better approach is to create a menu bar for the various Actions support by your application. Then you can have menu items to start/stop the clicker. When you create the menu items you can then assign an accelerator to the menu item and the menu item will create the key bindings for you automatically.
This is a better solution because the "key binding" is self documenting since it is part of the menu item.
Read the section from the Swing tutorial on How to Use Menus for more information and working examples to get you started.
as I said I'm trying to learn here.
Keep a link to the tutorial handy for all Swing basics. There are also sections on "Key Bindings" and "How to Use Actions".
I'm from Germany. My English isn't very good but I try to do as less mistakes as possible. In addition it's my first question in this community and I hope I will get a useful and helpful answer (I've asked Google for more than 20 times)
So, I've wrote a program that paints two rectangles in different colors. When I click on a button, the color of one of these rectangles should change but it doesn't do so. I've tried repaint(), validate() and something I don't understand: pack()
Nothing helps. The color changes when I resize the windows but it should changes when I click the button...
Does somebody have an idea or the answer for this problem?
My code:
import java.awt.Graphics2D;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
#SuppressWarnings("serial")
public class Test extends JFrame {
public static boolean buttonClicked = false;
public Test() {
initComponents();
}
private void initComponents() {
zeichne z = new zeichne();
JFrame frame = new JFrame();
frame.setTitle("Grafiktest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
Dimension dm = new Dimension(500,500);
frame.setMinimumSize(dm);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JButton button = new JButton("Push me!");
button.setSize(100, 50);
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonActionPerformed(evt);
}
});
panel.add(z);
panel.add(button, BorderLayout.SOUTH);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new Test();
}
private void buttonActionPerformed(java.awt.event.ActionEvent evt){
if(buttonClicked == false)
buttonClicked = true;
else
buttonClicked = false;
repaint();
}
public static boolean getClicked() {
return buttonClicked;
}
}
#SuppressWarnings("serial")
class zeichne extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawRect(0, 0, 150, 100);
g2.setColor(Color.black);
g2.fillRect(0, 0, 150, 100);
boolean clicked = Test.getClicked();
if(clicked) {
g2.setColor(Color.red);
}
else {
g2.setColor(Color.gray);
}
g2.fillRect(10,10,130,80);
System.out.println(g2.getColor());
}
}
The properties of a components should be defined within the component. For example when you use a JLabel you can use setText(...), setForeground(...), setFont(...) etc. to change the state of the label and then the label will repaint itself.
So when you do custom painting you should do the same thing. That is in your "Zeichne" class you create a method to change the state of the class like setSelected(...). So your code might be something like:
public void setSelected(boolean selected)
{
this.selected = selected;
repaint();
}
You would also need to create the isSelected() method so you can access the state of the property. Then in the paintComponent(...) method you can do:
g2.setColor( selected ? Color.RED : Color.GRAY );
g2.fillRect(10,10,130,80);
Finally in the ActionListener the code would be:
z.setSelected( !z.isSelected() );
I get it!
The extension of JFrame and the additional declaration of a JFrame was the problem. I've deleted the declaration, put the super() into the method Test() and modulated the used methods of JFrame. Now it's working.
Thanks for your help!