Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当鼠标已经在按钮上方时,鼠标侦听器如何在特定时间后激活?_Java_Swing_Mouseevent_Border_Mouselistener - Fatal编程技术网

Java 当鼠标已经在按钮上方时,鼠标侦听器如何在特定时间后激活?

Java 当鼠标已经在按钮上方时,鼠标侦听器如何在特定时间后激活?,java,swing,mouseevent,border,mouselistener,Java,Swing,Mouseevent,Border,Mouselistener,我正在尝试在计时器结束后在react按钮上显示边框。除非我把鼠标从触发按钮上移开,然后再移回到触发按钮上,否则我似乎无法让这种情况发生。有没有一种方法可以激活鼠标侦听器,而不必先将鼠标移开,然后在计时器后再打开触发器按钮?请不要说:计时器结束时设置边框,因为这不是我要找的。 此外,请随时指出我的代码中的其他错误或坏习惯。我不熟悉Java编码 import java.util.Timer; import java.util.TimerTask; import java.awt.Color; imp

我正在尝试在计时器结束后在react按钮上显示边框。除非我把鼠标从触发按钮上移开,然后再移回到触发按钮上,否则我似乎无法让这种情况发生。有没有一种方法可以激活鼠标侦听器,而不必先将鼠标移开,然后在计时器后再打开触发器按钮?请不要说:计时器结束时设置边框,因为这不是我要找的。 此外,请随时指出我的代码中的其他错误或坏习惯。我不熟悉Java编码

import java.util.Timer;
import java.util.TimerTask;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class ButtonTester{

  public static final Border PANEL_BORDER = new LineBorder(Color.red, 12);
  public static JPanel panel;
  public static JButton trigger;
  public static JButton react;
  public static JLabel msg;

  public static void main(String [] args){
    JFrame frame = new JFrame();
    frame.setSize(new Dimension(500,200)); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    panel = new JPanel();
    panel.setBorder(PANEL_BORDER);
    frame.getContentPane().add(panel);

    JButton trigger = new JButton("Trigger");
    JButton react = new JButton("React");
    JLabel msg = new JLabel();
    react.setPreferredSize(new Dimension(200, 60));
    trigger.setPreferredSize(new Dimension(200, 60));

    panel.add(trigger); 
    panel.add(react);
    panel.add(msg);
    panel.setVisible(true);
    frame.setVisible(true);

    MouseListener mL = new MouseAdapter(){
      @Override public void mouseEntered(MouseEvent evt) {
        react.setBorder(PANEL_BORDER);
      }
      @Override public void mouseExited(MouseEvent evt) {
        react.setBorder(javax.swing.BorderFactory.createEmptyBorder());
      }
    };
    countDown(msg, trigger, mL);
  }

  public static void countDown(JLabel msg, JButton trigger, MouseListener mL){
    Timer timer = new Timer();
    TimerTask task = new TimerTask(){
      short seconds = 4; 
      public void run(){
        if(seconds == 0){
          timer.cancel(); 
          trigger.addMouseListener(mL); 
          return;
        }
        seconds--;
        msg.setText("Attempting to add listener in : "+seconds);
      }
    };
    timer.scheduleAtFixedRate(task, 1000, 1000);
  }

}

如果您的鼠标位于
trigger
按钮上,然后将
MouseListener
添加到按钮上,则它无法捕获之前发生的进入
trigger
按钮区域的事件

如果您坚持在鼠标位于
触发器
按钮上时显示边框,而不在其上下移动,则应在添加
mouseListener
后手动调用
mouseEnter
方法:

(在此之前,您应该将
final JFrame
传递给您的
countDown
方法)

但正如MadProgrammer提到的,你的问题并不清楚,因为你说“我正试图让react按钮在计时器结束后显示一个边框”


希望这有帮助

好的,本例设置了两个状态变量,一个用于确定鼠标是否已进入或退出按钮,另一个用于确定计时器是否已完成

如果这两个条件为
true
,则设置边框

这意味着,当计时器用完时,如果鼠标不在
trigger
按钮上方,则不会更改
react
按钮的边框,但如果用户移回按钮,则会更改边框。当鼠标位于
触发器
按钮上方且计时器耗尽时,它也将被更改

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        public static final Border PANEL_BORDER = new LineBorder(Color.red, 12);

        private boolean mouseInTheHouse = false;
        private boolean timedOut = false;

        private JButton react;
        private JButton trigger;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.ipadx = 200;
            gbc.ipady = 60;
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            react = new JButton("React");
            trigger = new JButton("Trigger");

            add(react, gbc);
            add(trigger, gbc);

            trigger.addMouseListener(new MouseAdapter() {

                @Override
                public void mouseEntered(MouseEvent e) {
                    mouseInTheHouse = true;
                    stateChanged();
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    mouseInTheHouse = false;
                }

            });
            Timer timer = new Timer(4000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    timedOut = true;
                    System.out.println("!!");
                    stateChanged();
                }
            });
            timer.start();
        }

        protected void stateChanged() {
            if (mouseInTheHouse && timedOut) {
                react.setBorder(PANEL_BORDER);
            }
        }

    }

}
请注意,我没有设置当鼠标离开
触发器
按钮时应该发生什么的条件,但我假设您会重置边框


我明白了。我还有一个问题。如果我有10个触发按钮(面板顶部)和10个反应按钮(面板底部),会怎么样?条件是:如果我将鼠标放在其中一个触发按钮上,则相同位置的相应react按钮加上react按钮右侧的react按钮将具有边框。我如何在不循环浏览按钮列表和检测鼠标座的情况下检测到它

基本上,将想法提炼到最普通的层次。您有两个按钮,一个
计时器
鼠标侦听器
和两个状态变量。将它们封装到一个公共类中,然后可以重用

public class ButtonStateManager {

    private boolean mouseInTheHouse = false;
    private boolean timedOut = false;

    private JButton trigger;
    private JButton react;

    private Timer timer;

    public ButtonStateManager(JButton trigger, JButton react, int timeOut) {
        this.trigger = trigger;
        this.react = react;

        trigger.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseEntered(MouseEvent e) {
                mouseInTheHouse = true;
                stateChanged();
            }

            @Override
            public void mouseExited(MouseEvent e) {
                mouseInTheHouse = false;
            }

        });

        Timer timer = new Timer(timeOut, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                timedOut = true;
                stateChanged();
            }
        });
    }

    protected void stateChanged() {
        if (mouseInTheHouse && timedOut) {
            react.setBorder(TestPane.PANEL_BORDER);
        }
    }

}

现在,这假设两个按钮之间存在关系。

“另外,请随意指出我的代码中的其他错误或坏习惯。我对Java编码还不熟悉”-不要使用
Java.util.Timer
当您想要与UI交互时,使用
SwingWorker
javax.swing.Timer
。我还避免使用
setPreferredSize
,它没有考虑
getPreferredSize
计算其值时使用的许多条件。相反,考虑使用
JButton
上的
setMargin
或不同布局管理器中可用的不同布局约束,“请不要说:计时器结束时设置边框,因为这不是我要找的”-好的,但这听起来正是你要问的-“我试图在计时器结束后让react按钮显示一个边框”…所以我很困惑所以,你看起来是什么“换句话说,如果在您将
MouseAdapter
设置为
trigger
按钮后,鼠标位于
trigger
按钮上方,那么您是否希望触发侦听器?相反,你可以先应用侦听器,然后有两个标志,一个决定鼠标是否进入或退出按钮,另一个决定计时器是否已完成,这样,你就可以将这两个标志结合起来。它可能需要一个附加的方法或观察者将两个状态结合在一起,但是基本的想法应该是:如果鼠标实际上不在按钮上,会发生什么?@ MaldCuoth:非常好的考虑点!我应该检查鼠标是否确实在按钮区域,然后调用
mouseenterned
方法。谢谢我认为有两种,但我认为有一种更简单的方法;)实际上@statefi,这是一个非常好的解决方案。我试着用10个触发按钮和10个反应按钮将其应用到我的情况中,但没有循环,所以它对我想要如何使用它没有那么有效。我更愿意跳过循环。@PhongVo yes事件或动作侦听器是一些方法,在某些接口中最有可能被设计为
public
方法,可以类似于其他方法进行调用。实际上,注册监听器的机制是在某些情况下或由于某个操作而调用它们的nethods,这是一些隐藏的方法调用。我还有一个问题。如果我有10个触发按钮(面板顶部)和10个反应按钮(面板底部),会怎么样?条件是:如果我将鼠标放在其中一个触发按钮上,则相同位置的相应react按钮加上react按钮右侧的react按钮将具有边框。我如何在不循环浏览我的按钮列表和检测鼠标座的情况下检测到它?事实上,没关系。我使用MouseInfo获取位置,使用组件方法findComponentAt()检查它的实例,然后调用mouseEnter。谢谢你!基本思想是将MouseAdpter和ActionListener封装到一个可重用的类中。这样就可以用来管理这些状态
public class ButtonStateManager {

    private boolean mouseInTheHouse = false;
    private boolean timedOut = false;

    private JButton trigger;
    private JButton react;

    private Timer timer;

    public ButtonStateManager(JButton trigger, JButton react, int timeOut) {
        this.trigger = trigger;
        this.react = react;

        trigger.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseEntered(MouseEvent e) {
                mouseInTheHouse = true;
                stateChanged();
            }

            @Override
            public void mouseExited(MouseEvent e) {
                mouseInTheHouse = false;
            }

        });

        Timer timer = new Timer(timeOut, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                timedOut = true;
                stateChanged();
            }
        });
    }

    protected void stateChanged() {
        if (mouseInTheHouse && timedOut) {
            react.setBorder(TestPane.PANEL_BORDER);
        }
    }

}