【问题标题】:How to disable a JPanel from doing anything in Java如何禁止 JPanel 在 Java 中执行任何操作
【发布时间】:2012-12-19 23:14:00
【问题描述】:

我在禁用 JPanel 以使其内部调用任何方法时遇到问题。我设置了一个带有 2 个 JPanel 的框架来控制框架的图形。问题是,如果我在 Frame 中添加了一个新的 JPanel,并且我还删除了之前存在的旧 JPanel,那么旧 JPanel 中的绘制方法仍然会被调用。

这是我用来测试的代码:

开始类:

    import java.awt.Frame;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.WindowEvent;
    import java.awt.event.WindowListener;

    public class Start implements WindowListener, KeyListener{
        public static void main(String[] args) {
            new Start();
        }

        Frame frame = new Frame("Frame");

        TestPanel P1 = new TestPanel();
        TestPanel P2 = new TestPanel();

        static boolean active = true;

        public Start() {
            frame.setSize(500,500);
            frame.setLocationRelativeTo(null);
            frame.addWindowListener(this);
            frame.addKeyListener(this);
            frame.setVisible(true);
            frame.add(P1);
            for (Object c : frame.getComponents()){
                System.out.println(c.toString());
            }
        }

        @Override
        public void keyPressed(KeyEvent e) {
            if (active){
                frame.remove(P1);
                    frame.add(P2);
            }else{
                frame.remove(P2);
                frame.add(P1);
            }
            active = !active;
            for (Object c : frame.getComponents()){
                System.out.println(c.toString());
            }
        }

        @Override
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }

        public void windowOpened(WindowEvent e) {}
        public void windowClosed(WindowEvent e) {}
        public void windowIconified(WindowEvent e) {}
        public void windowDeiconified(WindowEvent e) {}
        public void windowActivated(WindowEvent e) {}
        public void windowDeactivated(WindowEvent e) {}
        public void keyTyped(KeyEvent e) {}
        public void keyReleased(KeyEvent e) {}
    }

TestPanel 类:

    import java.awt.Graphics;
    import javax.swing.JPanel;


    public class TestPanel extends JPanel{
        boolean active = Start.active;

        @Override
        public void paint(Graphics g) {
            System.out.println(active);
        }
    }

这个程序总是打印“true”,告诉我只有对象 P1 处于活动状态,而 P2 什么也不做,即使它显示在屏幕上。

所以我要问的是如何让 P1 对象在它不在屏幕上时停止调用绘制方法,并让 P2 对象在显示时调用它的绘制方法。

【问题讨论】:

  • 同一个类有两个单独的实例,你怎么知道哪个是开始调用的? (ps CALL super.paint(g)!更好的是,覆盖paintComponent!)
  • 尽可能避免使用静态属性(静态最终很好;静态本身可能意味着糟糕的设计)

标签: java swing jpanel frame


【解决方案1】:

让我们开始

TestPanel P1 = new TestPanel();
TestPanel P2 = new TestPanel();

P1P2 是同一类的不同实例。

看看

static boolean active = true;

// From TestPane
public void paint(Graphics g) {
    System.out.println(active);
}

因此,无论屏幕上是哪个面板,它都会始终显示 active 的值。

你没有提供任何方法来实际识别对象的不同实例,那么,你怎么知道P1实际上是开始调用的??

【讨论】:

  • 我可能没有解释清楚。当你按下键盘上的一个键时,活动变量通过这段代码切换状态:active = !active;
  • @alex 但是active 是一个静态变量,所以屏幕上的哪个面板都没有关系,它们也会显示相同的值 - 那么OP实际上如何知道哪个面板是在屏幕上??
【解决方案2】:

您在每个面板中的局部变量 'active' 不是参考,而是原始变量。它的值设置为创建面板时在“开始”类中设置的任何静态值。对于两个 Panel 实例,您显示的代码中的哪个都是“真”。这解释了为什么您的代码总是打印“true”。

至于显示问题,请注意删除功能的JavaDoc:

注意:如果组件已从容器中移除 显示时,必须在该容器上调用 validate() 以反映 变化。如果要删除多个组件,您可以改进 在所有组件之后只调用一次 validate() 来提高效率 已被删除。

【讨论】:

    【解决方案3】:

    可能是因为Frame的remove方法是针对MenuComponent的。 http://docs.oracle.com/javase/6/docs/api/java/awt/Frame.html#remove%28java.awt.MenuComponent%29 ... 正确的方法是使用 frame.getContentPane().add(P1) 添加组件。尝试使用 frame.getContentPane().remove(P1) 看看它是否有效。

    【讨论】:

      猜你喜欢
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-10
      • 2019-07-19
      • 1970-01-01
      相关资源
      最近更新 更多