Java AWT/Swing更新JPanel持续不工作
我试图制作一个程序,用GridLayout填充JPanel,其中包含JButton值的字符串键的HashMap的内容。因为HashMap的大小可能会改变,所以我不能对每个按钮都使用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
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);
}
}