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