Переключить только для чтения в Java - PullRequest
3 голосов
/ 28 ноября 2011

Есть ли способ переключить режим только для чтения, чтобы при щелчке любого объекта в окне он просто возвращал то, что щелкнул, игнорируя обычную обработку события объекта?IE, в то время как в этом режиме «только для чтения», если вы нажимаете кнопку, он просто возвращает кнопку, фактически не нажимая кнопку.Тогда я мог бы сделать что-то вроде:

if ("thing pressed" == button) "do this";
else if ("thing pressed" == panel) "do that";
else "do nothing";

Вот мой код, это рамка с 3 цветными прямоугольниками.Если щелкнуть 2-й блок, 3-й блок или фон, появится сообщение.Нажатие на поле 1 ничего не делает.Мне нравится использовать новые адаптеры для мыши, поэтому я хочу сделать это следующим образом.

Теперь, что я хочу, это когда вы нажимаете поле 1, поле 1 считается выбранным (если это поможет вам получить изображение).Затем, если вы щелкнете где-нибудь, в том числе снова в поле 1, поле 1 не будет выбрано, и больше ничего (то есть будет отображаться поле 2, поле 3. или сообщение фона).В то время, только если щелкнуть флажки 2 или 3, они по-прежнему не будут отображать свое обычное сообщение, но будет отображаться другое сообщение.

Мне очень жаль, если я немного оторвусь.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

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

    Square l1, l2, l3;
    public Labels() {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        l1 = new Square();
        l2 = new Square();
        l3 = new Square();

        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(120, 150);
        frame.setResizable(false);

        panel.setVisible(true);
        panel.setLayout(null);
        l1.setLocation(5, 5);
        l2.setLocation(5, 60);
        l3.setLocation(60, 5);

        l2.setColor("yellow");
        l3.setColor("black");

        l1.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                //do nothing
            }
        });

        l2.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Pushed label 2");
            }
        });
        l3.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Pushed label 3");
            }
        });
        panel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("pushed background");
            }
        });

        frame.add(panel);
        panel.add(l1);
        panel.add(l2);
        panel.add(l3);
    }

    class Square extends JLabel{
        Color color = Color.blue;

        public Square() {
            // TODO Auto-generated constructor stub\
            setVisible(true);
            setSize(50,50);
        }

        public void paint(Graphics g) {
            super.paint(g);
            g.setColor(color);
            g.fillRect(0, 0, 50, 50);
        }
        public void setColor(String color){
            if (color == "white") this.color = Color.white;
            else if (color == "black") this.color = Color.black;
            else if (color == "yellow") this.color = Color.yellow;
            else {
                System.out.println("Invalid color");
                return;
            }
            repaint();
        }
    }
}

Ответы [ 3 ]

3 голосов
/ 28 ноября 2011

Не отключайте ничего. Просто измените состояние вашего класса, возможно, с помощью нескольких переменных / полей логических флагов и измените эти флаги в зависимости от того, что нажимается.

Так что булевы поля называются label1PressedLast, label2PressedLast и label3PressedLast или что-то подобное, и когда нажата метка, проверьте состояния всех других флагов и измените поведение вашей программы в зависимости от состояния этих флаги и метка, которая была только что нажата. Затем установите для всех флагов значение false, кроме одного, соответствующего только что нажатой метке.

Например, эта маленькая программа реагирует, только если была нажата первая и третья JLabel:

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.*;

public class FlagEg extends JPanel {
   private static final int LABEL_COUNT = 3;
   private JLabel[] labels = new JLabel[LABEL_COUNT];
   private boolean[] flags = new boolean[LABEL_COUNT];

   public FlagEg() {
      setLayout(new GridLayout(1, 0, 20, 0));
      setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

      // panel mouse listener
      addMouseListener(new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent arg0) {
            inactivateAll();
         }
      });

      MouseListener labelsMouseListener = new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent mouseEvt) {
            myMousePressed(mouseEvt);
         }
      };

      // create JLabels and add MouseListener
      for (int i = 0; i < labels.length; i++) {
         labels[i] = new JLabel("Label " + (i + 1));
         labels[i].addMouseListener(labelsMouseListener);
         labels[i].setOpaque(true);
         labels[i].setBorder(BorderFactory.createLineBorder(Color.black));
         add(labels[i]);
      }
   }

   private void inactivateAll() {
      for (int i = 0; i < labels.length; i++) {
         labels[i].setBackground(null);
         flags[i] = false;
      }
   }

   private void myMousePressed(MouseEvent mouseEvt) {
      JLabel label = (JLabel) mouseEvt.getSource();

      // which label was pressed?
      int index = -1;
      for (int i = 0; i < labels.length; i++) {
         if (label == labels[i]) {
            index = i;
         }
      }

      // check if first label and then third pressed:
      if (flags[0] && index == 2) {
         System.out.println("first and then third label pressed!");
      }

      // reset all labels and flags to initial state
      inactivateAll();

      // set pressed label background color and set flag of label just pressed
      labels[index].setBackground(Color.pink);
      flags[index] = true;

   }

   private static void createAndShowGui() {
      FlagEg mainPanel = new FlagEg();

      JFrame frame = new JFrame("Flag Example");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Логическая итерация вторая: только метка 1 - это "учебник для начинающих" JLabel. Это на самом деле проще реализовать, потому что теперь вам нужен только один логический флаг, который представляет нажатую метку 1:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class FlagEg2 extends JPanel {
   private static final int LABEL_COUNT = 3;
   private JLabel[] labels = new JLabel[LABEL_COUNT];

   private boolean label1Flag = false;

   public FlagEg2() {
      setLayout(new GridLayout(1, 0, 20, 0));
      setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

      // panel mouse listener
      addMouseListener(new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent arg0) {
            inactivateAll();
         }
      });

      MouseListener labelsMouseListener = new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent mouseEvt) {
            myMousePressed(mouseEvt);
         }
      };

      // create JLabels and add MouseListener
      for (int i = 0; i < labels.length; i++) {
         labels[i] = new JLabel("Label " + (i + 1));
         labels[i].addMouseListener(labelsMouseListener);
         labels[i].setOpaque(true);
         labels[i].setBorder(BorderFactory.createLineBorder(Color.black));
         add(labels[i]);
      }
   }

   private void inactivateAll() {
      for (int i = 0; i < labels.length; i++) {
         labels[i].setBackground(null);
         label1Flag = false;
      }
   }

   private void myMousePressed(MouseEvent mouseEvt) {
      JLabel label = (JLabel) mouseEvt.getSource();

      // which label was pressed?
      int index = -1;
      for (int i = 0; i < labels.length; i++) {
         if (label == labels[i]) {
            index = i;
         }
      }

      if (label1Flag) {
         if (index == 1) {
            System.out.println("Label 1 and label 2 pressed");
         } else if (index == 2) {
            System.out.println("Label 1 and label 3 pressed");
         }

      }

      // reset all labels and flags to initial state
      inactivateAll();

      // if label1, then activate it
      if (index == 0) {
         labels[0].setBackground(Color.pink);
         label1Flag = true;
      }

   }

   private static void createAndShowGui() {
      FlagEg2 mainPanel = new FlagEg2();

      JFrame frame = new JFrame("Flag Example");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
2 голосов
/ 28 ноября 2011

Возможно, вы захотите создать прослушиватель, который будет выполнять работу для использования putClientProperty метода JComponent .

   public class JComponentClickCountListener extends MouseAdapter {

        private final Integer ONE = 1;

        @Override
        public void mouseClicked(MouseEvent e) {
            if (e.getComponent() instanceof JComponent) {

                JComponent jComponent = (JComponent) e.getComponent();

                Object property = jComponent.getClientProperty(JComponentClickCountListener.class);

                if (property instanceof Number) {
                    property = ONE + ((Number) property).intValue();
                }
                else {
                    property = ONE;
                }

                jComponent.putClientProperty(JComponentClickCountListener.class, property);
            }

        }

    }

Тогда в своем коде вы можете решить, что для всех ваших компонентов должно быть одно единственное хранилище этого класса или каждый раз создавать новое.

Это может дать вам преимущество использования propertyChangeListener для будущих действий.

PS.

Пример кода не представляет всей логики для вопроса ОП, но я мог бы использовать его в качестве твердой основы. Позже я постараюсь обновить его. Чтобы покрыть это.

РЕДАКТИРОВАТЬ2:

Я думаю, что вы должны разделить логику выбора и действия над выбранными элементами. Затем задача делится на две задачи. Во-первых, это возможность хранить информацию о его состоянии, кликнул активным, кликнул снова неактивным. Вторая задача - работать с этим статусом при изменении статуса jComponent.

Это простой пример, который я написал, функциональность заключается в том, чтобы выделять фон меток, когда они выделены, и удалять его при повторном нажатии или при нажатии панели, чтобы удалить все выделенные элементы.

Этот пример разделен на три элемента Enum, Iterface и class, которые управляют логикой выбора

Enum - мы храним возможные статусы и ключ свойства.

public enum JComponentActivationStatus {
    NONE,
    ACTIVE,
    INACTIVE;

    public static final String PROPERTY_KEY = JComponentActivationStatus.class.getCanonicalName();
}

Интерфейс - предоставить делегату действие, которое необходимо предпринять при изменении статуса jcomponenet.

public abstract interface JComponenetActivationStatusChangeAction<T extends JComponent> {

    public abstract void onActivation(T object);

    public abstract void onDeactivation(T object);

}

Class - этот класс управляет логикой состояния jcomponents.

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JComponent;



public class JComponenetActivationManager {



    public static <T extends JComponent> T addMouseStatusControl(T jComponent) {

        jComponent.addMouseListener(new JComponentMouseStatusModyfier());

        return jComponent;
    }

    public static <T extends JComponent> T addActivationStatusChangeAction(T jComponenet, JComponenetActivationStatusChangeAction<T> statusChangeAction) {

        jComponenet.addPropertyChangeListener(craeteJCompositeActivationStatusChangeListener(statusChangeAction));

        return jComponenet;

    }

    public static  <T extends JComponent> PropertyChangeListener craeteJCompositeActivationStatusChangeListener(JComponenetActivationStatusChangeAction<T> action) {

        return new JComponentStatusPropertyChangeListener<T>(action);

    }


    /**
     * Class that set the status for the JComponet after doubClicl
     */
    private final static class JComponentMouseStatusModyfier extends MouseAdapter {

        @Override
        public void mouseClicked(MouseEvent e) {

            if(e.getComponent() instanceof JComponent) {

                JComponent jComponent = (JComponent) e.getComponent();

                Object propertyValue = jComponent.getClientProperty(JComponentActivationStatus.PROPERTY_KEY);

                if(JComponentActivationStatus.ACTIVE.equals(propertyValue)) { //We check that the ACTIVE status is already selected, if so we inactive. 
                    propertyValue = JComponentActivationStatus.INACTIVE; //If so we inactive it. 
                } else {
                    propertyValue = JComponentActivationStatus.ACTIVE; // Otherwise we set it as active
                }

                jComponent.putClientProperty(JComponentActivationStatus.PROPERTY_KEY, propertyValue); // We use the property key form status

            }
        }
    }

    /**
     * Help class that fire the actions after status is changed 
     */
    private static final class JComponentStatusPropertyChangeListener<T extends JComponent> implements PropertyChangeListener {

        private final JComponenetActivationStatusChangeAction<T> statusChangeAction;

        /**
         * 
         */
        public JComponentStatusPropertyChangeListener(JComponenetActivationStatusChangeAction<T> statusChangeAction) {

            if(statusChangeAction == null) {
                throw new IllegalArgumentException("action can not be null at this point");
            }

            this.statusChangeAction = statusChangeAction;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {

            if(JComponentActivationStatus.PROPERTY_KEY.equals(evt.getPropertyName())) {

                if(JComponentActivationStatus.ACTIVE.equals(evt.getNewValue())) {
                    statusChangeAction.onActivation((T) evt.getSource());
                }

                if(JComponentActivationStatus.INACTIVE.equals(evt.getNewValue())){
                    statusChangeAction.onDeactivation((T) evt.getSource());
                }
            }
        }

    }
}

Этот класс содержит два общедоступных статических метода, которые позволяют разработчику добавлять функциональные возможности для управления состоянием любого объекта jComponent, добавлять подписку в обработчик действий, если происходят какие-либо изменения.

В конце у нас есть основной метод, который тестирует наше решение

public static void main(String[] args) {

        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
            JLabel l1 = new JLabel("Label 1");
            JLabel l2 = new JLabel("Label 2");
            JLabel l3 = new JLabel("Label 3");

        panel.setBackground(Color.CYAN);

        addMouseStatusControl(panel);
        addMouseStatusControl(l1);
        addMouseStatusControl(l2);
        addMouseStatusControl(l3);

        JComponenetActivationStatusChangeAction<JLabel> activeBackground = new JComponenetActivationStatusChangeAction<JLabel>() {
            @Override
            public void onActivation(JLabel object) {
                object.setOpaque(true);
                object.setBackground(Color.YELLOW);
            }


            @Override
            public void onDeactivation(JLabel object) {
                object.setOpaque(false);
                object.setBackground(object.getParent().getBackground());
            }

        };


        JComponenetActivationStatusChangeAction<JPanel> deactivateChildrens = new JComponenetActivationStatusChangeAction<JPanel>() {

            @Override
            public void onDeactivation(JPanel object) {
            }

            @Override
            public void onActivation(JPanel object) {

                for(Component component : object.getComponents()) {
                    if(component instanceof JComponent) {
                        ((JComponent) component).putClientProperty(JComponentActivationStatus.PROPERTY_KEY,JComponentActivationStatus.INACTIVE); 
                    }
                }
            }
        };

        addActivationStatusChangeAction(l1, activeBackground);
        addActivationStatusChangeAction(l2, activeBackground);
        addActivationStatusChangeAction(l3, activeBackground);
        addActivationStatusChangeAction(panel, deactivateChildrens);


        panel.add(l1);
        panel.add(l2);
        panel.add(l3);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);

}

Решение очень гибкое и расширяемое на случай, если вам понадобится добавить больше меток.

Пример для тех, кто хочет учиться. Любой комментарий будет признателен.

2 голосов
/ 28 ноября 2011
package javaapplication6;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 *
 * @author Jan Vorcak <vorcak@mail.muni.cz>
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        MouseListener listener = new MouseAdapter() {

            private int count = 0;

            @Override
            public void mouseClicked(MouseEvent e) {
                if(e.getComponent() instanceof JLabel) {
                    count++;
                    if (count >= 2) {
                        System.out.println("clicked 2 times on labels");
                        count = 0;
                    }
                } else {
                    count = 0;
                }
            }

        };

        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        JLabel l1 = new JLabel("Label 1");
        JLabel l2 = new JLabel("Label 2");
        JLabel l3 = new JLabel("Label 3");
        l1.addMouseListener(listener);
        l2.addMouseListener(listener);
        l3.addMouseListener(listener);
        frame.addMouseListener(listener); // or panel.addMouseListener(listener);
        panel.add(l1);
        panel.add(l2);
        panel.add(l3);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...