【问题标题】:.add() in java AWT not working after actionPerformedjava AWT中的.add()在actionPerformed之后不起作用
【发布时间】:2021-06-14 07:25:30
【问题描述】:

我对编码相当陌生,并且在我的代码中遇到了这个问题。 我使用 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 但是我不太确定它们是如何工作的,我想明确知道我的程序出了什么问题(尽管我仍然愿意在我的解决方案)。

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

【问题讨论】:

  • 哦,对不起,我正在测试一些东西,打算在这里删除它
  • 不要像这样使用while 循环来“停止”代码执行。相反,使用回调(观察者)
  • 强烈建议:不要使用 AWT。 AWT 之后有两代 gui 框架:Swing 和 JavaFX。如果你想学习新东西,试试 javafx。

标签: java button awt


【解决方案1】:

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

不过,与此同时,简单的解决方案是将这一行 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();
    }
}

注意:如果您调整窗口大小,多次单击“Hi”按钮会产生有趣的结果,即“REEE”按钮重叠或做奇怪的事情。

【讨论】:

  • OHHHH,我有时真是个白痴,我不知道它会在框架外创建,谢谢
  • 而不是使用pack,如果用户更改它可能会影响窗口的大小,最好重新验证包含按钮的容器
【解决方案2】:

所以,这里有很多问题。

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

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

接下来,AWT(以及扩展的 Swing)基于 Model-View-Controller 概念,其中一个方面是“观察者模式”。这基本上是一个回调概念,可让您在感兴趣的事情发生时收到通知。

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

【讨论】:

    猜你喜欢
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 2016-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    相关资源
    最近更新 更多