【问题标题】:componentListener getting disabledcomponentListener 被禁用
【发布时间】:2014-03-06 23:42:11
【问题描述】:

我遇到了一个不寻常的问题,即每当 mouseListener/Adapter 检测到事件时,componentListener/Adapter 就会被禁用。在下面的代码中,componentMoved() 方法覆盖可以完美运行,直到在MouseAdapter() 中触发了mouseClicked() 方法覆盖。任何想法如何解决这个问题?

public AlertScroller(String msg,Color col) {
    addComponentListener(new ComponentAdapter() {
        @Override
        public void componentMoved(ComponentEvent e) {
            setShape(new Rectangle2D.Double(0, 0, getWidth(), newHeight));
            if(!isVisible())
                setVisible(true);
        }
    });

    addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent click) {
            if(SwingUtilities.isLeftMouseButton(click)) {
                autoClear = false;
                scrollOff();
            }
        }
    });
    setAlwaysOnTop(true);
    JPanel panel = new JPanel();
        panel.setBorder(compound);
        panel.setBackground(col);

    JLabel imgLbl = new JLabel(msg);
        imgLbl.setFont(new Font("Arial",Font.BOLD,30));

    panel.add(imgLbl);
    setContentPane(panel);
    pack();
}

这个方法所在的类扩展了JWindow。

编辑:添加了scrollOff() 方法的代码。

public void scrollOff() {
    Insets scnMax = Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration());
    int taskBar = scnMax.bottom;
    int x = screenSize.width - getWidth();
    int yEnd = screenSize.height - taskBar;
    int yStart = this.getBounds().y;
    setLocation(x,yStart);
    int current = yStart;
    newHeight = this.getBounds().height;
    while(current < yEnd) {
        current+=2;
        newHeight = yEnd - current;
        setLocation(x,current);
        try {
            Thread.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    dispose();
    Main.alertControl.setAlertActive(false);
}

这基本上与 scrollOn() 方法完全相反,只要它是通过Listener 以外的任何方式触发的,它就可以正常工作。

编辑 2:感谢 MadProgrammer 的建议,修复了以下代码

public void scrollOff() {
    x = screenSize.width - getWidth();
    yEnd = screenSize.height - taskBar;
    yStart = this.getBounds().y;
    setLocation(x,yStart);
    current = yStart;
    newHeight = this.getBounds().height;

    ActionListener action = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {
            if(current < yEnd) {
                current+=2;
                newHeight = yEnd - current;
                setLocation(x,current);
            } else {
                timer.stop();
            }
        }
    };

    timer = new Timer(30, action);
    timer.setInitialDelay(0);
    timer.start();
    Main.alertControl.setAlertActive(false);
}

我还用else if 更新了AlertScroller() 构造方法,以便在完成后正确隐藏窗口:

    addComponentListener(new ComponentAdapter() {
        @Override
        public void componentMoved(ComponentEvent e) {
            setShape(new Rectangle2D.Double(0, 0, getWidth(), newHeight));
            if(!isVisible())
                setVisible(true);
            else if(getBounds().y == screenSize.height - taskBar)
                setVisible(false);
        }
    });

将setVisible(false) 放在其他任何地方都会导致窗口再次可见。

【问题讨论】:

  • 方法scrollOff()的代码是什么?
  • 添加了scrollOff() 代码。但请注意;当由其他侦听器以外的任何东西触发时,此方法可以正常工作
  • while 循环很危险,Thread.sleep 很危险,dispose 很可怕……你违反了 Swing 的单线程规则。 dispose 可能正在处理与窗口关联的本机对等方,导致问题无止境...
  • @MadProgrammer:想解释一下我如何正确地做到这一点?我还在学习 Java,所以我不确定这样做的“正确”方法。
  • 假设,您正试图在屏幕上/关闭窗口滑动,您应该使用 Swing Timer,当触发时,它将更新窗口的位置,直到它到达它的目标点并且什么时候你会简单地改变窗口的可见性。这假设您要重用窗口的实例...

标签: java swing mouselistener jwindow componentlistener


【解决方案1】:

while loop 很危险,Thread.sleep 很危险,而且 dispose 简直吓人……

你违反了 Swing 的单线程规则,阻塞了 Event Dispatching Thread。

详情请见Concurrency in Swing

dispose 可能正在处理与窗口关联的本机对等方,导致问题无止境...

更多详情请见JWindow#dispose。

假设您试图在屏幕上/关闭窗口滑动窗口,您应该使用 Swing Timer,当触发它时,会更新窗口的位置,直到它到达它的目标点,您只需更改窗口可见性。这假设您要重用窗口的实例..

更多详情请见How to Use Swing Timers。

【讨论】:

  • 太棒了!感谢您清除这些...并帮助我成为更好的程序员!哈哈!事实上,我最初是一名艺术家,因为没有其他人可以做而开始编程......即使它是错误的,代码也会按照它的要求去做。
  • 有趣,我有一段时间反其道而行之;)
  • 在 OP 中的“Edit 2:”下发布了我更新的代码。如果我犯了其他错误,请告诉我!注意:我将几个变量更改为字段而不是局部变量,因此我只需将它们初始化一次,而不必将它们设置为final。
  • 只要确保一旦你不再使用计时器,你就会停止它;)
  • 我最终会抓住那个(我希望是 x.x),哈哈,谢谢你指出那个!现在修复它。
猜你喜欢
  • 2013-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 1970-01-01
  • 2014-02-01
  • 2015-05-08
  • 2014-10-21
相关资源
最近更新 更多