我有一个带有框布局的面板,其中包含按钮{A,B,空...}。当我尝试删除A时,我留下{empty,B,empty}。所以我尝试添加panel.revalidate(),但现在我有{隐形,空,空}如果我鼠标悬停在那个按钮应该是并且点击它出现{B,空,空}。 添加panel.repaint()没有帮助。
Component[] components = Gui.panel.getComponents();
for(int b = 0; b < components.length; b++) {
if(((Button) components[b]).getLabel().contentEquals(parts[2])) {
Gui.panel.remove((Button) components[b]);
Gui.panel.revalidate();
Gui.panel.repaint();
break;
}
}
我还尝试重新创建跳过我想要省略的组件的列表,但它返回完全相同的结果。
Component[] components = Gui.panel.getComponents();
Gui.panel.removeAll();
for(int b = 0; b < components.length; b++) {
if(!((Button) components[b]).getLabel().contentEquals(parts[2])) {
Gui.panel.add(components[b]);
}
}
Gui.panel.revalidate();
Gui.panel.repaint();
我知道swing不是线程安全的,但我不确定这是否适用于此。 问题发生在可运行的类中,该类侦听来自服务器的消息。虽然我从同一个线程做了很多GUI操作,但这是我的第一个问题。
编辑: 这是一个突出我问题的程序:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CreativeName {
public static Thread listen;
static Object VirtualServer = new Object();
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Gui.createAndShowGUI();
}
});
listen = new Thread(new FromServer());
listen.start();
}
}
class FromServer implements Runnable {
public void run() {
//Wait for a message from the "server".
synchronized(CreativeName.VirtualServer) {
try {
CreativeName.VirtualServer.wait();
} catch (InterruptedException e) {e.printStackTrace();}
}
//Message received,remove button.
Component[] components = Gui.panel.getComponents();
for(int b = 0; b < components.length; b++) {
if(((Button) components[b]).getLabel().contentEquals("A")) {
Gui.panel.remove((Button) components[b]);
Gui.panel.revalidate();
Gui.panel.repaint();
break;
}
}
}
}
class Gui extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
protected static JPanel panel;
protected static Button remove, A, B;
public Gui() {
super(new GridBagLayout());
remove = new Button("Remove");
remove.setBackground(new Color(250, 200, 200));
remove.addActionListener(this);
A = new Button("A");
A.setBackground(new Color(200, 200, 250));
B = new Button("B");
B.setBackground(new Color(250, 250, 0));
panel = new JPanel(new GridLayout(0,3));
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
add(remove, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 5;
c.gridheight = 5;
add(panel, c);
panel.add(A);
panel.add(B);
}
public void actionPerformed(ActionEvent event) {
if(event.getSource() == remove) {
//Send a message from the "server".
synchronized(CreativeName.VirtualServer) {
CreativeName.VirtualServer.notify();
}
}
}
static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Button Dilemma");
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(300, 400));
//Add contents to the window.
frame.add(new Gui());
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
我设置了一个监视器来模拟服务器,似乎问题是线程安全。也许我可以反转显示器,以便来自服务器的消息将通知Gui线程?我还没有看到要对它进行处理。
编辑:确认在EDT上发生呼叫后,我得到了相同的结果。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CreativeName {
public static Thread listen;
static Object VirtualServer = new Object();
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Gui.createAndShowGUI();
}
});
listen = new Thread(new FromServer());
listen.start();
}
}
class FromServer implements Runnable {
public void run() {
//Wait for a message from the "server".
synchronized(CreativeName.VirtualServer) {
try {
CreativeName.VirtualServer.wait();
} catch (InterruptedException e) {e.printStackTrace();}
}
//Message received,remove button.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (SwingUtilities.isEventDispatchThread()) {
System.err.println("Is running on EDT");
} else {
System.err.println("Is not running on EDT");
}
Component[] components = Gui.panel.getComponents();
for(int b = 0; b < components.length; b++) {
if(((Button) components[b]).getLabel().contentEquals("A")) {
Gui.panel.remove((Button) components[b]);
Gui.panel.revalidate();
Gui.panel.repaint();
break;
}
}
}
});
}
}
class Gui extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
protected static JPanel panel;
protected static Button remove, A, B;
public Gui() {
super(new GridBagLayout());
remove = new Button("Remove");
remove.setBackground(new Color(250, 200, 200));
remove.addActionListener(this);
A = new Button("A");
A.setBackground(new Color(200, 200, 250));
B = new Button("B");
B.setBackground(new Color(250, 250, 0));
panel = new JPanel(new GridLayout(0,3));
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
add(remove, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 5;
c.gridheight = 5;
add(panel, c);
panel.add(A);
panel.add(B);
}
public void actionPerformed(ActionEvent event) {
if(event.getSource() == remove) {
//Send a message from the "server".
synchronized(CreativeName.VirtualServer) {
CreativeName.VirtualServer.notify();
}
}
}
static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Button Dilemma");
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(300, 400));
//Add contents to the window.
frame.add(new Gui());
//Display the window.
frame.pack();
frame.setVisible(true);
}
}