如果未选中 CheckBoxMenuItem,Java 退出 MouseListener

标签 java swing actionlistener mouselistener jmenubar

我创建了一个带有一些条目的菜单栏,其中之一是 CheckBoxMenuItem。 如果选中该项目,我想执行 MouseListener 事件,并且如果取消选中它,我希望它停止。

除此之外,我还创建了一个可以在其上执行鼠标事件的 JPanel 和一个状态栏。

为了解决这个问题,我想到了 if 循环:

clickItem.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                   if (clickItem.getState() == true) {
                       mousePanel.addMouseListener(mouseHandler);
                       mousePanel.addMouseMotionListener(mouseHandler);
                   }
                   else if (clickItem.getState() == false) {                           
                       statusBar.setText("Mouse Mode OFF");
                   }    
               }
           });

但是,如果我使用此代码运行程序,并且取消选中该复选框,则具有鼠标事件的面板不会关闭。

怎么了?

编辑:

private JLabel statusBar;
private JPanel mousePanel;


private class HandlerClass implements MouseListener, MouseMotionListener {

// Mouse events for MouseListener

public void mouseClicked(MouseEvent event) {

statusBar.setText(String.format("Clicked at %d %d", event.getX(), event.getY()));
        }
...

HandlerClass mouseHandler = new HandlerClass();

最佳答案

好吧,我知道,有点矫枉过正,但请考虑进行模型- View - Controller 设置,其中 View 尽可能愚蠢。它所做的只是创建用于显示的组件,仅此而已。该模型保存复选框的状态,它保存鼠标的位置和状态——无论是按下、拖动还是释放。该模型可以使用 Java Bean 的属性监听器支持,以便 Controller 可以向其添加监听器并收到状态更改的通知。整个事情可能看起来像:

import javax.swing.*;

// main program that creates the model and view and plugs them into 
// the controller
public class SimpleMvc {
    private static void createAndShowGui() {
        SimpleModel model = new SimpleModel();
        SimpleView view = new SimpleView();
        new SimpleController(model, view);

        JFrame frame = new JFrame("Simple MVC");
        frame.setJMenuBar(view.getJMenuBar());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(view.getMainPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

import java.awt.Point;
import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;

// model that holds the state of the program
// and notifies listeners of changes in this state
public class SimpleModel {
    public static final String CHECK_STATE = "check state";
    public static final String MOUSE_POINT = "mouse point";
    public static final String MOUSE_STATE = "mouse state";
    private SwingPropertyChangeSupport support = new SwingPropertyChangeSupport(this);
    private boolean checkState = false;
    private Point mousePoint = null;
    private SimpleMouseState mouseState = SimpleMouseState.RELEASED;

    public boolean isCheckState() {
        return checkState;
    }

    public void setCheckState(boolean checkState) {
        boolean oldValue = this.checkState;
        boolean newValue = checkState;
        this.checkState = checkState;

        // notify the listeners of the change
        support.firePropertyChange(CHECK_STATE, oldValue, newValue);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        support.addPropertyChangeListener(propertyName, listener);
    }

    public Point getMousePoint() {
        return mousePoint;
    }

    public void setMousePoint(Point mousePoint) {
        Point oldValue = this.mousePoint;
        Point newValue = mousePoint;
        this.mousePoint = mousePoint;
        support.firePropertyChange(MOUSE_POINT, oldValue, newValue);
    }

    public SimpleMouseState getMouseState() {
        return mouseState;
    }

    public void setMouseState(SimpleMouseState mouseState) {
        SimpleMouseState oldValue = this.mouseState;
        SimpleMouseState newValue = mouseState;
        this.mouseState = mouseState;
        support.firePropertyChange(MOUSE_STATE, oldValue, newValue);
    }    
}

// enum to encapsulate the mouse state
public enum SimpleMouseState {
    PRESSED("Pressed"),
    DRAGGED("Dragged"),
    RELEASED("Released");
    private String text;

    private SimpleMouseState(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }
}

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JPanel;

// our view, again make it as dumb as possible
// all the "brains" are in the model and controller
public class SimpleView {
    private static final int PREF_W = 600;
    private static final int PREF_H = 450;
    private JComponent mainPanel = new JPanel();
    private JMenuBar menuBar = new JMenuBar();
    private JLabel statusLabel = new JLabel("  ");

    public SimpleView() {
        JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        statusPanel.setBorder(BorderFactory.createEtchedBorder());
        statusPanel.add(statusLabel);

        mainPanel.setPreferredSize(new Dimension(PREF_W, PREF_H));
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(statusPanel, BorderLayout.PAGE_END);
    }

    public JComponent getMainPanel() {
        return mainPanel;
    }

    public JMenuBar getJMenuBar() {
        return menuBar;
    }

    public void setStatusMessage(String text) {
        statusLabel.setText(text);
    }

}

import java.awt.Point;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;

// our controller, where we hook everything together
public class SimpleController {
    public static final String MOUSE_MODE_OFF = "Mouse Mode OFF";
    public static final String MOUSE_MODE_ON = "Mouse Mode ON";
    private SimpleModel model;
    private SimpleView view;
    private JCheckBoxMenuItem clickItem = new JCheckBoxMenuItem("Click Me");

    public SimpleController(SimpleModel model, SimpleView view) {
        this.model = model;
        this.view = view;
        view.setStatusMessage(MOUSE_MODE_OFF);

        // Add view listeners
        clickItem.addItemListener(new ViewClickItemListener());
        JMenu menu = new JMenu("Menu");
        menu.add(clickItem);
        view.getJMenuBar().add(menu);
        ViewMouseListener mouseListener = new ViewMouseListener();
        view.getMainPanel().addMouseListener(mouseListener);
        view.getMainPanel().addMouseMotionListener(mouseListener);

        // add model listeners
        model.addPropertyChangeListener(SimpleModel.CHECK_STATE, new ModelCheckStateListener());
        model.addPropertyChangeListener(SimpleModel.MOUSE_POINT, new ModelMousePointListener());
        model.addPropertyChangeListener(SimpleModel.MOUSE_STATE, new ModelMouseStateListener());
    }

    private class ModelMousePointListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Point p = (Point) evt.getNewValue();
            String text = model.getMouseState().getText();
            view.setStatusMessage(String.format("%s at [%03d, %03d]", text, p.x, p.y));            
        }
    }

    private class ModelMouseStateListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Point p = model.getMousePoint();
            String text = model.getMouseState().getText();
            if (p == null) {
                return;
            }
            view.setStatusMessage(String.format("%s at [%03d, %03d]", text, p.x, p.y));            
        }
    }

    private class ModelCheckStateListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if ((boolean) evt.getNewValue()) {
                view.setStatusMessage(MOUSE_MODE_ON);
            } else {
                view.setStatusMessage(MOUSE_MODE_OFF);
            }
        }
    }

    private class ViewClickItemListener implements ItemListener {
        @Override
        public void itemStateChanged(ItemEvent e) {
            model.setCheckState(e.getStateChange() == ItemEvent.SELECTED);
        }
    }

    private class ViewMouseListener extends MouseAdapter {
        @Override
        public void mousePressed(MouseEvent e) {
            // check model's check state first
            if (model.isCheckState()) {
                // mouse listener is active -- change the model's state
                model.setMouseState(SimpleMouseState.PRESSED);
                model.setMousePoint(e.getPoint());
            } // else do nothing
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            // similar to mouse pressed
            if (model.isCheckState()) {
                model.setMouseState(SimpleMouseState.DRAGGED);
                model.setMousePoint(e.getPoint());
            } // else do nothing            
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            // similar to mouse pressed
            if (model.isCheckState()) {
                model.setMouseState(SimpleMouseState.RELEASED);
                model.setMousePoint(e.getPoint());
            } // else do nothing            
        }
    }
}

关于如果未选中 CheckBoxMenuItem,Java 退出 MouseListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44783486/

相关文章:

java - 制作图像查看器时出错

java - Java 中跳过第一次出现并分割字符串

java - JFrame 中的更新信息

java - 有没有办法在 JLabel 上设置 anchor ?

java - JFrame 错误 java.lang.nullpointerException

在 JButton MouseClicked 中执行的 Java 类

java - 使用此差异的构造函数参数?

java - 转发不会更改浏览器地址栏中的 URL

java - 如何将按钮链接到操作监听器和文本字段?

java - 当光标放在按钮上时更改按钮的位置