Java changing the text of JLabel inside another method - java

I want to change the text of a JLabel outside of the method I created it in.
I've looked through the other pages on the same topic but I still cannot get it to work. Perhaps I am lacking knowledge of Java to solve this by myself.
Would you please help me?
package autumn;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main {
private JFrame frame;
JLabel TestLabel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main window = new Main();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Main() {
initialize();
setText();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JLabel TestLabel = new JLabel("");
TestLabel.setBounds(0, 0, 46, 14);
frame.getContentPane().add(TestLabel);
}
void setText() {
TestLabel.setText("Works!");
}
}

You have a class field JLabel TestLabel.
But in the initializemethod you shadow this field by using a local variable with the same name:
JLabel TestLabel = new JLabel("");
so the class field is not initialized and the later call to setText fails.
Therefore simply write:
TestLabel = new JLabel(""); // assigns to Main.TestLabel

Related

Importing button and text field from another class to main class

I have two different classes (mainClass) and (visual). In the visual class I have a method and inside the method I put the required code for a simple JButton. In the main class I create an object to call the method from visual class, to show the button in the main class . But it does not work. I would appreciate any advice.
package init;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
public class mainClass {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
mainClass window = new mainClass();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public mainClass() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
In the code below I made an object and called the method from the visual class
visual bt = new visual();
bt.btn();
}
}
////////////////VISUAL CLASS//////////////////////
package init;
import javax.swing.JButton;
import javax.swing.JFrame;
public class visual {
public JFrame frame;
public void btn() {
JButton btnNewButton = new JButton("New button");
btnNewButton.setBounds(141, 155, 151, 45);
frame.getContentPane().add(btnNewButton);
}
}
For what you are trying to achieve here you don't need 2 classes. You can do it like this:
import javax.swing.*;
import java.awt.*;
public class MainClass {
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JFrame frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnNewButton = new JButton("New button");
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(btnNewButton);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

JLabel variable updated but GUI is not updated

When I run this code which should take the text from a JLabel, use a getter method to move it to the button action class, modifiy it and then use a setter method to set it in the original class, it updates the JLabel variable but does not update the GUI.
I have tried repaint(), revalidate(), doLayout() on the label, the frame and the panel that holds the label.
The class that initializes the label:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.JButton;
public class Testing4 {
private JFrame frame;
private JLabel lblNewLabel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Testing4 window = new Testing4();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Testing4() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
lblNewLabel = new JLabel("label");
lblNewLabel.setBounds(52, 101, 277, 53);
frame.getContentPane().add(lblNewLabel);
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
JButton btnNewButton = new JButton("New button");
btnNewButton.setBounds(114, 28, 156, 53);
frame.getContentPane().add(btnNewButton);
btnNewButton.addActionListener(new ButtonAction());
}
public String getLabelText()
{
return this.lblNewLabel.getText();
}
public void setLabelText(String text)
{
System.out.println(text);
this.lblNewLabel.setText(text);
System.out.println(lblNewLabel.getText());
}
}
If you look at the setLabelText(String) method, it sets the text to the label called lblNewLabel and then it prints out the text to the console in the next line of code. That .getText() shows that the label has been modified, however the GUI does not show that it has been modified.
Here is the code for the button:
public class ButtonAction implements ActionListener
{
Testing4 test;
public void actionPerformed(ActionEvent e)
{
test = new Testing4();
String x = test.getLabelText();
System.out.println(x);
x = x + " hello";
System.out.println(x);
test.setLabelText(x);
}
}
For all intents and purposes, this should update the GUI with the new text, I've done this before and not had an issue but something this time is causing an issue.

Swing JLabel missing characters

So I have come across a peculiar problem.
My interface is just a single label, and a JSlider.
My code(stripped):
import javax.swing.*;
import java.awt.*;
public class Broken {
JLabel value = new JLabel();
JSlider slider = new JSlider(0, 255, 0);
public Broken() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel panel = new JPanel();
value.setText("Some Value");
panel.add(value);
JFrame frame = new JFrame("Frame Name");
frame.setLayout(new GridLayout(2, 1));
frame.add(panel);
frame.add(slider);
frame.pack();
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
new Broken();
}
}
What happens is the label doesn't show up. If I resize the screen from the right to the smallest possible, suddenly the text appears, and it will stay there if I resize back to what it was. I have no idea what's happening, this truly seems like a bug to me.
Before and after resizing screenshots:
Despite your efforts, you're not on the EventDispatchThread when you're creating your JLabel (or JSlider, for that matter). To test, I subclassed JLabel just see if the code was on the EDT when it's constructor is called:
import java.awt.*;
import javax.swing.*;
public class Broken {
JLabel value = new XLabel(); // called before constructor, so not on EDT
JSlider slider = new JSlider(0, 255, 0); // same here
public Broken() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel panel = new JPanel();
value.setText("Some Value");
panel.add(value);
JFrame frame = new JFrame("Frame Name");
frame.setLayout(new GridLayout(2, 1));
frame.add(panel);
frame.add(slider);
frame.pack();
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
new Broken();
}
class XLabel extends JLabel {
public XLabel() {
super();
System.out.println("EDT? " + SwingUtilities.isEventDispatchThread());
}
}
}
To fix, place the invokeLater call in main, so as to wrap the entire construction of your class onto the EDT:
import java.awt.*;
import javax.swing.*;
public class Broken2 {
JLabel value = new JLabel();
JSlider slider = new JSlider(0, 255, 0);
public Broken2() {
JPanel panel = new JPanel();
value.setText("Some Value");
panel.add(value);
JFrame frame = new JFrame("Frame Name2");
frame.setLayout(new GridLayout(2, 1));
frame.add(panel);
frame.add(slider);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Generally the proper way. Create Whole app on EDT
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Broken2();
}
});
}
}

Void is invalid for the variable main?

How do i fix the error, Void is invalid for the variable main? I tried looking this up online but couldn't find anything. Also I am kind of new to this so please take it easy on me. I am learning as I go.
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;
import javax.swing.JTextField;
public class Text extends JFrame
{
JPanel jp = new JPanel();
JLabel jl = new JLabel();
JTextField jt = new JTextField("Month",30);
JTextField jt2 = new JTextField("Date",30);
JButton jb = new JButton("Enter");
public Text()
{
public static void main (String[] args); {
setTitle("Tutorial");
setVisible(true);
setSize(400, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
jp.add(jt);
jp.add(jt2);
jt.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String input = jt.getText();
jl.setText(input);
}
});
jp.add(jb);
jb.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String input = jt.getText();
String input2 = jt2.getText();
jl.setText(input);
jl.setText(input2);
int day = Integer.parseInt(input2);
if ((input.equals("Test")) && (input2.equals(day >= 26)))//||(input2.equals("27")))))
JOptionPane.showMessageDialog(null, "" , "" ,JOptionPane.PLAIN_MESSAGE,aries);
}
});
add(jp);
}
}
}
You have placed your main method inside the constructor for class Text. It belongs outside the constructor, at the same level as the constructor. Move it outside the constructor.
public class Text extends JFrame
{
JPanel jp = new JPanel();
JLabel jl = new JLabel();
JTextField jt = new JTextField("Month",30);
JTextField jt2 = new JTextField("Date",30);
JButton jb = new JButton("Enter");
public static void main (String[] args); {
setTitle("Tutorial");
setVisible(true);
setSize(400, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
...
}
public Text()
{
...
}
...
}
Java doesnt allow methods to be defined within other methods. Move the main method out of the Text constructor and remove the semi-colon which is terminating the statement early.
In addition you have a number of methods (e.g. setTitle and setVisible) which belong to the JFrame - these need to be moved to an instance code block to make them are accessible.
public class Text extends JFrame {
JPanel jp = new JPanel();
JLabel jl = ...
public Text() {
setTitle("Tutorial");
setVisible(true);
...
add(jp);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Text().setVisible(true);
}
});
}
}
Delete the ; after the main method declaration:
public static void main (String[] args);
^-------- Delete this
And put the main method out of the constructor:
public Text() {
...
}
public static void main(...) {
...
}

Adding text to a label from another class - Simple Logic Issue

I have a label and a button in a class called FrameTest, when i press the button, a method named buttonpressed get's executed from the class Test. In this buttonpressed method i will set a text to the label found in the FrameTest class.
The problem i have is that, the text for the label is not getting set. The reason is that i am creating a separate object to call the buttonpressed method;
public void actionPerformed(ActionEvent arg0) {
Test t = new Test();
t.buttonpress();
}
and i am creating a separate object in the main method of the Test class to create the UI.
public static void main(String[] args) {
FrameTest f = new FrameTest();
f.mainScreen();
}
The full code as follows;
public class FrameTest extends JFrame {
private JPanel contentPane;
private JLabel lblLabel;
private FrameTest ft = this;
//private FrameTest frame;
/**
* Launch the application.
*/
public void mainScreen() {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
//FrameTest frame = new FrameTest();
//setVisible(true);
FrameTest frame = ft;
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void writeLabel(String k){
this.lblLabel.setText(k);
}
public FrameTest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
//setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
lblLabel = new JLabel("LABEL");
contentPane.add(lblLabel, BorderLayout.CENTER);
JButton btnNewButton = new JButton("Press");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Test t = new Test();
t.buttonpress();
}
});
contentPane.add(btnNewButton, BorderLayout.WEST);
//pack();
setLocationByPlatform(true);
}
}
Test Class
public class Test {
public static void main(String[] args) {
FrameTest f = new FrameTest();
f.mainScreen();
}
public void buttonpress(){
FrameTest f = new FrameTest();
f.writeLabel("Button was pressed");
}
1) Dont extend JFrame class unnecessarily.
2) dont use setContentPane() unless thats what you want. Rather just simply JFrame#add(..).
3) Steer away from EventQueue and use SwingUtilities block rather
4) Dont forget to call JFrame#pack(); before setting JFrame visible.
5) Java naming convention is CamelCase so buttonPress() is correct not buttonpress()
Here is an example I made (basically your code fixed):
Test.java: (This is the main class which will create an instance of your FrameTest and has the method to change JLabel text)
import javax.swing.SwingUtilities;
public class Test {
private static FrameTest f;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
f = new FrameTest();
f.mainScreen();
}
});
}
void buttonPress() {
f.writeLabel("Hello");
}
}
FrameTest.java: (This class will show the JFrame and create a new instance of class Test to call buttonPress()):
import java.awt.BorderLayout;
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.border.EmptyBorder;
public class FrameTest {
private JPanel panel;
private JLabel lblLabel;
private JFrame frame;
private void initComponents() {
frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
panel = new JPanel();
panel.setBorder(new EmptyBorder(5, 5, 5, 5));
panel.setLayout(new BorderLayout(0, 0));
lblLabel = new JLabel("LABEL");
panel.add(lblLabel, BorderLayout.CENTER);
JButton btnNewButton = new JButton("Press");
btnNewButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Test t = new Test();
t.buttonPress();
}
});
panel.add(btnNewButton, BorderLayout.WEST);
frame.add(panel);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public void writeLabel(String k) {
this.lblLabel.setText(k);
}
void mainScreen() {
initComponents();
}
}
Pass your FrameTest object to the buttonpress method and use it there, instead of creating a new object:
public void buttonpress(FrameTest f) {
f.writeLabel("Button was pressed");
}
Change the invocation of the method like so:
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Test t = new Test();
t.buttonpress(FrameTest.this);
}
});
You have to use FrameTest.this here, as you're inside of an anonymous class implementing ActionListener, so the normal this would reference to that anonymous class.
- Well the first approach is using Composition Principle, where you create an instance of FrameTest.java in Test.java class and then access the Label (use Getter Setters for this label in FrameTest) in FrameTest.java class using this instance.
- Second approach is a dirty and quick fix one, make the Label static in FrameTest.java class and directly set the value from Test.java class. Voila its done.....
- The reason your code is not working, cause you have created a very new instance of the FrameTest class. So now you either pass the FrameTest Object Reference Variable to buttonpress() method or make the label static.
Eg:
public class FrameTest extends JFrame {
private JPanel contentPane;
public static JLabel lblLabel;
.....
.....
}
Or
public void buttonpress(FrameTest f) {
f.writeLabel("Button was pressed");
}
/////////////////////////// Edited Part ///////////////////////////////////
import java.awt.BorderLayout;
import java.awt.EventQueue;
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.border.EmptyBorder;
class FrameTest extends JFrame {
private JPanel contentPane;
private JLabel lblLabel;
private FrameTest ft = this;
public void mainScreen() {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
FrameTest frame = ft;
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void writeLabel(String k) {
this.lblLabel.setText(k);
}
public FrameTest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
lblLabel = new JLabel("LABEL");
contentPane.add(lblLabel, BorderLayout.CENTER);
JButton btnNewButton = new JButton("Press");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Test t = new Test();
t.buttonpress(FrameTest.this); // Passing the current object to
// the Test class
// You can use just "this" , but
// as we are in an Anonymous
// Inner Class here,
// we have to use
// "Class_name.this"
}
});
contentPane.add(btnNewButton, BorderLayout.WEST);
// pack();
setLocationByPlatform(true);
}
}
public class Test {
public static void main(String[] args) {
FrameTest f = new FrameTest();
f.mainScreen();
}
public void buttonpress(FrameTest f) { // Receiving the reference to the
// current frame, but remember
// THOUGH IT SEEMS that we are passing the
// reference but still in
// Here and in Java its always pass
// by copy.( ie pass by value).
f.writeLabel("Button was pressed");
}
}
Just change your Test class like below
package com.test;
public class Test {
private static FrameTest f;
public static void main(String[] args) {
f = new FrameTest();
f.mainScreen();
}
public void buttonpress() {
f.writeLabel("Button was pressed");
}
}
The actual problem was
You created a FrameTest variable f in main and shown the UI to user.
Then on button press you again created another FrameTest instance f, which does not map the original/first f
Now i treat the variable as a class variable and it works as expected

Categories

Resources