重新验证()后,Java swing按钮不可见,直到被点击

时间:2016-12-23 16:30:55

标签: java swing layout thread-safety paint

我有一个带有框布局的面板,其中包含按钮{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);
    }
}

0 个答案:

没有答案