我创建了一个包含一些条目的菜单栏,其中一个是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();
答案 0 :(得分:1)
好的,我知道,但是考虑做一个模型 - 视图 - 控制器设置,其中视图尽可能愚蠢。它所做的只是创建它的组件以便显示它。模型保持复选框的状态,它保存鼠标的位置和状态 - 无论是按下,拖动还是释放。该模型可以使用Java Bean的属性侦听器支持,以便控制器可以向其添加侦听器并通知状态更改。整个事情看起来像:
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
}
}
}