使用mouseMoved()

时间:2017-02-11 22:29:17

标签: java swing

我正在尝试编写一个程序,允许用户通过单击窗口中的JButton创建正方形或圆形,然后单击窗口中的某个位置(而不是按钮)。

我目前正在为不同的按钮使用两个actionListener,这些按钮将Square或Circle添加到Shape类型的arrayList(方形和圆形实现的接口)。我有一个名为frameListener的类,它实现MouseListener和MouseMotionListener,它在鼠标移动时更新方形或圆的位置,如果鼠标离开窗口则删除方形或圆形,或者在单击鼠标时停止更新它(制作永久)。

我还有一个名为MyPanel的类,它扩展了JPanel,并使用paintComponent(Graphics g)方法在背景上绘制正方形和圆形。

package smys01;

import java.util.ArrayList;
import java.text.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;




public class SMYS01 extends JFrame {

    private Color c = new Color(0, 0, 0);
    private static ArrayList<Shape> shapes = new ArrayList();
    private static ArrayList<Shape> deleted = new ArrayList();

    private Point a;
    private boolean makeSquare = false, makeCircle = false, makeSquiggle = false;

    public static void main(String[] args) {
        SMYS01 window = new SMYS01();

    }
    //good main

    //0 is empty for making things, 1 is having a square selected to change, 2 is background;

    private JButton makeSquareB = new JButton("New Square" /*, add icon later*/);

    private JButton makeCircleB = new JButton("New Circle");

    private Color background = new Color(0, 150, 0);



    public SMYS01() {
        makeSquareB.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("making square");
                if(!makeCircle&&!makeSquare){
                    makeSquare = true;

                    shapes.ensureCapacity(shapes.size());
                    shapes.add(new Square((int) a.getX(), (int) a.getY(), c));
                }else if(makeSquare){

                }else if(makeCircle){
                    makeCircle=false;
                    makeSquare=true;
                    shapes.remove(shapes.size()-1);
                    shapes.ensureCapacity(shapes.size());
                    shapes.add(new Square((int) a.getX(), (int) a.getY(), c));
                }
            }
        });


        makeCircleB.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("making circle");
                if(!makeCircle&&!makeSquare){
                    makeCircle = true;
                    shapes.ensureCapacity(shapes.size());
                    shapes.add(new Circle((int) a.getX(), (int) a.getY(), c));
                }else if(makeCircle){

                }else if(makeSquare){
                    makeSquare=false;
                    shapes.remove(shapes.size()-1);
                    shapes.ensureCapacity(shapes.size());
                    shapes.add(new Circle((int) a.getX(), (int) a.getY(), c));
                }
            }
        });
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane();
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        MyPanel thing = new MyPanel();


        frame.addMouseListener(new FrameListener());
        frame.setContentPane(thing);

        frame.setSize(thing.getPreferredSize());

        frame.setTitle("Art!");

        frame.addMouseMotionListener(new FrameListener());
    }


    private class MyPanel extends JPanel {

        public MyPanel() {

            GroupLayout layout = new GroupLayout(this);
            layout.setHorizontalGroup(
                    layout.createSequentialGroup()
                    .addComponent(makeCircleB)
                    .addComponent(makeSquareB)
            );
            layout.setVerticalGroup(
                    layout.createSequentialGroup()
                    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                            .addComponent(makeCircleB)
                            .addComponent(makeSquareB)
                    )
            );

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 500);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(background);
            g.drawRect((int)g.getClipBounds().getX(),(int)g.getClipBounds().getY(),(int)g.getClipBounds().getWidth(),(int)g.getClipBounds().getHeight());
            g.fillRect((int)g.getClipBounds().getX(),(int)g.getClipBounds().getY(),(int)g.getClipBounds().getWidth(),(int)g.getClipBounds().getHeight());


            System.out.println(shapes.size());
            for (Shape i : shapes) {

                int[] a = i.getDim();
                g.setColor(new Color(a[4], a[5], a[6], a[7]));

                if(i instanceof Square){
                    g.drawRect(a[0], a[1], a[2], a[3]);
                    g.fillRect(a[0], a[1], a[2], a[3]);
                }else if(i instanceof Circle){
                    g.drawOval(a[0], a[1], a[2], a[3]);
                    g.fillOval(a[0], a[1], a[2], a[3]);
                }

            }

        }
    }


    class FrameListener implements MouseListener, MouseMotionListener {


        public void mousePressed(MouseEvent e) {
            System.out.println("pressed");
            a = new Point(e.getPoint());
            if (makeSquare) {
                makeSquare = false;
                System.out.println("square made!");
            }
            if (makeCircle) {
                makeCircle = false;
                System.out.println("cirlce made!");
            }

            //use this for sliders, nothing else. 

        }

        public void mouseReleased(MouseEvent e) {
            System.out.println("released");
            a = new Point(e.getPoint());
            //use for sliders, nothing else.

        }

        public void mouseClicked(MouseEvent e) {
            System.out.println("clicked");
            a = new Point(e.getPoint());
            //don't need this
            //makeSquare = false;
            //makeCircle = false;

            //makeSquiggle too.
        }

        public void mouseMoved(MouseEvent e) {

            //showing up as false atm
            a = new Point(e.getPoint());
            System.out.println(a);
            if (makeSquare||makeCircle) {
                Shape b = shapes.get(shapes.size()-1);
                b.updateLocation((int) a.getX(), (int) a.getY());

            }


        }

        public void mouseDragged(MouseEvent e) {
            //only check if over a JSlider
        }

        //complete methods:
        public void mouseEntered(MouseEvent e) {
            System.out.println("entered");
            //nothing, Mouse re-entering doesn't effect the program. 
        }

        public void mouseExited(MouseEvent e) {
            System.out.println("exited");
            makeSquare = false;
            makeCircle = false;
            makeSquiggle = false;
            //if mouse leaves the window while trying to make one of these, stop it. 

        }
    }



}

Shape接口的代码:

package smys01;

public interface Shape {
    public void updateLocation(int newXPos, int newYPos);
    public void updateDimensions(int newXDim, int newYDim);
    public void delete();
    public void purge();
    public void restore();
    public int[] getDim();
}

广场代码: 注意!这段代码写了一些,并且有一些部分根本不相关甚至完整(但完全未使用)。这适用于构造函数,updateDimensions()方法和updateLocation()方法

package smys01;
import java.awt.Color;
public class Square implements Shape{
    //tbr=to be returned.
    boolean deleted=false;
    boolean purged=false;
    private int xPos, yPos, xDim, yDim;
    private int saveXPos, saveYPos, saveXDim, saveYDim, saveR, saveG, saveB, saveA;
    private Color fill;
    public Square(int initX, int initY, Color a){
        xPos=initX;
        yPos=initY;
        xDim=50;
        yDim=50;
        fill=a;
    }
    public void updateDimensions(int newXDim, int newYDim){
        if(purged||deleted)
            return;
        if(newXDim<=2){
            xDim=2;
        }else{
            xDim=newXDim;
        }
        if(newYDim<=2){
            yDim=2;
        }else{
            yDim=newYDim;
        }

    }
    public void updateLocation(int newXPos, int newYPos){
        if(purged){
            return;
        }
        if(newXPos<=5){
            xPos=5;


        }else{
            xPos=newXPos;

        }
        if(newYPos<=25){
            yPos=25;
        }else{
            yPos=newYPos;
        }


                }
        public void delete(){
        if(!deleted){
            saveXPos=xPos;
            saveYPos=yPos;
            saveXDim=xDim;
            saveYDim=yDim;
            saveR=fill.getRed();
            saveB=fill.getBlue();
            saveG=fill.getGreen();
            saveA=fill.getAlpha();
            deleted=true;
            xPos=-5;
            yPos=-5;
            xDim=1;
            yDim=1;
                        }
    }
    public void purge(){
        saveXPos=-10;
        saveYPos=-10;
        saveXDim=3;
        saveYDim=3;
        //use in an if statement, and if true (will be, set the square value to null, so this reference will go away, preventing data overflow
    }
    public void restore(){
        xPos=saveXPos;
        yPos=saveYPos;
        xDim=saveXDim;
        yDim=saveYDim;
        deleted=false;
    }
    public int[] getDim(){
        int[] tbr={xPos,yPos, xDim, yDim,fill.getRed(), fill.getBlue(), fill.getGreen(), fill.getAlpha()};
        return tbr;
    }
    public String toString(){
        String tbr="Square: ("+xPos+", "+yPos+"); ("+xDim+", "+yDim+"); ("+fill.toString();
        return tbr;
    }

}

Circle类的代码完全相同,但对象类型允许paintComponent方法区分它们。

我试图在调用mouseMoved时调用paintComponent,但是我似乎无法做到这一点。我尝试过使用repaint(),我已经找了几个小时试图解决这个问题。

到目前为止,我已经看到,基本上,Swing会在需要时调用paintComponent(当窗口大小改变时,或者窗口被最小化并重新打开)。

但是,我不确定如何在按下按钮或移动鼠标时调用它,并且repaint()将无法正常工作。

我道歉,如果有些代码很草率,我已经重写了几次,有些部分是不必要的,但仍然存在。

有没有办法从匿名操作类或FrameListener类中主动调用paintComponent方法?

1 个答案:

答案 0 :(得分:1)

经过@MadProgrammer的一些输入后,我发现了什么不起作用。 mouseListener附加到JFrame而不是JPanel,因此事件被触发,但paintComponent(通过repaint())不是。我将它添加到面板并将repaint()添加到mouseMoved()方法的末尾,它运行正常。