Пользовательские слушатели мыши Java? - PullRequest
4 голосов
/ 04 ноября 2010

Во-первых, я пришел на Java в качестве программиста веб-сайта.В JavaScript все, что вам нужно сделать, чтобы добавить событие mousemove, mouseover или click, - это вызвать функцию addEventListener.Из моего ограниченного опыта работы с Java вы не можете просто реализовать интерфейс MouseListener из любого объекта.

По сути, у меня есть JPanel, который рисует некоторые фигуры (объект CustomShape с помощью метода рисования)которые имеют значения х / у / ширина / высота.Я хочу добавить некоторый тип слушателя мыши к объекту фигуры, чтобы я мог запускать события перемещения / вращения / щелчка для фигуры.Простая реализация интерфейса MouseListener для объекта CustomShape не работает (по очевидным причинам.Я посмотрел, как спроектировать пользовательские прослушиватели событий, но кажется, что создание пользовательского прослушивателя мыши не представляется возможным.

В конце концов я прибег к добавлению прослушивателя мыши к JPanel, а затем перебираювсе объекты формы.Если к объекту фигуры был прикреплен «слушатель», и координаты мыши подтвердили, что произошло событие мыши, это вызвало метод.Изначально все было хорошо, но по мере того, как приложение становилось все более развитым, оно становилось действительно очень грязным.Кроме того, я бы никогда не смог скопировать объекты / интерфейсы формы в другое приложение, не скопировав кучу кода.

В качестве простой иллюстрации: (реальный код довольно большой)

Interface CustomShape{
    int width, height, x, y;
    void paint(Graphics g);
}

public class StarShape implements CustomShape{
    int width, height, x, y;
    public StarShape(){
        width = 100;
        height = 100;
        x = 50;
        y = 50;
    }
    void paint(Graphics g){
        g.setColor(Color.black);
        g.draw(new Rectangle(x,y,width,height));
    }
}

public class Main extends JPanel{
    StarShape check = new StarShape();
    public Main(){  }
    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        check.paint(g);
    }
}

Итак, мне было интересно, существует ли чистый способ реализации какого-либо типа слушателя мыши для «рисованной» формы.

Ответы [ 3 ]

5 голосов
/ 04 ноября 2010

Чтобы иметь возможность получать события, ваши объекты "Shape" должны расширять java.awt.Component (или javax.swing.JComponent).Затем вы можете добавить их в JPanel как ребенок, и они будут получать события, и вы можете добавлять слушателей непосредственно к ним.

Как вы делаете, вы должны вручную отслеживать положение ваших фигурв JPanel.Вы бы добавили прослушиватель мыши на саму панель, и в зависимости от координат x / y получаемого события, вызовите какой-нибудь метод в форме для обработки события.Что в значительной степени переопределяет то, что базовые классы AWT / Swing сделают для вас.

2 голосов
/ 04 ноября 2010

Мой подход к тому, что ты пытаешься сделать.Скомпилируйте, запустите, прочитайте: -)

(Примечание: вы можете скопировать каждую строчку кода ниже в один файл Example01.java. Скомпилируйте и запустите.)

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

public class Example01 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame jf = new JFrame();
                MainPanel mainPanel = new MainPanel();
                jf.add(mainPanel);
                jf.setSize(640, 480);
                jf.setLocationRelativeTo(null);
                jf.setVisible(true);
            }
        });
    }
}

class MainPanel extends JPanel {
    StarShape check1 = new StarShape();
    StarShape check2 = new StarShape();

    public MainPanel() {
        check1.setName("check1");
        check2.setName("check2");
        check1.addMouseListener(new MyMouseListener(check1));
        check2.addMouseListener(new MyMouseListener(check2));
        this.add(check1);
        this.add(check2);
    }
}

class StarShape extends JComponent {
    public StarShape() {
        this.setPreferredSize(new Dimension(100, 100));
    }

    @Override
    protected void paintComponent(Graphics g) {
        g.setColor(Color.black);
        Graphics2D g2d = (Graphics2D) g;
        int x = 0;
        int y = 0;
        int width = this.getWidth() - 1;
        int height = this.getHeight() - 1;
        g2d.draw(new Rectangle(x, y, width, height));
    }
}

class MyMouseListener implements MouseListener {
    private final JComponent component;

    public MyMouseListener(JComponent component) {
        this.component = component;
    }

    public void mouseClicked(MouseEvent e) {
        System.out.println("mouseClicked: " + component.getName());
    }

    public void mouseEntered(MouseEvent e) {
        System.out.println("mouseEntered: " + component.getName());
        Dimension preferredSize = component.getPreferredSize();
        preferredSize.height += 20;
        preferredSize.width += 20;
        component.setPreferredSize(preferredSize);
        component.invalidate();
        SwingUtilities.getWindowAncestor(component).validate();
    }

    public void mouseExited(MouseEvent e) {
        System.out.println("mouseExited: " + component.getName());
        Dimension preferredSize = component.getPreferredSize();
        preferredSize.height -= 20;
        preferredSize.width -= 20;
        component.setPreferredSize(preferredSize);
        component.invalidate();
        SwingUtilities.getWindowAncestor(component).validate();
    }

    public void mousePressed(MouseEvent e) {
        System.out.println("mousePressed: " + component.getName());
    }

    public void mouseReleased(MouseEvent e) {
        System.out.println("mouseReleased: " + component.getName());
    }
}
1 голос
/ 04 ноября 2010

То, что вы могли бы сделать, это расширить форму JPanel.

public abstract class CustomShape extends JPanel {

    public CustomShape(){
        setOpaque(false);
    }

    public abstract void paintShape(Graphics g);

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        paintShape(g);
    }

}

Тогда вы можете добавлять слушателей прямо на фигуры.

Затем вам нужно будет создать своего родителя JPanel и установить его LayoutManager на null. И тогда вам нужно будет вручную установить местоположение Shape на родительском элементе.

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

...