Java AWT / Swing更新JPanel连续不起作用

问题描述 投票:0回答:1

我正在尝试制作一个程序,该程序使用包含JButton值的字符串键的HashMap的内容填充GridLayout的JPanel。由于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应该不断用更新后的带有不同文本的JButton重新填充,但是看来程序挂起了并且没有更新。我尝试制作一个更简单的示例,该示例是我从here修改而来的,结果不同:

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();  

    }  
} 

此代码段无法绘制任何内容,这与第一个代码段至少绘制了在构造函数中创建的对象不同。

如何通过程序实时地更新列表或网格JPanel并填充按钮?我知道我可以每次更改每个按钮的文本,但是按钮的数量可以随时更改。

完整代码here

java swing awt
1个回答
0
投票

您违反了Swing的单线程规则-您不应在Swing的事件分配线程之外执行任何与UI相关的事情。

阅读herehere

© www.soinside.com 2019 - 2024. All rights reserved.