java AWT 中的 .add() 在 actionPerformed 后不工作

.add() in java AWT not working after actionPerformed

我对编码还很陌生,在我的代码中遇到过这个问题。 我使用 Java AWT 导入创建了一个按钮。然后我使用 while 循环检查响应并希望在之后创建另一个按钮,但是 .add() 似乎不再起作用。

import java.awt.*;
import java.awt.event.*;

public class Main1
{
    public static void main(String[] args)
    {
       Frame f = new Frame();
       f.setSize(500, 500);
       f.setVisible(true);
       ButtonPanel bp = new ButtonPanel(f);
       
       bp.x = null;
       while (bp.x == null)
       {
       }
       System.out.println(bp.x);
       
       //THE ISSUE- THIS WILL NOT APPEAR AFTER BUTTON PRESS
       f.add("South", new Button("REEE"));
    }
}
class ButtonPanel extends Panel implements ActionListener
{
    volatile String x;
    public ButtonPanel(Frame f)
    {
        Button b = new Button("Hi");
        b.addActionListener(this);
        f.add("North", b);
    }
    
    
    public void actionPerformed(ActionEvent e)
    {
        x = e.getActionCommand();
    }
}

我在过去一天左右一直在尝试解决这个问题,但似乎没有任何效果。我在其他帖子中看到有人说要使用 Wait/Notify 但是我不太确定这些是如何工作的,我想明确地知道我的程序出了什么问题(尽管我仍然愿意使用 Wait/Notify 在我的解决方案中)。

任何帮助将不胜感激,非常感谢

看起来什么都没发生,因为按钮被添加到 window 的底部下方。您应该考虑使用布局管理器来解决这个问题。

然而,与此同时,简单的解决方案是将此行 f.add("South", new Button("REEE")); 移动到动作事件中并利用 Frame.pack();:

public class Main1
{
    public static void main(String[] args)
    {
       Frame f = new Frame();
       //set minimums rather than a fixed size
       f.setMinimumSize(new Dimension(500, 500));
       f.setVisible(true);
       CustomButton b = new CustomButton(f);

       //Add this line to update/size/show the UI
       f.pack();
       
       //Don't place any more code inside the main method. Future events should be triggered by interacting with the UI/buttons
    }
}

那么对于我们不需要扩展Panel的按钮,我们可以这样做:

class CustomButton implements ActionListener
{
    Frame parentFrame;
    public CustomButton(Frame f)
    {
        parentFrame = f;
        Button b = new Button("Hi");
        b.addActionListener(this);
        f.add("North", b);
    }
    
    public void actionPerformed(ActionEvent e)
    {
        //Add button here instead of the main class
        parentFrame.add("South", new Button("REEE"));
        //The buttons are being added below the bottom of your window, this will force them to be shown.
        //Using a layout manager will solve this ploblem and you will not need to do this:
        parentFrame.pack();
    }
}

注意:如果您调整 window.

的大小,多次单击“Hi”按钮将会出现“REEE”按钮重叠或做奇怪事情的有趣结果

所以,这里有很多问题。

首先是布局管理器通常很懒惰。这意味着您可以添加 and/or 快速删除多个组件,然后进行单个布局和绘制过程。

为此,您需要 revalidate 已更新的 Container

其次,AWT(以及扩展的 Swing)基于模型-视图-控制器概念,其中一个方面是“观察者模式”。这基本上是一个回调概念,允许您在感兴趣的事情发生时收到通知。

Button 使用 ActionListener 在按钮被“操作”时生成事件。这就是实际的“观察者模式”。

为什么这很重要?您真的要考虑需要将哪些信息传递到哪里以及谁实际负责做什么。

例如,更新框架真的是ButtonPanel的责任吗?让 ButtonPanel 不受约束地控制框架真的是个好主意吗?

相反,ButtonPanel“应该”在发生某些操作时提供某种通知,然后任何相关方都应该能够做他们需要做的事情。

作为“基本”示例...

import java.awt.Button;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.EventListener;
import javax.swing.event.EventListenerList;

public class Test {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test();
            }
        });
    }

    public Test() {
        Frame f = new Frame();
        f.setPreferredSize(new Dimension(500, 500));
        f.pack();

        ButtonPanel bp = new ButtonPanel(f);
        bp.addObsever(new Observer() {
            @Override
            public void hiWasPerformed() {
                f.add("South", new Button("REEE"));
                f.revalidate();
            }
        });

        f.setVisible(true);
    }

    public interface Observer extends EventListener {
        public void hiWasPerformed();
    }


    class ButtonPanel extends Panel  {

        private EventListenerList eventListener = new EventListenerList();

        public ButtonPanel(Frame f) {
            Button b = new Button("Hi");
            b.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Observer[] listeners = eventListener.getListeners(Observer.class);
                    for (Observer observer : listeners) {
                        observer.hiWasPerformed();
                    }
                }
            });
            f.add("North", b);
        }

        public void addObsever(Observer observer) {
            eventListener.add(Observer.class, observer);
        }

        public void removeObsever(Observer observer) {
            eventListener.remove(Observer.class, observer);
        }
    }
}