Reputation: 127
How can I update JLabel Count #0
to Count #1
as continued, at topPanel in Frame?
Initially it is Count #0
and as the operation performs further it changes to Count #1
.
OUTPUT: Here it is showing Count #0
but it should be Count #2
as the grey box is on second level, Similarly Here it should show Count #5
, as its on fifth level from top.
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
class Count {
private int num;
public Count() {
this.num = 1;
}
// Generate Next Number
public void generate(int currentNumber) {
this.num = currentNumber;
this.num += 1;
}
public int getNumber() {
return this.num;
}
}
class Panel extends JPanel {
private final BufferedImage image;
private Count count;
public Panel() {
this.image = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
this.count = new Count();
Timer timer = new Timer(0, ae -> createImage(image));
timer.setDelay(1000);
timer.start();
}
public void createImage(BufferedImage image) {
Graphics g = image.getGraphics();
int number = this.count.getNumber();
// Set field on frame which will be added to bottomPanel
for (int i = 0; i < (number * 20); i++) {
for (int j = 0; j < (number * 20); j++) {
g.setColor(Color.GRAY);
g.fillRect(i, j, 20, 20);
g.setColor(Color.GREEN);
g.drawRect(i, j, 20, 20);
}
}
// Generating next number
this.count.generate(number);
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
}
class GUI extends JFrame {
private JPanel topPanel;
private JPanel bottomPanel;
public GUI() {
topPanel = new JPanel();
bottomPanel = new JPanel();
// Setting topPanel and Adding Label to topPanel
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.PAGE_AXIS));
updateLabel(0);
// Instructions for bottomPanel
Panel panel = new Panel();
panel.setPreferredSize(new Dimension(300, 300));
// Adding the instructions to bottomPanel
bottomPanel.add(panel);
// Adding topPanel and bottomPanel to Frame
add(topPanel, BorderLayout.PAGE_START);
add(bottomPanel, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
pack();
}
public void updateLabel(int number) {
// Label - 1
JLabel countLabel = new JLabel("CountLabel");
countLabel.setText(" Count #" + number);
countLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
countLabel.setBounds(10, 5, 300, 20);
topPanel.add(countLabel);
}
}
public class NumberPresentation {
public static void main(String[] args) {
new GUI().setVisible(true);
}
}
So, how should I start working so that the JLabel in topPanel keeps updating every time Count
class generate()
another number, and generate()
is called in Panel
class's createImage()
function?
Thank You.
PS: The bottomPanel animation is good, I just want to know how I can work around with JLabel to update it everytime.
Upvotes: 1
Views: 56
Reputation: 412
I suggest a Callback oriented approach, this is very similar to how JButton's addActionListener
works. Warning it's a bit long and might get messy if you abuse it, but it keeps your initial classes separation intact.
The idea is to add an onUpdate
method to your Panel class that gets called every time the panel updates. And then to define what the action is when you create a panel.
For that, you will first need to declare an abstract class or interface with the methods you need, I choose generic names but feel free to customize
interface Callback {
public void action(int v);
}
We can now pass declare and pass an action method that takes an integer to any class, you just need to add a Callback field :
class Panel extends JPanel {
private final BufferedImage image;
private Count count;
private Callback onUpdate;
public void setOnUpdateAction(Callback action) {
this.onUpdate = action;
}
You're free to choose where to call onUpdate, I made it after the next number is generated
// Generating next number
this.count.generate(number);
onUpdate.action(this.count.getNumber());
repaint();
Your Panel
class is now ready.
Now after creating your panel, just make a call to setOnUpdateAction
panel.setOnUpdateAction(new Callback() {
public void action(int v) {
countLabel.setText(" Count #" + v);
}
});
Since there is only one method and one instruction, you can use a shorter Lambda syntax similar to the one you used in the Timer
panel.setOnUpdateAction(v -> countLabel.setText(" Count #" + v));
( I had to make the countLabel a field to access it inside GUI.)
And there you have it !
Here's the full modified code :
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
class Count {
private int num;
public Count() {
this.num = 1;
}
// Generate Next Number
public void generate(int currentNumber) {
this.num = currentNumber;
this.num += 1;
}
public int getNumber() {
return this.num;
}
}
interface Callback {
public void action(int v);
}
class Panel extends JPanel {
private final BufferedImage image;
private Count count;
private Callback onUpdate;
public void setOnUpdateAction(Callback action) {
this.onUpdate = action;
}
public Panel() {
this.image = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
this.count = new Count();
Timer timer = new Timer(0, ae -> createImage(image));
timer.setDelay(1000);
timer.start();
}
public void createImage(BufferedImage image) {
Graphics g = image.getGraphics();
int number = this.count.getNumber();
// Set field on frame which will be added to bottomPanel
for (int i = 0; i < (number * 20); i++) {
for (int j = 0; j < (number * 20); j++) {
g.setColor(Color.GRAY);
g.fillRect(i, j, 20, 20);
g.setColor(Color.GREEN);
g.drawRect(i, j, 20, 20);
}
}
// Generating next number
this.count.generate(number);
onUpdate.action(this.count.getNumber());
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
}
class GUI extends JFrame {
private JPanel topPanel;
private JPanel bottomPanel;
private JLabel countLabel; // Made it a field to use after being created
public GUI() {
topPanel = new JPanel();
bottomPanel = new JPanel();
// Setting topPanel and Adding Label to topPanel
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.PAGE_AXIS));
updateLabel(0);
// Instructions for bottomPanel
Panel panel = new Panel();
panel.setPreferredSize(new Dimension(300, 300));
panel.setOnUpdateAction(new Callback() {
public void action(int v) {
countLabel.setText(" Count #" + v);
}
});
// You can also use this lambda syntax ( since Callback has only 1 method to implement )
// panel.setOnUpdateAction(v -> countLabel.setText(" Count #" + v));
// Adding the instructions to bottomPanel
bottomPanel.add(panel);
// Adding topPanel and bottomPanel to Frame
add(topPanel, BorderLayout.PAGE_START);
add(bottomPanel, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
pack();
}
public void updateLabel(int number) {
// Label - 1
countLabel = new JLabel("CountLabel");
countLabel.setText(" Count #" + number);
countLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
countLabel.setBounds(10, 5, 300, 20);
topPanel.add(countLabel);
}
}
public class NumberPresentation {
public static void main(String[] args) {
new GUI().setVisible(true);
}
}
Upvotes: 1