Swing - Update Label

Swing JLabel text change on the running application

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.event.*;
public class Test extends JFrame implements ActionListener
{
private JLabel label;
private JTextField field;
public Test()
{
super("The title");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setPreferredSize(new Dimension(400, 90));
((JPanel) getContentPane()).setBorder(new EmptyBorder(13, 13, 13, 13) );
setLayout(new FlowLayout());
JButton btn = new JButton("Change");
btn.setActionCommand("myButton");
btn.addActionListener(this);
label = new JLabel("flag");
field = new JTextField(5);
add(field);
add(btn);
add(label);
pack();
setLocationRelativeTo(null);
setVisible(true);
setResizable(false);
}
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals("myButton"))
{
label.setText(field.getText());
}
}
public static void main(String[] args)
{
new Test();
}
}

Update a Label with a Swing Timer

I don't really understand your question why you are using the Random, but here are some observations:

I want to update a JLabel with the countdown, every second.

Then you need to set the Timer to fire every second. So the parameter to the Timer is 1000, not some random number.

Also, in your actionPerformed() method you stop the Timer the first time it fires. If you are doing a count down of some kind then you would only stop the Timer when the time reaches 0.

Here is a simple example of using a Timer. It just updates the time every second:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

public class TimerTime extends JPanel implements ActionListener
{
private JLabel timeLabel;

public TimerTime()
{
timeLabel = new JLabel( new Date().toString() );
add( timeLabel );

Timer timer = new Timer(1000, this);
timer.setInitialDelay(1);
timer.start();
}

@Override
public void actionPerformed(ActionEvent e)
{
//System.out.println(e.getSource());
timeLabel.setText( new Date().toString() );
}

private static void createAndShowUI()
{
JFrame frame = new JFrame("TimerTime");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new TimerTime() );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}

public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

If you need more help then update your question with a proper SSCCE demonstrating the problem. All questions should have a proper SSCCE, not just a few random lines of code so we can understand the context of the code.

Swing - Update Label

Yes you can do this using SwingWorker thread, do all the pre submitActionPerformed() activities like updating the label, in the execute() method of the currentThread and call doTheTask() as a background job using worker Thread.

I suggest you to go through this documentation for reference about SwingWorker Thread

Update the JLabel's label text during the event - Swing

You are creating a new JLabel when pressing the button and then set the text of that label to "new value"

final JLabel lblNewLabel = new JLabel("513 k bytes");
lblNewLabel.setText("new value");

rather than changing the text of the label on your UI. You will need to call setText("new value") on a reference to the label you've already added to the UI instead. For instance, that label would neeed to be a field in your UI class, eg final JLabel fileSizeLabel and you would set that labels text by calling

fileSizeLabel.setText("new value");

inside the buttons action listener.

Updating JLabel text from another thread in real-time

You could implement a thread-safe model, that encapsulates the data the view needs. The model should be updated by the information from the serial port (represented by the Worker class).

The view should listen to model changes and update.

The following code implements Model-View-Controller pattern. It is a one-file SSCCE : it can be copy-pasted into ViewUpdatedByThread.java and run.

The view is just that. It listens to changes in Model using Observer interface.

The Model encapsulates the information that the view needs (in this case just a double value). It allows thread-safe update of the value, and notifies the observers (the view) when information changes.

The Worker class uses a thread to change the information in Model.

The Controller orchestrates the various members : initialize them, and links view to model:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.util.Collections;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class ViewUpdatedByThread {

public static void main(String[] args) {
new Controller();
}
}

//Controller of the MVC pattern."wires" model and view (and in this case also worker)
class Controller{

public Controller() {

Model model = new Model();
View view = new View(model);
model.registerObserver(view); //register view as an observer to model

Worker worker = new Worker(model);

view.getStopBtn().addActionListener(e -> worker.cancel());
}
}

//view of the MVC pattern. Implements observer to respond to model changes
class View implements Observer{

private final Model model;
private final DataPane pane;
private final JButton stopBtn;

public View(Model model) {

this.model = model;
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

pane = new DataPane();
frame.add(pane, BorderLayout.CENTER);

stopBtn = new JButton("Stop");
frame.add(stopBtn, BorderLayout.SOUTH);

frame.pack();
frame.setVisible(true);
}

JButton getStopBtn() { return stopBtn; }

@Override
public void onObservableChanged() { //update text in response to change in model
pane.setText(String.format("%.2f",model.getValue()));
}

class DataPane extends JPanel {

private final JLabel label;

DataPane() {
setPreferredSize(new Dimension(200, 100));
setLayout(new GridBagLayout());
label = new JLabel(" ");
add(label);
}

void setText(String text){ label.setText(text); }
}
}

//Model of the MVC pattern. Holds the information view needs
//Notifies observers (in this case View) when model changes
class Model { //you can make it generic Model<T>

//the value that needs to be updated
private Double value = 0.;

// thread safe set for observers
private final Set<Observer> mObservers = Collections.newSetFromMap(
new ConcurrentHashMap<Observer, Boolean>(0));
Model() {}

//set all elements to value
void changeValue(Double value){
this.value = value;
notifyObservers();
}

synchronized Double getValue() { return value; }

synchronized void setValue(Double value) { this.value = value; }

//-- handle observers

// add new Observer - it will be notified when Observable changes
public void registerObserver(Observer observer) {
if (observer != null) {
mObservers.add(observer);
}
}

//remove an Observer
public void unregisterObserver(Observer observer) {
if (observer != null) {
mObservers.remove(observer);
}
}

//notifies registered observers
private void notifyObservers() {
for (Observer observer : mObservers) {
observer.onObservableChanged();
}
}
}

//Interface implemented by View and used by Model
interface Observer {
void onObservableChanged();
}

//Encapsulates thread that does some work on model
class Worker implements Runnable{

private final Model model;
private boolean cancel = false;
private final Random rnd = new Random();

public Worker(Model model) {
this.model = model;
new Thread(this).start();
}

@Override
public void run() {
while(! cancel){
model.changeValue(rnd.nextDouble()* 100); //generate random value
try {
TimeUnit.MILLISECONDS.sleep(300); //pause
} catch (InterruptedException ex) { ex.printStackTrace(); }
}
}

void cancel() { cancel = true; }
}

Sample Image

Update bound JLabel text in Java

When I ran the code you posted, I got a NullPointerException. Here is part of the stack trace. (Note that my environment is JDK 13.0.1 on [64 bit] Windows 10.)

Exception in thread "AWT-EventQueue-0" java.awt.IllegalComponentStateException: contentPane cannot be set to null.
at java.desktop/javax.swing.JRootPane.setContentPane(JRootPane.java:598)
at java.desktop/javax.swing.JFrame.setContentPane(JFrame.java:679)
at generalp/guitests.mouse_input.displayJframe(mouse_input.java:27)

This line of the code you posted caused the error.

frame.setContentPane(new mouse_input().mouse_pad);

That's because mouse_pad is never initialized.

This is easily fixed.

private JPanel mouse_pad = new JPanel();

When I run the changed code, the following window is displayed.

mousinp0

This is because a JPanel, like all Swing containers, has no defined size because it takes on the size of its contained [GUI] components. In fact, method pack() resizes the JFrame to be big enough to hold all the contained components and the only contained component is a zero sized JPanel. So for the code you posted, in order to have a decent sized window, we need to explicitly set a size. So instead of pack() we need (for example)

frame.setSize(400, 300);

Now when I run the updated code, I get

mousinp1.png

Where is the label? According to the code you posted, it is never added to the frame. You want to add two components to the frame, namely mouse_pad and label. If you set mouse_pad as the "content pane", then you have nowhere and no way to add the label. This is where layout manager becomes relevant. Unfortunately, if you are new to Swing and you rely on the GUI builder, it is not obvious how to utilize the layout manager to organize all the components you wish to display. Learning the basics, in my opinion, is important. The GUI builder is for programmers who know Swing well and know how to utilize the builder to save them time and effort. It is not a tool for learning Swing or for shortening the learning curve. So as someone who learned the basics, I know that the default layout manager for the content pane is BorderLayout, so in the code you posted I now replace the call to method setContentPane() with the following.

frame.add(mouse_pad, BorderLayout.CENTER);
createUIComponents(); // in order to initialize member 'label'
frame.add(label, BorderLayout.PAGE_START);

Finally, you need to add a MouseMotionListener to a component that receives mouse motion events. This is not JFrame but JPanel, i.e. mouse_pad in this case. Also, a GUI builder may not let you know about class MouseMotionAdapter which implements MouseMotionListener with empty methods, so if you write a class that extends MouseMotionAdapter you only need to implement the relevant methods and not all the methods, which explains what you noted in the following comment in the code you posted.

// It doesn't like me deleting this

Here is the fixed code. It's not the best implementation but it answers your question which basically was:

My code doesn't work. How should I change it in order to make it work?

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class MouseInput {
private JPanel mouse_pad = new JPanel();
private JLabel label;

private static int x;
private static int y;

public static void main(String[] args) {
MouseInput instance = new MouseInput();
SwingUtilities.invokeLater(new Runnable(){
public void run(){
instance.createUIComponents();
instance.displayJframe();
}
});

}
public void displayJframe(){
// Create blank content frame
JFrame frame = new JFrame("Mouse Input");
frame.add(mouse_pad, BorderLayout.CENTER);
frame.add(label, BorderLayout.PAGE_START);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setVisible(true);

// Add mouse motion listener
mouse_pad.addMouseMotionListener(new MouseMotionAdapter() {

@Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
label.setText("X = " + x + " , Y = " + y);
}
});

// Set cursor type
frame.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));

// Display frame
frame.setVisible(true);
}

private void createUIComponents() {
label = new JLabel();
label.setText("X = " + x + " , Y = " + y);
}
}

For learning Swing, I recommend Creating a GUI With JFC/Swing

But if you are just starting with GUI programming in Java, have you considered JavaFX which is intended to be a more modern replacement for Swing.



Related Topics



Leave a reply



Submit