Jlabel not updating when setText is called - java

While building a simple currency converter app setText is not setting the value in JLabel.(I am using eclipse ide in windows).I have called Action Listener for setting button and also had converted the getText to int with the help of parseInt.
My code is given below.
import java.awt.Color;
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.JTextField;
public class CurrencyConverter implements ActionListener {
JButton button1,button2;
JLabel display2,display3;
JTextField display;
public CurrencyConverter() {
var frame=new JFrame();
frame.setLayout(null);
frame.setBounds(300, 300, 400, 300);
frame.getContentPane().setBackground(Color.BLACK);
display=new JTextField();
display.setBounds(50, 30, 300, 50);
display.setBackground(Color.yellow);
display.setForeground(Color.black);
frame.add(display);
button1=new JButton("TO INR");
button1.setBounds(50, 100, 135, 50);
frame.add(button1);
button2=new JButton("TO USD");
button2.setBounds(215, 100, 135, 50);
frame.add(button2);
display2=new JLabel();
display2.setBounds(50, 170, 300, 50);
display2.setBackground(Color.GREEN);
display2.setForeground(Color.BLACK);
display2.setOpaque(true);
frame.add(display2);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new CurrencyConverter();
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==button1) {
int noInDisplay=Integer.parseInt(display.getText())*70;
display2.setText(""+noInDisplay);
}
else if(e.getSource()==button2) {
int noInDisplay=Integer.parseInt(display.getText())/70;
display2.setText(""+noInDisplay);
}
}
}

The main issue why you are not seeing any visible updates on your JLabel is that the ActionListener is never added on the buttons, hence the actionPerformed() is never called.
To fix this, you should add these two lines in the CurrencyConverter() constructor, to add the ActionListener on your buttons:
button1.addActionListener(this);
button2.addActionListener(this);
Some sidenotes on your code:
It is generally not recommended to use null layout in swing. Have a look at the Visual Guide to Layout Managers for an overview on swing layout managers. Using a layout manager will do the work of sizing and laying out the components for you. So you don't have to manually set the size and bounds for each component yourself.
Instead of checking for the source of the action in actionPerformed() you could implement an anonymous ActionListener for each JButton. This way, you have a clear mapping between component and action. E.g.
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int noInDisplay = Integer.parseInt(display.getText()) * 70;
display2.setText("" + noInDisplay);
}
});
Some kind of input validation should be considered in the next step.

Related

I am trying to create a GUI that will open a new label with different color whenever the next button is clicked

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Welcome
{
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setBounds(100, 100, 700, 500);
frame.setVisible(true);
JButton btn = new JButton("next");
btn.setBounds(100, 100, 100, 100);
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
JLabel label3 = new JLabel();
//first label
label1.setBackground(Color.BLACK);
label1.add(btn);
frame.getContentPane().add(label1);
btn.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
frame.getContentPane().remove(label1);
frame.getContentPane().repaint();
frame.getContentPane().revalidate();
frame.getContentPane().add(label2);
}
});
//second
JLabel label2.setBackground(Color.RED);
JButton btn2 = new JButton("next");
btn2.setBounds(100, 100, 100, 100);
label2.add(btn2);
btn2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.getContentPane().remove(label1);
frame.getContentPane().repaint();
frame.getContentPane().revalidate();
frame.getContentPane().add(label3);
}
});
//third JLabel
label3.setBackground(Color.BLUE);
}
}
Don't use setBounds().Swing was designed to be used with layout managers.
Changing the background of a label doesn't do anything. By default a JLabel is transparent so the background is not painted. To see the background you first need to use label.setOpaque(true);
Don't use remove/add logic. To swap a component in the same position in the frame use a CardLayout. Read the section from the Swing tutorial on How to Use CardLayout.
Start with the working code and then make changes. The code in the tutorial is better structured than your current code and demonstrates how to use the Event Dispatch Thread (EDT). All Swing components should be created and modified on the EDT.

When I click my JButton, the JLabel doesn't show on the window,

I tried to make a JButton that would put a JLabel in the window, but when I click the button, it doesn't seem to put the JLabel in the window. The button seems to work when I use it for the console, but not for putting the JLabel in the window. Why is this, and what should I do?
Here's my code:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class AnimaleseTranslator implements ActionListener {
private static JPanel panel;
private static JLabel label;
public AnimaleseTranslator() {
JFrame frame = new JFrame();
panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(220, 391, 220, 391));
panel.setLayout(new GridLayout(0, 1));
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null); // centers the JFrame
frame.setTitle("Animalese Translator");
frame.setVisible(true);
JButton button = new JButton("Click me!");
button.setBounds(100, 100, 98, 55);
button.addActionListener(this);
panel.add(button);
label = new JLabel("lkdsajflksdjlaskdjf");
label.setBounds(200, 200, 50, 50);
}
public static void main(String[] args) {
new AnimaleseTranslator();
}
#Override
public void actionPerformed(ActionEvent e) {
panel.add(label);
}
}
but when I click the button, it doesn't seem to put the JLabel in the window.
The setBounds(...) statement does nothing. Swing uses layout managers by default and the layout manager will set the size/location of each component. So get rid of the setBounds() statement because it is confusing.
Components need to be added to the frame BEFORE the frame is made visible. The pack() or setVisible() statement will then invoke the layout manager.
After you add a component to panel on a visible frame you need to invoke panel.revalidate() to invoke the layout manager. So you need to add the revalidate() in the ActionListener.
Get rid of the setBorder(...) statement until you better understand what it does. The problem with your current code is the border is too big, so there is no room for the button and label to display properly.

How to leave MouseListener on ChildComponent but correctly keep track of mouse enter and exit on parent?

I have a JPanel with a CardLayout and two cards. I want the layout to flip the cards each time the mouse enters or exits the panel.
This works fine unless one of the cards is a component that listens for mouse events. Consider the following example:
JPanel cardLayoutPanel = new JPanel(layout);
JButton button = new JButton("listening!");
JLabel label = new JLabel("not listening.");
cardLayoutPanel.add(button);
cardLayoutPanel.add(label);
layout.last(cardLayoutPanel);
cardLayoutPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("entered!");
layout.next(cardLayoutPanel);
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("exited!");
layout.next(cardLayoutPanel);
}
});
The problem is that, if the MouseEvent is catched by a child component, it is not processed by the parent as a read in many SO-questions related to this topic.
I tried different things like redispatching the event or just ignoring the exit event if the event if the event coordinates are still in the panel.
The first solution does not work at all, the second neither since then the mouse entered event does not occur anymore.
How can i solve this?
The only solution that I see right now would be to completely remove the listener from the child component and perform the collision and event handling on my own in the parents mouse mouse listener, but this would be a mess and not the intended way to do this, i guess.
Any help or ideas appreciated.
EDIT: here is a complete short compilable example:
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class CardLayoutTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel content = new JPanel();
content.setBorder(new EmptyBorder(new Insets(50, 50, 50, 50)));
CardLayout layout = new CardLayout();
JPanel cardLayoutPanel = new JPanel(layout);
JButton button = new JButton("listening!");
JLabel label = new JLabel("not listening.");
cardLayoutPanel.add(button);
cardLayoutPanel.add(label);
layout.last(cardLayoutPanel);
cardLayoutPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("entered!");
layout.next(cardLayoutPanel);
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("exited!");
layout.next(cardLayoutPanel);
}
});
content.add(cardLayoutPanel);
frame.add(content);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
I modified your example slightly and got it to work. The key (at least in this example), was to have the button share the same mouseListener with the cardLayoutPanel. I do not know if this is a universal solution but it does work here. I also made the following changes:
added a private innner class for the mouseListener.
Increased the size of the cardLayoutPanel.
Added color borders to the Label and Button.
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class CardLayoutTest {
JButton button = new JButton("listening!");
JPanel cardLayoutPanel = new JPanel();
CardLayout layout = new CardLayout();
public static void main(String[] args) {
new CardLayoutTest().start();
}
public void start() {
JFrame frame = new JFrame();
JPanel content = new JPanel();
content.setBorder(new EmptyBorder(
new Insets(50, 50, 50, 50)));
cardLayoutPanel.setLayout(layout);
cardLayoutPanel
.setPreferredSize(new Dimension(200, 200));
button.addActionListener(
ae -> System.out.println("IT WORKS!"));
button.removeMouseMotionListener(
button.getMouseMotionListeners()[0]);
button.removeMouseListener(
button.getMouseListeners()[0]);
MyMouseListener ml = new MyMouseListener();
button.addMouseListener(ml);
button.setBorder(new LineBorder(Color.red, 2));
JLabel label = new JLabel("not listening.");
label.setBorder(new LineBorder(Color.blue, 2));
cardLayoutPanel.add(button);
cardLayoutPanel.add(label);
layout.last(cardLayoutPanel);
cardLayoutPanel.addMouseListener(ml);
content.add(cardLayoutPanel);
frame.add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private class MyMouseListener extends MouseAdapter {
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("entered!");
layout.next(cardLayoutPanel);
}
public void mouseClicked(MouseEvent e) {
if (e.getSource() instanceof JButton) {
JButton b = (JButton)(e.getSource());
b.doClick();
}
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("exited!");
layout.next(cardLayoutPanel);
}
}
}
It is not quiet a good solution but i managed to achieve what i want by calling the flip event when entering the parent component. This works since i have enough space between my panels with this property.
I did not, however, managed to achieve this effect with glass panes as suggested in a comment. Maybe I was doing it wrong, but the events did not arrive at the components properly, even some instanceof checks failed out of nowhere.
If someone knows how to do this properly I would be glad to see.

Java cannot instantiate type ActionListener

im trying to add an ActionListener to my buttons for my calculator Im making. The problem is that Im being presented an error when I try to make an ActionListener. I tried in one class then I created a listener class just to see if that would help. Here is my code:
package main;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public abstract class Main extends JFrame implements Listener{
public static void main(String[] args) throws IOException{
//Main variables
String dis = "0";
double ans = Double.parseDouble(dis);
//Making frames
JFrame frame = new JFrame("Calculator");
JPanel panel = new JPanel();
//Buttons
JButton enter = new JButton("Enter");
JButton sub = new JButton("-");
JButton add = new JButton("+");
JButton div = new JButton("รท");
JButton mult = new JButton("*");
JTextField text = new JTextField(dis);
//Font
Font bigFont = text.getFont().deriveFont(Font.PLAIN, 30f);
Font butf = text.getFont().deriveFont(Font.PLAIN, 20f);
//Methods
panel.setLayout(new FlowLayout());
panel.add(text);
panel.setSize(590, 100);
text.setColumns(22);
text.setFont(bigFont);
text.setHorizontalAlignment(JTextField.RIGHT);
text.setEditable(false);
enter.setForeground(Color.RED);
sub.setForeground(Color.RED);
div.setForeground(Color.RED);
mult.setForeground(Color.RED);
add.setForeground(Color.RED);
//Buttons Methods
enter.setBounds(470, 450, 100, 150);
sub.setBounds(470, 350, 100, 90);
div.setBounds(470, 250, 100, 90);
mult.setBounds(470, 150, 100, 90);
add.setBounds(470, 50, 100, 90);
enter.setFont(butf);
sub.setFont(butf);
div.setFont(butf);
mult.setFont(butf);
add.setFont(butf);
//Frame
frame.add(div);
frame.add(mult);
frame.add(sub);
frame.add(enter);
frame.add(add);
frame.add(panel);
frame.setSize(600, 650);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//extra
text.setSize(1000, 100);
//Actions
}
}
package main;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
public interface Listener extends ActionListener {
//Throwing error here 'Cant instantiate the type ActionListener'
ActionListener al = new ActionListener();
public default void actionPerformed(ActionEvent e){
}
}
Anyone know how to fix this error?
To declare an ActionListener use
public class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//dostuff
}
}
ActionListener is a interface, it can't be instantiated, without provide a concrete implementation of it's contract
interfaces can't contain instance fields
Simply speaking, it should look more like...
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public interface Listener extends ActionListener {
public default void actionPerformed(ActionEvent e) {
}
}
You may also like to have a closer look at
How to Write an Action Listeners
What Is an Interface?
The Interfaces trail
In Swing, you should make sure that your UI is only created and manipulated from within the context of the Event Dispatching Thread. Have a look at Initial Threads for more details
You're also going to be very disappointed with the results of your layout, have a look at Laying Out Components Within a Container for better solutions

How do I add JButtons and JLabels without conflicts?

When I try to add a JButton and a JLabel into a JFrame, they both conflict each other in which all the JButtons would disappear and only the JLabel would be visible. The JLabel for some reason would go to the left most side of the JFrame instead of the desired location I set it to go. I'm new to GUI related material and I'm willing to learn from these mistakes.
Here is my code:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Windowb extends JFrame{
static String title = "This is a JFrame";
static int width = 500;
static int height = 400;
private static final int BUTTON_LOCATION_X = 46;
private static final int BUTTON_LOCATION_Y = 80;
public static void main(String[]args){
Windowb simple = new Windowb(title, width, height);
JPanel p = new JPanel();
p.setLayout(null);
JLabel c1 = new JLabel("Name: ");
JButton b1 = new JButton("Name:");
JButton b2 = new JButton("Grade:");
JButton b3 = new JButton("GPA");
b1.setBounds(BUTTON_LOCATION_X, BUTTON_LOCATION_Y, 90, 20);
b2.setBounds(50, 170, 90, 20);
b3.setBounds(50, 240, 90, 20);
c1.setLocation(100, 250);
b1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
JOptionPane.showMessageDialog(null, "ActionListener is working!");
}
});
b2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
JOptionPane.showMessageDialog(null, "The second one works too!");
}
});
b3.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
JOptionPane.showMessageDialog(null, "Surprise!");
}
});
p.add(b1);
p.add(b2);
p.add(b3);
simple.add(p);
simple.add(c1);
}
public Windowb(String t, int w, int h){
setVisible(true);
setResizable(true);
setSize(w, h);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocation(500, 100);
setTitle(t);
}
}
You probably should use a LayoutManager. See the layout manager tutorial: http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
setBounds() is used by the layout manager to position components. You can set the LayoutManager to null and position the components yourself but stuff like window resizing isn't handled for you that way (ie. components and space aren't scaled accordingly). If you want to maintain your sanity then don't use the build in GridBag layout! It will drive you insane! For more complex layouts use http://www.miglayout.com/ or http://www.jgoodies.com/freeware/libraries/forms/ . For simple layouts use layoutmanagers like BorderLayout.
If you really don't want to use a layoutmanager then use a JPanel. A JFrame can only hold a single component so thats your problem. Put a JPanel inside the JFrame and put your components in the JPanel.

Categories