在一个JPanel检测鼠标点击并防止圆从画中的JPanel问题(Problems with dete

2019-10-22 21:33发布

我现在的程序可以让用户通过按压在JFrame的底部JPanel中呈现的颜色之一移动一圈JFrame中,并改变其颜色。

我的代码:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.border.Border;
import javax.swing.BorderFactory;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.FlowLayout;
import java.awt.BorderLayout;
import java.awt.GridLayout;

public class SixthProgram
{
    public static void main(String[] args)
    {
        GUI prog=new GUI("SixthProgram");
        prog.setBounds(350,250,500,250);
        prog.setVisible(true);
    }
}

class GUI extends JFrame implements MouseListener, MouseMotionListener
{
    JButton button;
    JPanel colorPan, color1, color2, color3 ,color4 ,color5;
    Color color=Color.BLACK;

    int x=3,y=30;

    public GUI(String header)
    {
        super(header);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        maker();

        addMouseListener(this);
        addMouseMotionListener(this);

        add(colorPan, BorderLayout.SOUTH);
    }

    public void maker()
    {
        colorPan = new JPanel();

        Border raisedbevel = BorderFactory.createRaisedBevelBorder();
        Border loweredbevel = BorderFactory.createLoweredBevelBorder();
        Border compound = BorderFactory.createCompoundBorder(raisedbevel, loweredbevel);
        colorPan.setBorder(compound);

        colorPan.setLayout(new GridLayout(1, 0));

        color1 = new JPanel();
        color2 = new JPanel();
        color3 = new JPanel();
        color4 = new JPanel();
        color5 = new JPanel();

        color1.setBackground(Color.WHITE);
        color2.setBackground(Color.GREEN);
        color3.setBackground(Color.RED);
        color4.setBackground(Color.BLUE);
        color5.setBackground(Color.BLACK);

        colorPan.add(color1);
        colorPan.add(color2);
        colorPan.add(color3);
        colorPan.add(color4);
        colorPan.add(color5);

    }

    @Override
    public void paint(Graphics g)
    {
        //g.setColor(Color.WHITE);
        //g.fillRect(0,0,getWidth(),getHeight());
        super.paint(g); //Do the same thing as above(Clear jframe)

        g.setColor(color);
        g.fillOval(x,y,50,50);
    }

    public void mouseExited(MouseEvent e) //MouseListener overrided methods
    {}

    public void mouseEntered(MouseEvent e)
    {}

    public void mouseReleased(MouseEvent e)
    {}

    public void mousePressed(MouseEvent e)
    {
        System.out.println("Press");    
        if(e.getX()+50 < getWidth() && e.getY()+50 < getHeight()) // Preventing out of bounds
        {
            x=e.getX();
            y=e.getY();
            repaint();
        }
    }

    public void mouseClicked(MouseEvent e) //Press+Release=Click
    {
        System.out.println("Click");
        if((e.getX()>=8 && e.getX()<=105) && (e.getY()>=232 && e.getY()<=243))
            color=Color.WHITE;
        else if((e.getX()>=106 && e.getX()<=203) && (e.getY()>=232 && e.getY()<=243))
            color=Color.GREEN;
        else if((e.getX()>=204 && e.getX()<=301) && (e.getY()>=232 && e.getY()<=243))
            color=Color.RED;
        else if((e.getX()>=302 && e.getX()<=399) && (e.getY()>=232 && e.getY()<=243))
            color=Color.BLUE;
        else if((e.getX()>=400 && e.getX()<=489) && (e.getY()>=232 && e.getY()<=243))
            color=Color.BLACK;
        repaint();
    }

    public void mouseDragged(MouseEvent e) //MouseMotionListener overrided methods
    {
        System.out.println("Dragged to ("+ e.getX() +","+ e.getY() +")");
        if((e.getX()>=3 && e.getY()>=30) && (e.getX()+50<getWidth() && e.getY()+50<getHeight())) //If circle is dragged in the JFrame
        {
            x=e.getX();
            y=e.getY();
            repaint();
        }
    }

    public void mouseMoved(MouseEvent e)
    {}

}

上面的代码按预期方式工作,并产生输出:

当我点击的JPanel中的颜色太底层了,程序将按预期并改变圆圈的颜色。

出现的两个问题是:

  1. 当我调整的JFrame,如预期颜色选择器不工作。 这是因为我在硬编码的笨方法mouseClicked方法:

     public void mouseClicked(MouseEvent e) //Press+Release=Click { System.out.println("Click"); if((e.getX()>=8 && e.getX()<=105) && (e.getY()>=232 && e.getY()<=243)) color=Color.WHITE; else if((e.getX()>=106 && e.getX()<=203) && (e.getY()>=232 && e.getY()<=243)) color=Color.GREEN; else if((e.getX()>=204 && e.getX()<=301) && (e.getY()>=232 && e.getY()<=243)) color=Color.RED; else if((e.getX()>=302 && e.getX()<=399) && (e.getY()>=232 && e.getY()<=243)) color=Color.BLUE; else if((e.getX()>=400 && e.getX()<=489) && (e.getY()>=232 && e.getY()<=243)) color=Color.BLACK; repaint(); } 
  2. 第二个问题是,该圆可以被拖动到颜色选择。 我不知道我应该为了防止这种事情。 我可以硬编码就像我的问题#1的值,但是这会造成同样的问题,因为问题#1。

我宁愿不使用setResizable(false)和JFrame中要调整大小。

如何解决上述问题?

Answer 1:

我刚刚重新以更好的方式来实现你的问题。 下面是它的外观像现在存在的问题都解决了。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class CirclePainter implements MouseMotionListener, ActionListener {
    private JFrame mainFrame;
    private JPanel colorPanel, circlePanel;
    private JButton whiteColorButton, redColorButton, greenColorButton,
            blueColorButton;

    private int circleWidth = 3, circleHeight = 15;
    private Color circleColor = Color.black;

    public CirclePainter() {
        initGui();
    }

    public void initGui() {
        mainFrame = new JFrame("Circle");
        mainFrame.setLayout(new BorderLayout());
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.setSize(500, 400);

        colorPanel = new JPanel(new FlowLayout());

        whiteColorButton = new JButton();
        whiteColorButton.setBackground(Color.white);
        whiteColorButton.setActionCommand("white");
        whiteColorButton.addActionListener(this);
        redColorButton = new JButton();
        redColorButton.setBackground(Color.red);
        redColorButton.setActionCommand("red");
        redColorButton.addActionListener(this);
        greenColorButton = new JButton();
        greenColorButton.setBackground(Color.green);
        greenColorButton.setActionCommand("green");
        greenColorButton.addActionListener(this);
        blueColorButton = new JButton();
        blueColorButton.setBackground(Color.blue);
        blueColorButton.setActionCommand("blue");
        blueColorButton.addActionListener(this);

        colorPanel.add(whiteColorButton);
        colorPanel.add(redColorButton);
        colorPanel.add(greenColorButton);
        colorPanel.add(blueColorButton);

        circlePanel = new JPanel() {
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(circleColor);
                g.fillOval(circleWidth, circleHeight, 50, 50);
            }
        };
        circlePanel.addMouseMotionListener(this);
        circlePanel.setBackground(Color.yellow);
        mainFrame.add(circlePanel, BorderLayout.CENTER);

        mainFrame.add(colorPanel, BorderLayout.PAGE_END);
        mainFrame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        switch (e.getActionCommand()) {
        case "white":
            circleColor = Color.white;
            circlePanel.repaint();
            break;
        case "red":
            circleColor = Color.red;
            circlePanel.repaint();
            break;
        case "green":
            circleColor = Color.green;
            circlePanel.repaint();
            break;
        case "blue":
            circleColor = Color.blue;
            circlePanel.repaint();
            break;
        default:
            break;
        }
    }

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

    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if ((e.getX() >= 0 && e.getY() >= 0)
                && (e.getX() <= mainFrame.getWidth() - 60)
                && (e.getY() <= mainFrame.getHeight() - 110)) {
            circleWidth = e.getX();
            circleHeight = e.getY();
            circlePanel.repaint();
        }

    }

    @Override
    public void mouseMoved(MouseEvent arg0) {

    }

}

下面是输出:



Answer 2:

你不应该重写一个JFrame的paint()方法。 风俗画是通过覆盖一个JPanel(或JComponent中)的的paintComponent()方法,然后将面板添加到框架完成。 你会这个面板中添加使用框架BorderLayout.CENTER

对于你的颜色,你应该创建一个单独的面板和按钮添加到面板来表示每个颜色。 您将每个按钮的背景设置为特定的颜色。 你可以使用一个网格布局。 然后你这个面板添加到BorderLayout.PAGE_END框架。

然后,而不是使用的MouseListener你的添加ActionListener到每个按钮。 基本的代码如下:

public void actionPerformed(ActionEvent e)
{
    JButton button = (JButton)e.getSource();
    color = button.getBackground();
    repaint();
}


文章来源: Problems with detecting mouseClick in a JPanel and preventing circle from painting in JPanel