Java AWT/Swing更新JPanel持续不工作

Java AWT/Swing更新JPanel持续不工作,java,swing,awt,Java,Swing,Awt,我试图制作一个程序,用GridLayout填充JPanel,其中包含JButton值的字符串键的HashMap的内容。因为HashMap的大小可能会改变,所以我不能对每个按钮都使用setText()。到目前为止,我已经调用了.removeAll()来删除所有按钮的JPanel,然后我通过HashMap循环来重新填充JPanel。然后在JPanel上调用revalidate(),在JFrame上调用repaint() 当前代码: public class GUI implements Runnab

我试图制作一个程序,用GridLayout填充JPanel,其中包含JButton值的字符串键的HashMap的内容。因为HashMap的大小可能会改变,所以我不能对每个按钮都使用
setText()
。到目前为止,我已经调用了
.removeAll()
来删除所有按钮的JPanel,然后我通过HashMap循环来重新填充JPanel。然后在JPanel上调用
revalidate()
,在JFrame上调用
repaint()

当前代码:

public class GUI implements Runnable, ActionListener
{
    private ToDo td;

    JFrame frame;
    Thread t=null;
    int fontsize = 18;
    private Container contentPane;
    private JPanel topPane;
    private JButton main;
    private JButton add;
    private JButton settings;
    private JPanel centerPane;
    private JScrollPane centerScroll;
    private JPanel scrollable;

    private HashMap<String, JButton> items;

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

    public GUI(){
        td = new ToDo();

        frame = new JFrame();

        t = new Thread(this);  
        t.start();

        frame.setMinimumSize(new Dimension(480, 640));
        frame.setLayout(null);  
        frame.setVisible(true);

        contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());

        topPane = new JPanel();
        topPane.setLayout(new GridLayout(1, 3));
        topPane.setPreferredSize(new Dimension(480, 40));

        main = new JButton("View Tasks");
        main.setFont(new Font("Sans Serif", Font.PLAIN, fontsize));
        add = new JButton("Add Task");
        add.setFont(new Font("Sans Serif", Font.PLAIN, fontsize));
        settings = new JButton("Settings");
        settings.setFont(new Font("Sans Serif", Font.PLAIN, fontsize));

        topPane.add(main);
        topPane.add(add);
        topPane.add(settings);

        contentPane.add(topPane, BorderLayout.NORTH);

        centerPane = new JPanel();
        centerPane.setPreferredSize(new Dimension(480, 600));

        items = new HashMap<>();

        HashMap<String, Assignment> assignments = td.getAssignments();

        scrollable = new JPanel();
        scrollable.setLayout(new GridLayout(assignments.size(), 1));
        centerScroll = new JScrollPane(scrollable);

        for(String key: assignments.keySet()){
            Assignment a = assignments.get(key);
            JButton button = new JButton(a.getTitle() + " | " + a.getDetails() + " | " + a.getClassification().getCls() + " | " + a.getStatus().getStatus());
            button.addActionListener(this);
            items.put(key, button);
            scrollable.add(button);
        }
        centerPane.add(centerScroll);        
        contentPane.add(centerPane, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }
    public void update(int i){
        HashMap<String, Assignment> assignments = td.getAssignments();
        scrollable.removeAll();
        scrollable.setLayout(new GridLayout(assignments.size(), 1));
        for(String key: assignments.keySet()){
            Assignment a = assignments.get(key);
            JButton button = new JButton(Integer.toString(i));
            button.addActionListener(this);
            items.put(key, button);
            scrollable.add(button);
        }
        scrollable.revalidate();
        frame.repaint();
    }
    @Override
    public void run(){
        int counter = 0;
        try {

            while (true) {
                update(counter);
                t.sleep( 1000 );  // interval given in milliseconds 
                counter++;
            }  
        }  
        catch (Exception e) {
            System.out.println();
        }
    }
    @Override
    public void actionPerformed(ActionEvent e){
        for(String s: items.keySet()){
            if(items.get(s) == e.getSource()){
                EventMenu em = new EventMenu(td, s);
            }
        }
    }
}
此代码段无法绘制任何内容,不像第一个代码段,它至少绘制在构造函数中创建的对象

如何按程序和实时生成列表或网格JPanel更新并填充按钮?我知道我每次都可以更改每个按钮的文本,但按钮的数量随时可能更改


完整代码。

您违反了Swing的单线程规则-您不应该在Swing的事件调度线程之外做任何与UI相关的事情

仔细阅读它,然后

下面是一个工作示例。不确定他们为什么选择使用按钮显示时间。:-)


您违反了Swing的单线程规则-您不应该在Swing的事件调度线程之外做任何与UI相关的事情

仔细阅读它,然后

下面是一个工作示例。不确定他们为什么选择使用按钮显示时间。:-)


该类实现runnable,这意味着所有内容都应该在Swing事件调度线程下运行。我举的第二个例子是基于这个项目的:。所做的唯一更改是更改正在修改的GUI项目。恐怕javatpoint.com/digital-watch上的代码是错误的,对不起。您正在执行t=新线程(此);和t.start();它启动一个新线程,并且不在AWT/Swing事件调度线程上运行。如前所述,您所基于的代码在许多方面都是错误和令人敬畏的-我建议您找到另一个/更好的示例。对于定期更新,您可能希望了解javax.swing.Timer。我在回答中添加了一个示例。该类实现了runnable,这意味着所有内容都应该在swing事件调度线程下运行。我举的第二个例子是基于这个项目的:。所做的唯一更改是更改正在修改的GUI项目。恐怕javatpoint.com/digital-watch上的代码是错误的,对不起。您正在执行t=新线程(此);和t.start();它启动一个新线程,并且不在AWT/Swing事件调度线程上运行。如前所述,您所基于的代码在许多方面都是错误和令人敬畏的-我建议您找到另一个/更好的示例。对于定期更新,您可能希望了解javax.swing.Timer。我在回答中添加了一个示例。
public class DigitalWatch implements Runnable{  
    JFrame f;  
    JPanel p;
    Thread t=null;  
    int hours=0, minutes=0, seconds=0;  
    String timeString = "";  
    JButton b;  

    DigitalWatch(){  
        f=new JFrame();  
        p = new JPanel();
        t = new Thread(this);  
            t.start();  

        b=new JButton();  
            b.setBounds(100,100,100,50);  

        p.add(b);
        f.add(p);
        f.setSize(300,400);  
        f.setLayout(null);  
        f.setVisible(true);  
    }  

    public void run() {  
        try {  
            while (true) {  

                Calendar cal = Calendar.getInstance();  
                hours = cal.get( Calendar.HOUR_OF_DAY );  
                if ( hours > 12 ) hours -= 12;  
                minutes = cal.get( Calendar.MINUTE );  
                seconds = cal.get( Calendar.SECOND );  

                SimpleDateFormat formatter = new SimpleDateFormat("hh:mm:ss");  
                Date date = cal.getTime();  
                timeString = formatter.format( date );  

                p.removeAll();
                b=new JButton(timeString);  
                b.setBounds(100,100,100,50); 
                p.add(b);
                f.add(p);
                p.revalidate();
                f.repaint();

                //printTime();  

                t.sleep( 1000 );  // interval given in milliseconds  
            }  
        }  
          catch (Exception e) {
          System.out.println(e);
        }  
    }

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

    }  
} 
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.Timer;

public class DigitalWatch extends JFrame {

    private DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);

    public DigitalWatch() {
        JButton btn = new JButton(getCurrentTime());
        this.getContentPane().setLayout(new FlowLayout());
        this.getContentPane().add(btn);
        this.setPreferredSize(new Dimension(200, 150));
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null); // center it on the screen
        new Timer(500, e -> btn.setText(getCurrentTime())).start();
    }

    private String getCurrentTime() {
        return formatter.format(LocalTime.now());
    }

    public static void main(String[] args) {
        new DigitalWatch().setVisible(true);
    }

}