How can I prevent my JFrame Window from multiplying? - java

For the sake of everyone understanding my problem, I've created a simple GUI program which shows my problem. I'll first put the codes for you to analyze. And then, please watch the video below to see what I've been meaning to ask. Please bear with me, the video is just a few seconds and will not take time to load.
Menu JFrame:
//This is a Menu JFrame Window
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Menu extends JFrame implements GlobalVariables{
public Menu(){
clickMe.setBounds(75, 50, 100, 50);
clickMe.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
dispose();
SubMenu sm = new SubMenu();
sm.subMenuProperties();
}
});
add(clickMe);
}
void menuProperties(){
setLayout(null);
setSize(250,175);
setVisible(true);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
Menu m = new Menu();
m.menuProperties();
}
}
SubMenu JFrame:
//This is a SubMenu JFrame Window
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class SubMenu extends JFrame implements GlobalVariables{
public SubMenu(){
clickMe2.setBounds(75, 50, 100, 50);
clickMe2.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
dispose();
Menu m = new Menu();
m.menuProperties();
}
});
add(clickMe2);
}
void subMenuProperties(){
setLayout(null);
setSize(250,175);
setVisible(true);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SubMenu sm = new SubMenu();
sm.subMenuProperties();
}
}
And if your're wondering what's the "GlobalVariables" implementation, here it is:
import javax.swing.*;
public interface GlobalVariables{
//Menu Variable
JButton clickMe = new JButton("SubMenu");
//SubMenu Variable
JButton clickMe2 = new JButton("Back");
}
Now, this video will show you what I mean in JFrame being multiplied:
http://www.youtube.com/watch?v=iCavg_1SqvY
*If you watched the video, you can see what I mean when I say the JFrame is being multiplied. I've been analyzing this for days but I cannot identify my mistake. If you can just pinpoint my mistake, I'll be more than thankful. I'm also open for comments and adjustments in the code, I just wish that the structure of the code will not be re-structured because as I've said earlier, I've created this simple GUI just to show you my problem but to tell you at least, I have a whole program waiting to be finished using this kind of approach in GUI making. Please help me.

Those two classes are both a subclass of JFrame which results in a new window.
The one named Menu contains a button "clickMe" which instantiates SubMenu that contains a button "clickMe2" that instantiates Menu. This creates a endless loop creating more instances of each class. I.e creating more frames.
In the class SubMenu, remove these lines:
Menu m = new Menu();
m.menuProperties();
To get started using swing, Oracle has great tutorials.

I found the issue with the code. You need to remove the ActionListener in you actionPerformed method. For each button click, your code creates a new ActionListener object and it gets associated with your button. Subsequent clicks gets executed by this duplicate action listeners and you end up getting more JFrames.
Add the below line to actionPerformed(ActionEvent e) method of both classes after the line dispose(). This should fix your problem
Menu.java
clickMe.removeActionListener(this);
......
SubMenu.java
clickMe2.removeActionListener(this)
;

Related

Adding a action listener in java for a counter

I am a fairly new user with programming in Java with about a week and a bit experience, as of before I have been using python for about 3 years but thought to give java a try.
I have been trying to develop my skills by creating small projects and applications and am now creating a small GUI counter.
I have achieved creating the GUI with 2 buttons and a label and have tested the maths behind the application but I am struggling to work out how the ActionListener works as it feels a lot different to python when making a button have a action.
This is My Code;
package gui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.*;
public class GUI{
//This creates a frame or panel to contain things
public static void main(String[] args) {
//Maths To The Counter
int Counter = 0;
System.out.println(Counter);
Counter =+ 1;
System.out.println(Counter);
//Creating The Frame
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
frame.getContentPane().add(panel);
//Creating The Label
JLabel label3 = new JLabel("Counter: ");
panel.add(label3);
//Button Which should have a funtion to add and display the number
JButton button = new JButton("Click Here.");
panel.add(button);
//Button to reset the counter
JButton buttonReset = new JButton("Reset Counter.");
panel.add(buttonReset);
//Set Size Of Window
frame.setSize(new Dimension(500, 400));
//Set Starting Position to centre
frame.setLocationRelativeTo(null);
//Setting a default close action
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set Title
frame.setTitle("Counter");
//Disable Resize
frame.setResizable(false);
//Setting if its visible
frame.setVisible(true);
//Fits frame to fit everything
frame.pack();
}
}
enter code here
I know that in python a action is in a function so that has been my logic to this problem however I have seen that I need to use the actionlistener instead and I am struggling to get my head around it.
If Someone could show me how this type of action should be implemented it would be great help, I have watch some youtube videos and done a bit of research but im still struggling to understand in my situation how to do it.
For any confussion im sorry, overall my question is how do I add a action to a button in my program that can implement my maths at the start.
As well any feedback on the structure of my code would be welcomed as I am just starting in java and I do know poor structure can lead to mistakes.
This code should work:
Basically, in the main method I am creating an instance of the class and calling a method to create the gui.
I also created an instance variable as the counter, otherwise you won't be able to update the variable in your action listener.
public class Gui {
private int counter;
// This creates a frame or panel to contain things
public static void main(String[] args) {
Gui gui = new Gui();
gui.create();
}
private void create() {
// Creating The Frame
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
frame.getContentPane().add(panel);
// Creating The Label
JLabel label3 = new JLabel("Counter: ");
panel.add(label3);
// Button Which should have a funtion to add and display the number
JButton button = new JButton("Click Here.");
panel.add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(counter++);
}
});
// Button to reset the counter
JButton buttonReset = new JButton("Reset Counter.");
panel.add(buttonReset);
buttonReset.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
counter = 0;
}
});
// Set Size Of Window
frame.setSize(new Dimension(500, 400));
// Set Starting Position to centre
frame.setLocationRelativeTo(null);
// Setting a default close action
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Set Title
frame.setTitle("Counter");
// Disable Resize
frame.setResizable(false);
// Setting if its visible
frame.setVisible(true);
// Fits frame to fit everything
}
}
With Lambda expressions, you can simplify your action listeners as follows:
button.addActionListener(a -> System.out.println(counter++));
buttonReset.addActionListener(a -> counter = 0);
If you want to write more than 1 statement, then you can just put your code in curly brackets:
button.addActionListener(a -> {
System.out.println(counter++);
System.out.println("doing more stuff...");
});
JButton has a function called addActionListener. You can pass on an action listener by doing this:
button.addActionListener(() -> {
// Do some logic here
});
Here, I use a lambda expression as an action listener. Within the lambda expression you can place whatever logic you want to have.
Also note that you can add multiple different action listeners to the same button. In a nutshell, the way the JButton interacts with the ActionListeners is based on the observer-pattern.
Imagine this: When the JButton is pressed, it will notify all of it's observers saying "Hey, I have been pressed". Each observer can then independently decide what to do. In case of the JButton, all observers are ActionListeners. If you add multiple ActionListeners then the JButton will notify all of them, and as a result all of their actionPerformed(ActionEvent e) functions are executed. In the example above, I used a lambda expression which then by java is interpreted as an ActionListener.
Other ways to achieve the exact same functionality are:
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Do some logic here
}
});
In the example above, you use an anonymous class as an actionlistener.
public class MyClass {
public MyClass() {
JButton button = new JButton("press me");
button.addActionListener(new MyActionListener());
}
private class MyActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// Do some logic here
}
}
}
In the example above, an inner class is used.
In a nutshell, there is a ton of ways you can make your button have functionality. Above are just a few examples of how to do so.
Does this clarify it a bit more, or do you have some remaining questions?

Why is there a visual difference on the button when the mouse is moving vs not moving?

I am trying to figure out a interesting visual incongruity with awt buttons.
The below code will open a window with a button. If you click on that button rapidly without moving your mouse you will see the button presses and depresses slower than your clicks. However if you move your mouse around while rapidly clicking on the button it will press and depress as quick as you click.
I cant seam to find anything about this visual difference online. Mostly just post saying "don't use awt and use swift instead". I am not interesting in what the "better" GUI library is but rather what is causing this visual difference.
Can someone explain to me why the button appears to behave differently when them mouse is not moving verses when it is moving?
import java.awt.*;
import java.awt.event.*;
public class TestApp extends Frame implements WindowListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private Button btn1;
public TestApp () {
setLayout(new FlowLayout());
btn1 = new Button("Click ME!");
add(btn1);
setSize(80, 80);
setVisible(true);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
}
public static void main(String[] args) {
new TestApp();
}
}

trying to use a frame in another frame but from two different classes [duplicate]

I have two JFrame.
public class Main extends JFrame
public class ColourOption extends JPanel implements ActionListener which is then set up in a JFrame.
I wanted to open the second JFrame when i click on button of first JFrame
.setVisible() is not working. I also tried revalidate(), as well as invalidate() , validate() in the second JFrame.
What could be the reason for it to not work?
You will have to instantiate the 2nd class which has the 2nd Frame(to be shown)..and then if you call the setVisible(true) .. then it must show .. what you doing .. could you provide your button's event handler..
and this is not good practice
so personally i would recommend you to switch over to better alternatives like JTABBEDPANES or CARDLAYOUT
and consider the comments as well .. good comments guys :) .. especially using JDialog for this context :)
well if you still want help in your context: a sample:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class JFrame1 extends JFrame
{
public JFrame1()
{
setLayout(new FlowLayout());
JButton b=new JButton("Click");
add(b);
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
JFrame jf = new JFrame2();
jf.setVisible(true);
jf.setSize(200, 200);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
);
}
public static void main(String args[])
{
JFrame jf = new JFrame1();
jf.setVisible(true);
jf.setSize(200, 200);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
and the second class:
import javax.swing.*;
import java.awt.*;
class JFrame2 extends JFrame
{
public JFrame2()
{
setLayout(new FlowLayout());
add(new JLabel("2nd Frame"));
}
}
But again i would still recommend to switch to other methods as i mentioned earlier: tabbedpanes, cardlayout etc..
Hope i helped :)
Since they are from 2 different classes, you just have to define/instantiate an object of the other class... and if within that 2nd class (ColourOption) it already contains setVisible(true) then there must be no problem loading the window.
//this will be placed on your constructor
yourButton.addActionListener(new ButtonListener());
//listener class
class ButtonListener implements ActionListener{
public void actionPerformed(ActionEvent ae){
if(ae.getSource() == yourButton){
new ColourOption();
}
}
}

AS3 - Button Click + Number

What I'm trying to do is create a very basic button click game much like "AdVenture Capitalist" and several other casual games like it. Nothing quite as fancy. I'm using FlashDevelop (AS3) and I'm trying to figure out how to create a button then every time that button is pressed it adds +1 to my main value represented on screen.
I'd also like to figure out how to make a button that would automate the clicking process.
If anyone could show me how, or direct me to a specific page that would help me out I would be very thankful.
I'm also not sure if Actionscript is the best language to write this in. If you have a recommendation that I can use FlashDevelop with I would appreciate the tip!
Thank you!
I have idea about the how this operation will be performed in java. For example creating buttons and labels. As long as you need to combine java and flash this link is useful for starters. If you need only java the following snippet will be useful. Also learn java swing from JavaDocs for GUI purpose
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonClick
{
int counter = 0;
public ButtonClick()
{
JFrame frame = new JFrame("Title");
JButton btn = new JButton("Click me");
JLabel clicks = new JLabel("");
frame.setSize(400,400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
counter++;
clicks.setText("Number of clicks till now :"+Integer.toString(counter));
frame.repaint();
}
});
frame.add(btn);
frame.add(clicks);
frame.setVisible(true);
}
public static void main(String []args)
{
ButtonClick c = new ButtonClick();
}
}

Why does using ActionListener break my Swing Applet?

I have an application working in Java Swing, but can't seem to convert to an Applet. Basically there are four buttons displayed on the Applet, and I want one of them to clear the screen and then draw a new interface (I'm going to add stuff for the other buttons, of course, but I got stuck here).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.JApplet; //import swing applet interface
import java.util.Hashtable;
public class TopMenu extends JApplet{
private JPanel panel = new JPanel();
public void init(){
mainMenu();
}
public void mainMenu() {
// create buttons
panel.setLayout(new GridLayout(2, 2));
JButton collectButton = new JButton("Collect data");
JButton uploadButton = new JButton("Upload");
JButton downloadButton = new JButton("Download");
JButton exploreButton = new JButton("Explore data");
panel.add(collectButton);
panel.add(uploadButton);
panel.add(downloadButton);
panel.add(exploreButton);
collectButton.addActionListener(new ActionListener( ) {
public void actionPerformed(ActionEvent e) {
int numberGFish = 400;
//panel.removeAll();
//panel.add(new JLabel("Just to test"), BorderLayout.CENTER);
//panel.revalidate();
//panel.repaint();
}
});
setContentPane(panel);
}
}
All the code works totally fine until I add the ActionListener, and then the whole thing just goes blank. It compiles okay, but when I test it on my server not even the first menu comes up, it's just a blank panel. I've tried putting loads of really banal things in the ActionListener bit to make sure it's not a problem with them, but as you can see even just declaring a number in there doesn't work.
Originally I actually had the Listener bit call on another method which then did everything else, and that didn't work either, I scrapped that because I thought perhaps that was the problem.
I'm sure this is so simple but I've sunk many hours into it now and I've really just run out of ideas of things to test. And advice gratefully appreciated.
Don't know if it would be a problem or not but all GUI components should be created on the Event Dispatch Thread.
Here is the recommended code structure from the Swing tutorial on How to Make Applets:
public void init() {
//Execute a job on the event-dispatching thread:
//creating this applet's GUI.
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createGUI();
}
});
} catch (Exception e) {
System.err.println("createGUI didn't successfully complete");
}
}
private void createGUI() {
JLabel label = new JLabel(
"You are successfully running a Swing applet!");
label.setHorizontalAlignment(JLabel.CENTER);
label.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.black));
add(label, BorderLayout.CENTER);
}
I knew it was a dumb question, but I just couldn't figure it out. I've sorted it now.
I was being totally daft and not copying across the TopMenu$1.class file to the server. For some reason it works without this file but not with the ActionListener bit added. So I never thought that could be the problem.
Doh! Thanks all.

Categories