Ok so im working on a game and right now i have an image and im trying to place buttons under the image in specific places so when the user clicks that part of the screen the image changes. I am having trouble trying to figure out how to format my program for the action listener.
public class TestJFrame{
private static JFrame frame = new JFrame();
private static JLabel label = new JLabel();
private static JButton buttons[] = new JButton[4];
private static int[][] location = new int[3][4];
public static void main(String args[]){
frame.getInsets().set(20, 5, 5, 5);
frame.setLayout(null);
frame.setPreferredSize(new Dimension(507, 528));
frame.pack();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Test");
buttons[0] = new JButton("jbZero");
buttons[1] = new JButton("jbOne");
buttons[2] = new JButton("jbTwo");
buttons[3] = new JButton("jbThree");
frame.add(buttons[0]);
frame.add(buttons[1]);
frame.add(buttons[2]);
frame.add(buttons[3]);
setButtons();
frame.setVisible(true);
buttons[0].setLocation(100, 100);
}
private static void setButtons(){
for (int i=0;i<=3;i++){
buttons[i].setSize(10, 10);
buttons[i].setLocation(0, 0);
buttons[i].setVisible(true);
}
}
public void intializeListener(){
buttons[0].addActionListener((ActionListener) this);
}
public void buttonsZeroActionPreformed(java.awt.event.ActionEvent e){
System.out.println("button zero works");
}
}
So any help would be greatly appreciated.
Depends what do you want to implement in the listener:
If they do the same action you implement the listener inside setButtons function:
private static void setButtons(){
for (int i=0;i<=3;i++){
buttons[i].setSize(10, 10);
buttons[i].setLocation(0, 0);
buttons[i].setVisible(true);
buttons[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// listener implement btn 0
}
});
}
}
If each button need unique implementation I think that better implementation will be in a new function setBtnListeners and call it from your main after using setButtons();:
private static void setBtnListeners() {
buttons[0].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// listener implement btn 0
}
});
}
Update: Sorry i'd just noticed you have four buttons... you can just add another one :)
Related
I am working on a simple counter swing app. I'm trying to make it so when you click the check box, it will stay on the top and display a message dialog being "On Top" or "Not On Top".
However, when I click the checkbox after compiling and running, both of the messages display, and after clicking OK on both messages, the checkbox isn't even enabled. If I were to remove the showMessageDialog, it would still function properly, but I want to learn how to appropriately implement this.
Thank you in advance. Here is all of the code for the program:
public Class Counter {
JFrame frame;
JPanel panel;
JButton button, clear;
JTextField textC;
JLabel label;
JCheckBox cbox;
boolean topC = false;
int icount = 0;
String scount;
String topStatus = "";
public Counter() {
gui();
setActions();
}
public void gui() {
frame = new JFrame("Counter Program");
panel = new JPanel();
label = new JLabel("Counter");
textC = new JTextField();
textC.setPreferredSize(new Dimension(72,28));
textC.setEditable(false);
button = new JButton("Click");
clear = new JButton("Clear");
cbox = new JCheckBox("Top");
frame.setSize(350,80);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(panel);
panel.add(label);
panel.add(textC);
panel.add(button);
panel.add(clear);
panel.add(cbox);
frame.setVisible(true);
}
public void setActions() {
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
icount++;
scount = Integer.toString(icount);
textC.setText(scount);
}
});
clear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
icount = 0;
textC.setText("");
}
});
cbox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
topC = !topC;
if (topC) {
topStatus = "Top";
}
else topStatus = "Not Top";
frame.setAlwaysOnTop(topC);
JOptionPane.showMessageDialog(frame, topStatus, "Top Setting", 1);
}
});
}
public static void main(String[]args) {
new Counter();
}
}
An ItemListener generates two events, one for the selection and one for the unselection (and vice versa). Read the section from the Swing tutorial on How to Write an ItemListener for more information and working exmaples if you really want to use an ItemListener.
Otherwise, use an ActionListener instead, it will only generate a single event.
I've two class. Can i change a text of a button in a class "home" with an actionlistener of the combobox in a class "panelGestisciImpianti"? I don't unterstand becasue don't works.
The code is this:
//home
package s;
public class home extends JFrame {
private JPanel contentPane;
private panelImpostazioni panel5= new panelImpostazioni();
private JButton btnImpostazioni = new JButton("no"); //$NON-NLS-1$
public static void main(String[] args) {
home frame = new home();
frame.setVisible(true);
}
public home() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState( JFrame.MAXIMIZED_BOTH) ;
setBounds(0, 0, 1963, 688);
contentPane = new JPanel();
setContentPane(contentPane);
contentPane.setLayout(null);
btnImpostazioni.setBounds(0, 560, 140, 140);
contentPane.add(btnImpostazioni);
btnImpostazioni.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
contentPane.add(panel5);
revalidate();
repaint();
}
});
}
public void changetext() {
btnImpostazioni.setText("yes");
}
}
//panelGestisciImpostazioni
package s;
public class panelImpostazioni extends JPanel {
private JComboBox comboboxLingua = new JComboBox();
static home h=new home();
public panelImpostazioni() {
setBounds(140, 0, 800, 560);
setLayout(null);
comboboxLingua.setBounds(100, 24, 150, 45);
comboboxLingua.setModel(new DefaultComboBoxModel(new String[] {"italiano", "inglese"}));
add(comboboxLingua);
comboboxLingua.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
h.changetext();
}
});
}
}
Thank you.
Its because when you create panel5 you have a new home created.
static home h = new home ().
So when you call changetext method you do it in a new invisible frame.
In order to make this work (it is really really bad) you have to pass your visible "home" as an argument to your panel5. Which means you have to initiate it in home's constructor and not as a field.
public panelImpostazioni(home h)
And in your combobox action listener
h.changetext ()
I was just messing around with GUI in Java and created a little game. In it, 105 randomly placed buttons are created and then an instruction screen pops up, telling the user which button to find. I've tried to figure out how to program a "Loading..." JDialog, which will pop up while the buttons are being created in the background. The trouble is, when I run the program the JDialog doesn't load until AFTER all the buttons have been created, which kind of defeats the purpose of the box in the first place. How can I force the "Loading..." box to load BEFORE the buttons begin to be created??? Thanks in advance.
Because I've just been tinkering, my code is not perfect but here it is:
import java.util.Scanner;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Random;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.ProgressMonitor;
public class ButtonGame {
private static int butNum = 1;
private static JFrame frame;
private static ActionListener notIt;
private static ActionListener it;
private static Random rand = new Random();
private static int butToFind = rand.nextInt(105);
private static JFrame frameToClose;
//private static int mouseClicks;
//private static double time;
public static void main(String[] args) {
//actionlistener for all incorrect buttons (buttons that are "not it")
notIt = new ActionListener() {
public void actionPerformed(ActionEvent e) {
Component component = (Component) e.getSource();
JFrame frame5 = (JFrame) SwingUtilities.getRoot(component);
frame5.dispose();
}
};
//actionlistener for the correct button (the button that's "it")
it = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame youWin = new JFrame("YOU WON!");
//removes all panels to begin game again
JButton again = new JButton("Play again");
again.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
java.awt.Window windows[] = java.awt.Window.getWindows();
for(int i=0;i<windows.length;i++){
if (windows[i] != frame) { windows[i].dispose(); }
butToFind = rand.nextInt(105);
butNum = 1;
youWin.dispose();
}
frame.setVisible(true);
}
});
//quits game
JButton win = new JButton("Quit");
win.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
//layout
youWin.setSize(775, 300);
youWin.setLayout(new FlowLayout());
JLabel label1 = new JLabel("Fantastic!");
Font font1 = new Font("Courier", Font.BOLD,120);
label1.setFont(font1);
label1.setHorizontalAlignment(JLabel.CENTER);
JLabel label2 = new JLabel("You beat the game!");
Font font2 = new Font("Courier", Font.BOLD,60);
label2.setFont(font2);
label2.setHorizontalAlignment(JLabel.CENTER);
youWin.add(label1);
youWin.add(label2);
JPanel panel = new JPanel();
youWin.add(panel);
panel.add(again);
panel.add(win);
youWin.setLocation(260, 100);
youWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
youWin.setVisible(true);
java.awt.Window windows[] = java.awt.Window.getWindows();
}
};
//start window
frame = new JFrame("Window");
frame.setLocation(400, 200);
JButton button1 = new JButton("Click to begin");
//button to begin game
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// JDialog load = new JDialog();
// load.setAlwaysOnTop(true);
// load.setSize(500,500);
// load.setVisible(true);
// load.add(new Label("Loading..."));
// load.pack();
frame.setVisible(false); // "start" window's visibility
// try {
// Thread.sleep(100000);
// } catch (Exception t) {
// }
// creates buttons
for (int i = 0; i < 105; i++) {
JFrame nextFrame = newFrame(butNum);
nextFrame.setVisible(true);
butNum++;
}
//creates instructions and tells user what button to find
JFrame instructions = new JFrame("How to play");
instructions.setSize(300,175);
instructions.setLayout(new GridLayout(4,1));
JPanel instPanel = new JPanel();
//button to remove instruction panel
JButton ok = new JButton("Ok");
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
instructions.dispose();
}
});
instPanel.add(ok);
instructions.setLocation(400,200);
//layout of instruction panel
JLabel find = new JLabel("Your goal is to find Button " + butToFind + ".");
find.setHorizontalAlignment(JLabel.CENTER);
JLabel find2 = new JLabel("Click a button to make it disappear.");
find2.setHorizontalAlignment(JLabel.CENTER);
JLabel find3 = new JLabel("Good luck!");
find3.setHorizontalAlignment(JLabel.CENTER);
instructions.add(find);
instructions.add(find2);
instructions.add(find3);
instructions.add(instPanel);
instructions.setVisible(true);
}
});
frame.add(button1);
frame.setSize(150,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
//creates frame with button in it
public static JFrame newFrame(int num) {
JFrame frame2 = new JFrame();
JButton button = new JButton("Button " + num);
if (num == butToFind) {
button.addActionListener(it);
frameToClose = frame2;
} else {
button.addActionListener(notIt);
}
frame2.add(button);
frame2.setSize(randNum(90,200), randNum(50,100));
frame2.setLocation(rand.nextInt(1200), rand.nextInt(800));
frame2.getContentPane().setBackground(new Color(rand.nextInt(255),
rand.nextInt(255),
rand.nextInt(255)));
frame2.setVisible(true);
return frame2;
}
//provides random number between high and low
public static int randNum(int low, int high) {
int result = -1;
while (result < low || result > high) {
result = rand.nextInt(high);
}
return result;
}
}
Also, as a side-question, which of the variables defined before main should be static? And how can I get the program to compile without being static? Thanks!
First take a look at The Use of Multiple JFrames, Good/Bad Practice? and understand why I freaked out when I ran your code...
Instead of creating a bunch of frames, why not use something like JButton on another JPanel and add it to the current frame (this would also be a good use for a CardLayout)
JPanel panel = new JPanel(new GridLayout(10, 0));
Random rnd = new Random();
// creates buttons
for (int i = 0; i < 105; i++) {
JButton btn = new JButton(String.valueOf(i));
panel.add(btn);
//JFrame nextFrame = newFrame(butNum);
//nextFrame.setVisible(true);
//butNum++;
}
frame.getContentPane().removeAll();
frame.add(panel);
frame.revalidate();
frame.pack();
Alternatively, if you're really hell bent on using "frames", consider using a JDesktopPane and JInternalFrame instead.
See How to Use Internal Frames for more details
Also, as a side-question, which of the variables defined before main should be static? And how can I get the program to compile without being static?
As much as possible, none. Instead of trying to create the whole thing in the main method, use the classes constructor to initialise the UI and use another method to actually get the game rolling...
public class ButtonGame {
private int butNum = 1;
private JFrame frame;
private ActionListener notIt;
private ActionListener it;
private Random rand = new Random();
private int butToFind = rand.nextInt(105);
private JFrame frameToClose;
//private static int mouseClicks;
//private static double time;
public static void main(String[] args) {
ButtonGame game = new ButtonGame();
game.start();
}
public ButtonGame() {
//... All the code that was once in main...
frame.add(button1);
frame.setSize(150, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void start() {
frame.setVisible(true);
}
Answering to your side questions:
a static method can only accept static global variables
You can put all your code in the constructor and use main to only run the program.
Constructor:
public ButtonGame() {
// All of your code goes here - except the static methods
}
You should also make all other methods non-static.
To run the program:
public static void main(String[] args) {
new ButtonGame();
}
I want to ask what function or another have to write so that every time I pressed the Start button (function:addbutton), the other button to exit (function:addButton2) to change its title to how many times I press the start?
class DroppingFrame extends JFrame {
public DroppingFrame() {
int clicked=0;
String b="a";
setSize(1400, 700);
setTitle("Dropping");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container contentPane = getContentPane();
canvas = new JPanel();
contentPane.add(canvas, "Center");
JPanel p = new JPanel();
addButton(p, "Drop ball", clicked, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//addButton.setText(String.valueOf(++clicked));
Ball b = new Ball(canvas);
// if(b== new Ball(canvas)){
// clicked++;
// }
b.start();
}
});
addButton2(p, b, clicked, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvas.setVisible(false);
System.exit(0);
}
});
contentPane.add(p, "South");
}
public void addButton(Container c, String title, int i, ActionListener a) {
//i++;
//title = Integer.toString(i);
JButton b = new JButton(title);
c.add(b);
b.addActionListener(a);
}
public void addButton2(Container c, String title, int i, ActionListener a ) {
i++;
title = Integer.toString(i);
JButton b = new JButton(title);
c.add(b);
b.addActionListener(a);
}
private JPanel canvas;
}
My preference would be:
Make clicked a class field - that way you can access it and mutate it inside the event handler
Create a class field for a button
Refactor the addButton method so there is only one of them - this makes your code tidier:
Change the method return type to return the button created, then you decide if you store it or not from the caller. This just smells nicer.
The code looks like:
class DroppingFrame extends JFrame {
final JPanel canvas = new JPanel();
JButton button2;
int clicked = 0;
public DroppingFrame() {
setSize(1400, 700);
setTitle("Dropping");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container contentPane = getContentPane();
contentPane.add(canvas, "Center");
JPanel p = new JPanel();
addButton(p, "Drop ball", clicked, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Ball b = new Ball(canvas);
b.start();
button2.setText(String.valueOf(++clicked));
}
});
button2 = addButton(p, String.valueOf(clicked), clicked, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvas.setVisible(false);
System.exit(0);
}
});
contentPane.add(p, "South");
}
public JButton addButton(Container c, String title, int i, ActionListener a) {
JButton b = new JButton(title);
c.add(b);
b.addActionListener(a);
return b;
}
}
It requires the reference of the second button so that start button can update its text.
Keep it simple:
Use setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); instead of adding WindowListener to close the window.
Use JFrame#dispose to close the JFrame programmatically.
Favor Composition over Inheritance It means if you are not overriding any logic/implementation of the existing class then don't extend it.
There is no meaning of creating separate method for adding each component. Either make the method generic or simply remove it.
Sample code:
public class DroppingFrame {
private int clicked = 0;
public DroppingFrame() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
JPanel p = new JPanel();
final JButton btn2 = new JButton(String.valueOf(clicked));
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
frame.dispose();
}
});
JButton btn1 = new JButton("Drop ball");
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
btn2.setText(String.valueOf(++clicked));
}
});
p.add(btn1);
p.add(btn2);
contentPane.add(p, BorderLayout.SOUTH);
frame.setVisible(true);
}
}
It's not correct.. addButton always creates a new button and its reference is lost.. you should make it class-scoped.
So make a class variable:
JButton button = new JButton();
Change your function:
public void addButton(Container c, String title, int i, ActionListener a) {
button.setText(title);
c.add(button);
button.addActionListener(a);
}
And also change your actionPerformed override:
public void actionPerformed(ActionEvent evt) {
button.setText(String.valueOf(++clicked));
....
});
I have some code here, and when the button is pressed, I'm trying to extend the JPanel. However, it remains at the height it was previously. Is there a way to do this or is it fixed on the dimensions it was set when it was created?
public class GUITest extends JFrame {
JPanel jp;
JButton one;
public static void main(String[] args) {
new GUITest();
}
public GUITest() {
initWidgets();
}
public void initWidgets() {
setSize(250, 250);
setTitle("Stretch Panel Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
one = new JButton("Click me!");
ActionListener extend = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < 80; i++) {
jp.setPreferredSize(new Dimension(200,(i+70)));
}
//System.out.println(jp.getHeight());
}
};
one.addActionListener(extend);
add(one, BorderLayout.NORTH);
jp = new JPanel();
jp.setBackground(Color.BLACK);
jp.setPreferredSize(new Dimension(200,70));
add(jp, BorderLayout.CENTER);
setVisible(true);
}
}
alternatively, you can call revalidate() on the jpanel after the button click
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < 80; i++) {
jp.setPreferredSize(new Dimension(200,(i+70)));
**jp.revalidate();**
}
//System.out.println(jp.getHeight());
}
to clarify, once you change the dimensions, it has to be redrawn. the thing has been changed, but it hasn't been told to update that change visually
You should use the validate() method in order to do that.
I hope i was able to help!
Have a great day!
try this:
jp.setSize(new Dimension(200,(i+70)));
instead of jp.setPreferredSize(new Dimension(200,(i+70)));
in this code on eachclick the size will be increase by 10 :
ActionListener extend = new ActionListener() {
int count=0;
public void actionPerformed(ActionEvent e) {
count=count+10;
jp.setSize(new Dimension(100+count,70+count));
System.out.println("in listener");
}
};
one more thing setPrefferedsize is the default size which is called whenever component re-validates. to change the setPrefferedSize on each click :
count=count+10;
jp.setSize(new Dimension(100+count,70+count));
jp.setPreferredSize(new Dimension(100+count,70+count));