Have a little problem with some code i have writing to try out something. I have made a frame with a single button in it. When i click on this button, a new frame opens, which it should. I close down the new frame, and then click on the button again, to try see if it still works. The problem starts here, corse insted of opening a single new frame, it opens two new frames. Third time i click it opens 4 frames and so on. I have tried quite a few things, but sadly cant seem to find the reason why it is opening more frames. Please help.
package budget;
import java.awt.event.*;
import javax.swing.*;
public class GUI extends JFrame {
String labelPrefix;
JButton button;
JButton button2;
JLabel label;
public static void main(String[] args) {
JFrame f = new GUI();
f.setExtendedState(f.MAXIMIZED_BOTH);
f.setVisible(true);
}
public GUI() {
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
p.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
button = new JButton("Click Me");
label = new JLabel(labelPrefix);
p.add(button);
this.setTitle("Try");
getContentPane().add(p);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
button.addActionListener(new MyActionListener());
}
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
button.addActionListener(this);
labelPrefix = "Try";
JFrame f2 = new GUI(label, labelPrefix);
f2.setExtendedState(f2.MAXIMIZED_BOTH);
f2.setVisible(true);
}
}
public GUI(JLabel label, String labelPrefix) {
JPanel p2 = new JPanel();
button2 = new JButton("Close");
p2.add(label);
p2.add(button2);
this.setTitle("Try");
getContentPane().add(p2);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
button2.addActionListener(new MyActionListener2());
}
class MyActionListener2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
button2.addActionListener(this);
dispose();
}
}
}
Clearly, the problem is here:
button.addActionListener(this);
Every time you click the button, it adds the listener yet another time to the button.
Simply remove that line and the error will go away. Once a listener is added to a button, it stays there. It isn't "consumed" after being triggered.
Check the first line in the actionPerformed of MyActionListener which states:
button.addActionListener(this);
This line should be removed.
Related
I'm trying to make a little game that will first show the player a simple login screen where they can enter their name (I will need it later to store their game state info), let them pick a difficulty level etc, and will only show the main game screen once the player has clicked the play button. I'd also like to allow the player to navigate to a (hopefully for them rather large) trophy collection, likewise in what will appear to them to be a new screen.
So far I have a main game window with a grid layout and a game in it that works (Yay for me!). Now I want to add the above functionality.
How do I go about doing this? I don't think I want to go the multiple JFrame route as I only want one icon visible in the taskbar at a time (or would setting their visibility to false effect the icon too?) Do I instead make and destroy layouts or panels or something like that?
What are my options? How can I control what content is being displayed? Especially given my newbie skills?
A simple modal dialog such as a JDialog should work well here. The main GUI which will likely be a JFrame can be invisible when the dialog is called, and then set to visible (assuming that the log-on was successful) once the dialog completes. If the dialog is modal, you'll know exactly when the user has closed the dialog as the code will continue right after the line where you call setVisible(true) on the dialog. Note that the GUI held by a JDialog can be every bit as complex and rich as that held by a JFrame.
Another option is to use one GUI/JFrame but swap views (JPanels) in the main GUI via a CardLayout. This could work quite well and is easy to implement. Check out the CardLayout tutorial for more.
Oh, and welcome to stackoverflow.com!
Here is an example of a Login Dialog as #HovercraftFullOfEels suggested.
Username: stackoverflow Password: stackoverflow
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
import javax.swing.*;
public class TestFrame extends JFrame {
private PassWordDialog passDialog;
public TestFrame() {
passDialog = new PassWordDialog(this, true);
passDialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new TestFrame();
frame.getContentPane().setBackground(Color.BLACK);
frame.setTitle("Logged In");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
});
}
}
class PassWordDialog extends JDialog {
private final JLabel jlblUsername = new JLabel("Username");
private final JLabel jlblPassword = new JLabel("Password");
private final JTextField jtfUsername = new JTextField(15);
private final JPasswordField jpfPassword = new JPasswordField();
private final JButton jbtOk = new JButton("Login");
private final JButton jbtCancel = new JButton("Cancel");
private final JLabel jlblStatus = new JLabel(" ");
public PassWordDialog() {
this(null, true);
}
public PassWordDialog(final JFrame parent, boolean modal) {
super(parent, modal);
JPanel p3 = new JPanel(new GridLayout(2, 1));
p3.add(jlblUsername);
p3.add(jlblPassword);
JPanel p4 = new JPanel(new GridLayout(2, 1));
p4.add(jtfUsername);
p4.add(jpfPassword);
JPanel p1 = new JPanel();
p1.add(p3);
p1.add(p4);
JPanel p2 = new JPanel();
p2.add(jbtOk);
p2.add(jbtCancel);
JPanel p5 = new JPanel(new BorderLayout());
p5.add(p2, BorderLayout.CENTER);
p5.add(jlblStatus, BorderLayout.NORTH);
jlblStatus.setForeground(Color.RED);
jlblStatus.setHorizontalAlignment(SwingConstants.CENTER);
setLayout(new BorderLayout());
add(p1, BorderLayout.CENTER);
add(p5, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
jbtOk.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (Arrays.equals("stackoverflow".toCharArray(), jpfPassword.getPassword())
&& "stackoverflow".equals(jtfUsername.getText())) {
parent.setVisible(true);
setVisible(false);
} else {
jlblStatus.setText("Invalid username or password");
}
}
});
jbtCancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
parent.dispose();
System.exit(0);
}
});
}
}
I suggest you insert the following code:
JFrame f = new JFrame();
JTextField text = new JTextField(15); //the 15 sets the size of the text field
JPanel p = new JPanel();
JButton b = new JButton("Login");
f.add(p); //so you can add more stuff to the JFrame
f.setSize(250,150);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Insert that when you want to add the stuff in. Next we will add all the stuff to the JPanel:
p.add(text);
p.add(b);
Now we add the ActionListeners to make the JButtons to work:
b.addActionListener(this);
public void actionPerforemed(ActionEvent e)
{
//Get the text of the JTextField
String TEXT = text.getText();
}
Don't forget to import the following if you haven't already:
import java.awt.event*;
import java.awt.*; //Just in case we need it
import java.x.swing.*;
I hope everything i said makes sense, because sometimes i don't (especially when I'm talking coding/Java) All the importing (if you didn't know) goes at the top of your code.
Instead of adding the game directly to JFrame, you can add your content to JPanel (let's call it GamePanel) and add this panel to the frame. Do the same thing for login screen: add all content to JPanel (LoginPanel) and add it to frame. When your game will start, you should do the following:
Add LoginPanel to frame
Get user input and load it's details
Add GamePanel and destroy LoginPanel (since it will be quite fast to re-create new one, so you don't need to keep it memory).
Ok so I have 2 jPanels.
one of them has a number of buttons that when pressed should add text to the the textfield that is in the second jPanel.
I am brand spanking new to swing with previously only having to write back end code and web based code so I am having difficulty seeing how you would accomplish this.
I only have buttons created in one panel and a textfield in another so i suspect code would be irrelevant.
Any articles that someone could point me to or examples are greatly appreciated.
So I had this problem ones,
So Lets say you have two JFrame JFrame1 and JFrame2
In order to communicate with each other at runtime both has to have most recent initialized object of each individual frame.
Now lets say this is your first frame where is your textbox,
public class JFrame1 extends JFrame{
JTextField jTextField= null;
public JFrame1() throws HeadlessException {
super("JFrame");
setSize(200, 200);
jTextField = new JTextField();
add(jTextField);
setVisible(true);
}
public void setValueToText(String value){
jTextField.setText(value);
}
}
Then This is second and where is your Button,
public class JFrame2 extends JFrame{
JButton jButton= null;
JFrame1 frame1=null;
public JFrame2() throws HeadlessException {
super("JFrame");
frame1=new JFrame1();
jButton = new JButton("Clieck Me");
add(jButton);
setVisible(true);
jButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
frame1.setValueToText("Hi");
}
});
setVisible(true);
}
public static void main(String[] args) {
JFrame2 jf= new JFrame2();
jf.setSize(200, 200);
}
}
Now Just run second class file and click one button which will set hi on your textbox which is in second frame.
So As you see answer lay's in Initialized second object in frame.
My execution is like,
Run JFrame2
Initialized JFrame1 in JFame2 const.
you can make the JTextField an instance variable of the enclosing JFrame and make the two panels inner classes of it. By this, the two panels will have a reference to the same field which belongs to the outer class.
So, you will end up having something similar to:
public class Outer extends JFrame{
private JTextField text = new JTextField();
...
public Outer(){
this.add(new Inner1(), BorderLayout.NORTH);
this.add(new Inner2(), BorderLayout.SOUTH);
}
class Inner1 extends JPanel{
...
public Inner1(){
this.add(text);
}
}
class Inner2 extends JPanel implements ActionListener{
private JButton button = new JButton();
public Inner2(){
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e){
if (e.getSource() == button)
text.setText("Hello StackOverFlow");
}
}
}
add your code to change the text in another panel, when a button clicked in the first panel.
mybutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//do your logic to change the text in another panel
}
});
I'm trying to make button show a message when pressed, it's not working. Can anyone tell me what I missed?
In the end I have the KeyListener and the if for JOptionPane, but the website is not letting me post it (I'm new to this).
Anyway, it would be really nice if someone could tell me what I'm doing wrong, thanks.
public javalearning(){
FlowLayout f = new FlowLayout();
setLayout(f);
this.setSize(200,200);
JFrame j = new JFrame();
this.setTitle("this is a tittle");
JButton button = new JButton();
button.setText("Button");
this.add(button);
JButton button2 = new JButton();
button2.setText("Button2");
this.add(button2);
this.setVisible(true);
}
please follow example in this code and you will be fine. If at the end of the day you are unable to resolve it. you can write back. i believe this will help you.
import javax.swing.*;
import java.awt.event.*;
public class ChangeButtonLabel{
JButton button;
public static void main(String[] args){
ChangeButtonLabel cl = new ChangeButtonLabel();
}
public ChangeButtonLabel(){
JFrame frame = new JFrame("This is a Frame");
button = new JButton("Button");
button.addActionListener(new MyAction());
frame.add(button);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class MyAction implements ActionListener{
public void actionPerformed(ActionEvent e){
String text = (String)e.getActionCommand();
if (text.equals("Button2")){
button.setText("I am Sectona");
}
else{
button.setText("Click Me");
}
}
}
}
You state:
In the end I have the KeyListener and the if for JOptionPane,
As the tutorial that I've linked to in my comment will explain, you don't use KeyListeners with JButtons but rather ActionListeners.
e.g.,
myButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
System.out.println("Button pressed");
}
});
You state:
but the website is not letting me post it (I'm new to this).
This site will let you post any reasonable amount of code. If you're having problems posting it, tell us the specifics of what's wrong, and maybe we can help you. Again, if you're trying to post code as an image, don't. It should be text that is formatted as code, not an image. But most important, don't keep us in the dark, or we can't help you.
like Hovercraft said, you will need to set ImagIcon(String image_name)
The code below will help you in embedding image on JButton. Give me a shout if you still find it difficult to integrate
import javax.swing.*;
import java.awt.*;
public class IconButton{
public static void main(String[] args){
JFrame frame = new JFrame("Icon on button");
JButton button = new JButton("Image button fro Sectona");
Icon imgicon = new ImageIcon("sectona.gif");
JPanel panel = new JPanel();
button.setIcon(imgicon);
panel.add(button);
frame.add(panel, BorderLayout.NORTH);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I am new to java and am getting to the advanced level of it, i have a problem in the GUI Controls, i made a button that when clicked opens up a new window like this:
JButton b = new JButton("Open New Window");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Window w = new Window();
w.setVisible(true);
}
});
this window contains other objects but i have been thinking of making the button in such a way that instead of opening a new JFrame, it opens everything in that same window without opening a new window, honestly i dont know how to do so please could i get some professional help
I think you want a card layout for this situation. Here is some code which should point you in the right direction.
class MyFrame extends JFrame {
public MyFrame() {
JComponent allMyStuff = new JComponent();
JComponent allMyOtherStuff = new JComponent();
this.getContentPane().setLayout(new CardLayout());
this.getContentPane().add(allMyStuff, "1");
this.getContentPane().add(allMyOtherStuff, "2");
CardLayout cl = (CardLayout) (this.getContentPane().getLayout());
cl.show(this.getContentPane(), "1");
JButton b = new JButton("Open New Window"); //add somewhere to first compoonent
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout) (this.getContentPane().getLayout());
cl.show(this.getContentPane(), "2");
}
});
}
}
I doubt the code runs but generally it holds the idea. You have stuff in one panel, and stuff in another panel, and you just want to switch between the two. The button of course needs to be added in the first panel (allMyStuff) somewhere.
I"m not clear on what it is exactly that you want to show in the GUI when the button is pressed, but perhaps you should consider creating different JPanel "views" and swap these views in the GUI using a CardLayout.
For example, check out these StackOverflow questions and answers:
Java CardLayout Main Menu Problem
Change size of JPanel using CardLayout
Java CardLayout JPanel moves up, when second JPanel added
Java swing; How to toggle panel's visibility?
Clear components of JFrame and add new componets on the same JFrame
gui multiple frames switch
JLabel displaying countdown, java
Within the action listener that you have introduced, you have the possibility to access to instance variables. Therefore you can add further elements to your GUI if you want. I've done a small demo, maybe this is kind of, what you want to do. In order to make your GUI better, you should consider of using layout managers.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class GUI {
JFrame frame;
JButton btn;
JButton compToAdd;
public GUI() {
frame = new JFrame("Testwindow");
frame.setSize(500, 500);
frame.setLayout(null);
btn = new JButton("test btn");
btn.setBounds(20, 20, 200, 200);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
compToAdd = new JButton("new Button");
compToAdd.setBounds(20, 220, 200, 200);
frame.add(compToAdd);
frame.repaint();
}
});
frame.add(btn);
frame.setVisible(true);
}
public static void main(String[] args) {
GUI gui = new GUI();
}
}
I'm quite new to programming so I don't know the right way to do things and have been just experimenting a bit. I want to create a runnable where I can move back and forth between different content. The following works when run from inside eclipse, but if I export it as a JAR file, once I've moved forward once and then back again, moving forward won't give me the content anymore, but just the back button.
I tried something like this:
public class TestMain extends JFrame {
static PanelClass panel;
static boolean inUse = false;
public static void main(String[] args) {
panel = new PanelClass();
final TestMain test = new TestMain();
final Container container = test.getContentPane();
container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
test.setSize(500, 500);
final JButton back = new JButton("Back");
back.setAlignmentX(Component.CENTER_ALIGNMENT);
back.setMaximumSize(new Dimension(200, 80));
back.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
test.getContentPane().removeAll();
test.setContentPane(container);
test.getContentPane().revalidate();
}
});
final JButton exit = new JButton("Exit");
exit.setAlignmentX(Component.CENTER_ALIGNMENT);
exit.setMaximumSize(new Dimension(200, 80));
exit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
JButton problem = new JButton("Problem");
problem.setMaximumSize(new Dimension(200, 80));
problem.setAlignmentX(Component.CENTER_ALIGNMENT);
problem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
inUse = true;
test.setContentPane(panel);
test.getContentPane().add(back);
test.getContentPane().revalidate();
}
});
container.add(problem);
container.add(exit);
test.setVisible(true);
test.setDefaultCloseOperation(EXIT_ON_CLOSE);
test.setLocationRelativeTo(null);
while (true) {
while (!panel.stop && !inUse) {
}
inUse = false;
panel = new PanelClass();
test.setContentPane(panel);
test.getContentPane().add(back);
test.getContentPane().revalidate();
}
}
}
And the class for what I want to have as the second content:
public class PanelClass extends JPanel {
JTextArea text = new JTextArea("Some text here!" + '\n' + '\n');
JButton button1 = new JButton("Button 1");
JButton button2 = new JButton("Button 2");
boolean stop = false;
public PanelClass() {
text.setEditable(false);
text.setMaximumSize(new Dimension(300, 300));
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
Dimension d = new Dimension(200, 60);
button1.setAlignmentX(Component.CENTER_ALIGNMENT);
button1.setMaximumSize(d);
button2.setAlignmentX(Component.CENTER_ALIGNMENT);
button2.setMaximumSize(d);
this.add(text);
this.add(button1);
this.add(button2);
}
}
What is the actual working way to do this? What if I have a lot of windows I'd like to be able to move back and forth between? I know it's a lot of bad/possibly-hard-to-read code, but I hope someone could help me out.
This is the code that runs when you press "Problem":
test.setContentPane(panel);
test.getContentPane().add(back);
test.getContentPane().revalidate();
and this is the code that runs when you press "Back":
test.getContentPane().removeAll();
test.setContentPane(container);
test.getContentPane().revalidate();
What is the sequence of calls when you press "Problem" then "Back" then "Problem"? It's this. (The revalidate() calls won't mess anything up, so I won't show them)
// Problem
test.setContentPane(panel);
test.getContentPane().add(back);
// Back
test.getContentPane().removeAll();
test.setContentPane(container);
// Problem
test.setContentPane(panel);
test.getContentPane().add(back);
Notice that you set the panel as the content pane, and then remove all the components from it when "Back" is pressed. The next time you press "Problem", the panel has no components on it, because you removed them.
did you try exporting as a runnable jar and choose package required libraries into generated jar when you exported as JAR from eclipse?