Java 每次帧更新JLabel';s面板已更新

Java 每次帧更新JLabel';s面板已更新,java,swing,Java,Swing,如何在帧中的topPanel中将JLabelCount#0更新为Count#1(续) 最初它是Count#0,随着操作的进一步执行,它会变为Count#1 输出:它显示的是Count#0,但它应该是Count#2,因为灰色框位于第二级,同样,它应该显示Count#5,因为它位于顶部的第五级 import java.awt.*; import java.awt.image.BufferedImage; import javax.swing.*; class Count { private

如何在帧中的topPanel中将JLabel
Count#0
更新为
Count#1
(续)

最初它是
Count#0
,随着操作的进一步执行,它会变为
Count#1

输出:它显示的是
Count#0
,但它应该是
Count#2
,因为灰色框位于第二级,同样,它应该显示
Count#5
,因为它位于顶部的第五级

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);
    }
}
import java.awt.*;
导入java.awt.image.buffereImage;
导入javax.swing.*;
班级人数{
私有整数;
公众计数(){
this.num=1;
}
//生成下一个号码
公共void生成(int currentNumber){
this.num=当前编号;
这个.num+=1;
}
public int getNumber(){
返回这个.num;
}
}
类面板扩展了JPanel{
私有最终缓冲图像;
私人计数;
公共事务委员会(){
this.image=新的BuffereImage(300300,BuffereImage.TYPE_INT_RGB);
this.count=新计数();
定时器定时器=新定时器(0,ae->createImage(图像));
定时器设置延迟(1000);
timer.start();
}
public void createImage(buffereImage图像){
Graphics g=image.getGraphics();
int number=this.count.getNumber();
//在将添加到底部面板的框架上设置字段
对于(int i=0;i<(数字*20);i++){
对于(int j=0;j<(数字*20);j++){
g、 setColor(颜色为灰色);
g、 fillRect(i,j,20,20);
g、 setColor(Color.GREEN);
g、 drawRect(i,j,20,20);
}
}
//生成下一个数字
此.count.generate(number);
重新油漆();
}
公共组件(图形g){
超级组件(g);
g、 drawImage(image,0,0,null);
}
}
类GUI扩展了JFrame{
私人杰帕内尔·托帕内尔;
私人JPanel小组;
公共图形用户界面(){
topPanel=新的JPanel();
底部面板=新的JPanel();
//设置topPanel并向topPanel添加标签
topPanel.setLayout(新的BoxLayout(topPanel,BoxLayout.PAGE_轴));
更新标签(0);
//底部面板的说明
面板=新面板();
面板。设置首选尺寸(新尺寸(300300));
//将说明添加到底部面板
底部面板。添加(面板);
//将顶部面板和底部面板添加到框架
添加(topPanel,BorderLayout.PAGE_START);
添加(底部面板、边框布局、中间);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(空);
包装();
}
公共void updateLabel(整数){
//标签-1
JLabel countLabel=新JLabel(“countLabel”);
countLabel.setText(“Count#”+number);
countLabel.setFont(新字体(“Comic Sans MS”,Font.PLAIN,14));
countLabel.setBounds(10,5300,20);
topPanel.add(计数标签);
}
}
公共类编号表示{
公共静态void main(字符串[]args){
新建GUI().setVisible(true);
}
}
那么,我应该如何开始工作,以使topPanel中的JLabel在每次
Count
class
generate()
另一个数字时都保持更新,并且
generate()
面板中调用
class的
createImage()
函数

多谢各位


PS:底部面板动画很好,我只是想知道如何使用JLabel每次更新它。

我建议采用面向回调的方法,这与JButton的
addActionListener
的工作原理非常相似。警告:它有点长,如果您滥用它,可能会变得混乱,但它保持了初始类的完整分离

我们的想法是在面板类中添加一个
onUpdate
方法,该方法在面板每次更新时都会被调用。然后定义创建面板时的操作

为此,您首先需要用所需的方法声明一个抽象类或接口,我选择泛型名称,但可以自由定制

接口回调{
公共无效诉讼(INTV);
}
现在,我们可以将declare和action方法传递给任何类,该方法接受一个整数,您只需添加一个回调字段:

类面板扩展了JPanel{
私有最终缓冲图像;
私人计数;
私有回调更新;
public void setOnUpdateAction(回调操作){
this.onUpdate=操作;
}
你可以自由选择在哪里拨打onUpdate,我是在下一个号码生成后拨打的

//生成下一个号码
此.count.generate(number);
onUpdate.action(this.count.getNumber());
重新油漆();
您的
面板
类现在已准备就绪

现在,在创建面板之后,只需调用setOnUpdate操作

panel.setOnUpdateAction(新回调(){
公共无效诉讼(INTV){
countLabel.setText(“Count#”+v);
}
});
因为只有一个方法和一条指令,所以可以使用与计时器中使用的语法类似的更短的Lambda语法

panel.setOnUpdateAction(v->countLabel.setText(“Count#“+v));
(我必须将countLabel设置为一个字段,以便在GUI中访问它。)

就在这里

以下是完整的修改代码:

import java.awt.*;
导入java.awt.image.buffereImage;
导入javax.swing.*;
班级人数{
私有整数;
公众计数(){
this.num=1;
}
//生成下一个号码
公共void生成(int currentNumber){
this.num=当前编号;
这个.num+=1;
}
public int getNumber(){
返回这个.num;
}
}
接口回调{
公共无效诉讼(INTV);
}
P类