问题描述
我有一个项目,我需要在 Java 中创建一个 GUI,该 GUI 在鼠标单击时创建一个圆圈,并在鼠标拖过框架时继续制作尾随圆圈。我已经在这里参考了多个线程,但似乎没有一个能帮助我做我需要做的事情。到目前为止,我已经在 JFrame 中添加了一个静态圆,但我想让多个圆显示在该框架中的 JPanel 上。在尝试了许多不同的角度后,我被困住了。截至目前,我只需要能够点击一次并创建一个圆圈。
public class Theremin extends JFrame implements ActionListener,MouseListener{
private JPanel windowArea;
private int x,y;
private static final long serialVersionUID = 1L;
public Theremin() {
}
public static void main(String[] args) {
Theremin Frame = new Theremin();
Frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
MyPanel panel = new MyPanel();
panel.setLayout(null);
Frame.add(panel);
Frame.pack();
Frame.setLocationRelativeto(null);
Frame.setVisible(true);
}
private static class MyPanel extends JPanel {
public void paint(Graphics g) {
Graphics2D gObj = (Graphics2D)g;
Shape disk = new Ellipse2D.Double(10,10,100,100);
gObj.setColor(new Color(255,120));
gObj.fill(disk);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(700,600);
}
}
@Override
public void actionPerformed(ActionEvent e) {
// Todo Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
@Override
public void mousepressed(MouseEvent e) {
// Todo Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// Todo Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// Todo Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// Todo Auto-generated method stub
}
}
解决方法
这是我拼凑的图形用户界面。
每次鼠标点击都会创建一个圆圈。
当我创建 Swing GUI 或任何 Java 应用程序时,我使用 model / view / controller (MVC) 模式。这种模式使我能够将我的关注点分开,并一次专注于应用程序的一个部分。
对于 Swing GUI,MVC 模式意味着:
- 视图从模型中读取。
- 视图不会更新模型。
- 控制器更新模型并重新绘制/重新验证视图。
该模型由两个类组成,Circles
和 Circle
。 Circle
类定义了一个圆心为 Point
、半径为 int
和颜色为 Color
的圆。因为 Circle
是一个类,所以我可以定义任意数量的实例(圆圈)。
Circles
类拥有 List
个 Circle
实例。
视图由 JFrame
和绘图 JPanel
组成。绘图 paintComponent
的 JPanel
方法绘制圆圈。时期。我们在控制器类中创建圆圈。
控制器类 CirclesListener
创建圆圈并重新绘制绘图 JPanel
。每次重新绘制绘图 JPanel
时,都会重新绘制所有圆圈。
JFrame
类和应用程序模型类的实例被传递给控制器 CirclesListener
类。这允许类创建一个新圆并重新绘制绘图 JPanel
。
这是完整的可运行代码。
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MouseClickCircleGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new MouseClickCircleGUI());
}
private Circles circles;
private DrawingPanel drawingPanel;
public MouseClickCircleGUI() {
this.circles = new Circles();
}
@Override
public void run() {
JFrame frame = new JFrame("Circles");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawingPanel = new DrawingPanel(this,circles);
frame.add(drawingPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public void repaint() {
drawingPanel.repaint();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final Circles circles;
public DrawingPanel(MouseClickCircleGUI frame,Circles circles) {
this.circles = circles;
setBackground(Color.WHITE);
setPreferredSize(new Dimension(500,500));
addMouseListener(new CirclesListener(frame,circles));
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(3f));
for (Circle circle : circles.getCircles()) {
Point p = circle.getCenter();
int radius = circle.getRadius();
g2.setColor(circle.getColor());
g2.drawOval(p.x - radius,p.y - radius,2 * radius,2 * radius);
}
}
}
public class CirclesListener extends MouseAdapter {
private final Circles circles;
private final MouseClickCircleGUI frame;
public CirclesListener(MouseClickCircleGUI frame,Circles circles) {
this.frame = frame;
this.circles = circles;
}
@Override
public void mouseReleased(MouseEvent event) {
circles.addCircle(new Circle(event.getPoint(),30,Color.BLACK));
frame.repaint();
}
}
public class Circles {
private final List<Circle> circles;
public Circles() {
this.circles = new ArrayList<>();
}
public void addCircle(Circle circle) {
this.circles.add(circle);
}
public List<Circle> getCircles() {
return circles;
}
}
public class Circle {
private final int radius;
private final Color color;
private final Point center;
public Circle(Point center,int radius,Color color) {
this.center = center;
this.radius = radius;
this.color = color;
}
public int getRadius() {
return radius;
}
public Point getCenter() {
return center;
}
public Color getColor() {
return color;
}
}
}
,
这里的想法是:
- 捕获点
- 将其添加到列表中
- 重绘组件
这是我的做法,这是一个示例代码。
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
Theremin frame = new Theremin();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyPanel panel = new MyPanel();
panel.initListeners();
panel.setLayout(null);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
panel.releaseListener();
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
}
}
class MyPanel extends JPanel implements MouseListener,MouseMotionListener {
private Graphics graphics;
private List<CircleData> shapeList = new ArrayList<>();
private Graphics2D gObj;
public MyPanel() {
}
@Override
public void paint(Graphics g) {
this.graphics = g;
gObj = (Graphics2D) g;
System.out.println("called paint with times: " + times++);
for (CircleData circleData : shapeList) {
Rectangle rectangle = circleData.rectangle;
Color color = circleData.color;
Shape disk = new Ellipse2D.Double(rectangle.x,rectangle.y,rectangle.width,rectangle.height);
gObj.setColor(color);
gObj.fill(disk);
}
}
Color randomColor() {
int red = (int) (Math.random() * 256);
int green = (int) (Math.random() * 256);
int blue = (int) (Math.random() * 256);
return new Color(red,green,blue);
}
static int times = 0;
@Override
public Dimension getPreferredSize() {
return new Dimension(700,600);
}
public void initListeners() {
System.out.println("added default listeners");
addMouseListener(this);
addMouseMotionListener(this);
}
public void releaseListener() {
System.out.println("removed default listeners");
removeMouseListener(this);
removeMouseMotionListener(this);
}
@Override
public void mouseClicked(MouseEvent e) {
float x = e.getX();
float y = e.getY();
String cordinates = String.format("(%f,%f)",x,y);
System.out.println("Mouse Clicked @ " + cordinates);
shapeList.add(new CircleData(new Rectangle((int) x,(int) y,50,50),randomColor()));
repaint();
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
float x = e.getX();
float y = e.getY();
String cordinates = String.format("(%f,y);
System.out.println("Mouse Dragged @ " + cordinates);
System.out.println("Mouse Dragged @ " + shapeList.size());
shapeList.add(new CircleData(new Rectangle((int) x,randomColor()));
repaint();
}
@Override
public void mouseMoved(MouseEvent e) {
}
}
class CircleData {
Rectangle rectangle;
Color color;
public CircleData(Rectangle rectangle,Color color) {
this.rectangle = rectangle;
this.color = color;
}
}
class Theremin extends JFrame {
private static final long serialVersionUID = 1L;
public Theremin() {
}
}