我是Java的新手,至于我班级的最终项目,我正在开发一个绘图应用程序,使用户能够绘制丰富的曲线和常见的几何形状,如矩形和椭圆形,用户也可以撤消它们的形状绘图。
我的应用程序在形状绘制方面表现良好。当我想绘制形状时,我想要绘制的形状存储在LinkedList中,将被调用以在屏幕上绘制形状当我应用此LinkedList概念在屏幕上绘制曲线时。我修改了形状绘制代码来绘制曲线。我碰到了一个问题;我得到的结果是little dots on the screen.如果我试图复制类似的代码来绘制绘制曲线的形状,我会得到直线而不是曲线。
我认为这个问题与MouseListener接口有关。我需要一些关于如何修改MouseListener方法的建议,以便我可以正确地在屏幕上绘制曲线。
欢迎更改我的源代码:
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PaintAppPlusSecondDraft extends JApplet implements ActionListener {
private static final long serialVersionUID = 1L;
private JMenuBar menuBar = new JMenuBar();
private JMenu mainMenu = new JMenu("Main menu");
private JMenuItem howToUse = new JMenuItem("How to use?");
private JMenuItem toDefaultMode = new JMenuItem("Return to default mode");
private JMenu boardSettings = new JMenu("Paint board settings");
private JMenuItem clearBoard = new JMenuItem("Clear screen");
private JMenuItem toDefaultBoard = new JMenuItem("Set to default paint board");
private JMenuItem bCustom = new JMenuItem("Set background colour");
private JMenu brushSettings = new JMenu("Paintbrush settings");
private JMenuItem eraser = new JMenuItem("Eraser");
private JMenuItem toDefaultBrush = new JMenuItem("Set to default paintbrush");
private JMenu setBrushSize = new JMenu("Set paintbrush size");
private JMenuItem Two = new JMenuItem("2 pixels");
private JMenuItem Four = new JMenuItem("4 pixels");
private JMenuItem Six = new JMenuItem("6 pixels");
private JMenuItem Eight = new JMenuItem("8 pixels");
private JMenuItem Ten = new JMenuItem("10 pixels");
private JMenu setBrushType = new JMenu("Set paintbrush type");
private JMenuItem defaultType1 = new JMenuItem("Default");
private JMenuItem defaultType2 = new JMenuItem("Default (light stroke)");
private JMenuItem Custom = new JMenuItem("Set paintbrush colour");
private JMenu drawShapes = new JMenu("Draw shapes");
private JMenuItem undoShape = new JMenuItem("Undo shape drawing");
private JMenuItem StraightLine = new JMenuItem("Straight line");
private JMenuItem Rectangle = new JMenuItem("Rectangle");
private JMenuItem Oval = new JMenuItem("Oval");
private JMenuItem filledRectangle = new JMenuItem("Filled rectangle");
private JMenuItem filledOval = new JMenuItem("Filled oval");
private int prevBrushSize = PaintBoard.brushSize;
private int prevBrushType = PaintBoard.brushType;
private Color prevBrushColour = PaintBoard.currentColour; /* For better user experience */
public void init() {
Frame frame = (Frame) getParent().getParent();
frame.setTitle("JAVA Paint plus");
frame.setResizable(false);
this.setSize(600, 400);
this.setContentPane(new PaintBoard());
mainMenu.add(howToUse);
mainMenu.add(toDefaultMode);
mainMenu.add(about);
boardSettings.add(clearBoard);
boardSettings.add(toDefaultBoard);
boardSettings.add(bCustom);
brushSettings.add(eraser);
brushSettings.add(toDefaultBrush);
setBrushSize.add(Two);
setBrushSize.add(Four);
setBrushSize.add(Six);
setBrushSize.add(Eight);
setBrushSize.add(Ten);
brushSettings.add(setBrushSize);
setBrushType.add(defaultType1);
setBrushType.add(defaultType2);
setBrushType.add(waterColourBrush);
setBrushType.add(triangleType);
setBrushType.add(squareType);
setBrushType.add(hexagonType);
setBrushType.add(starType);
setBrushType.add(heartType);
brushSettings.add(setBrushType);
brushSettings.add(Custom);
drawShapes.add(undoShape);
drawShapes.add(StraightLine);
drawShapes.add(Rectangle);
drawShapes.add(Oval);
drawShapes.add(filledRectangle);
drawShapes.add(filledOval);
menuBar.add(mainMenu);
menuBar.add(boardSettings);
menuBar.add(brushSettings);
menuBar.add(drawShapes);
howToUse.addActionListener(this);
toDefaultMode.addActionListener(this);
clearBoard.addActionListener(this);
toDefaultBoard.addActionListener(this);
bCustom.addActionListener(this);
eraser.addActionListener(this);
toDefaultBrush.addActionListener(this);
Two.addActionListener(this);
Four.addActionListener(this);
Six.addActionListener(this);
Eight.addActionListener(this);
Ten.addActionListener(this);
defaultType1.addActionListener(this);
defaultType2.addActionListener(this);
Custom.addActionListener(this);
undoShape.addActionListener(this);
StraightLine.addActionListener(this);
Rectangle.addActionListener(this);
Oval.addActionListener(this);
filledRectangle.addActionListener(this);
filledOval.addActionListener(this);
this.setJMenuBar(menuBar);
this.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == howToUse) {
JOptionPane.showMessageDialog(null, "Press your mouse on the board and drag to draw!", "How to use?", JOptionPane.INFORMATION_MESSAGE);
}
if (e.getSource() == toDefaultMode) {
PaintBoard.canvasColour = Color.WHITE;
PaintBoard.brushSize = prevBrushSize = 6;
PaintBoard.brushType = prevBrushType = 1;
PaintBoard.currentColour = prevBrushColour = Color.BLACK;
PaintBoard.shapes.makeEmpty();
repaint();
}
if (e.getSource() == clearBoard) {
PaintBoard.shapes.makeEmpty();
repaint();
}
if (e.getSource() == toDefaultBoard) {
PaintBoard.canvasColour = Color.WHITE;
repaint();
}
if (e.getSource() == bCustom) {
try {
Color customColour = JColorChooser.showDialog(null, "Select colour:", PaintBoard.canvasColour);
PaintBoard.canvasColour = customColour;
PaintBoard.shapes.makeEmpty();
repaint();
} catch (NullPointerException ex) {
}
}
if (e.getSource() == eraser) {
prevBrushSize = PaintBoard.brushSize;
prevBrushType = PaintBoard.brushType;
prevBrushColour = PaintBoard.currentColour;
PaintBoard.brushSize = 44;
PaintBoard.brushType = 1;
PaintBoard.currentColour = PaintBoard.canvasColour;
}
if (e.getSource() == toDefaultBrush) {
PaintBoard.brushSize = prevBrushSize = 6;
PaintBoard.brushType = prevBrushType = 1;
PaintBoard.currentColour = prevBrushColour = Color.BLACK;
}
if (e.getSource() == Two) {
PaintBoard.brushSize = prevBrushSize = 2;
PaintBoard.brushType = prevBrushType;
PaintBoard.currentColour = prevBrushColour;
}
if (e.getSource() == Four) {
PaintBoard.brushSize = prevBrushSize = 4;
PaintBoard.brushType = prevBrushType;
PaintBoard.currentColour = prevBrushColour;
}
if (e.getSource() == Six) {
PaintBoard.brushSize = prevBrushSize = 6;
PaintBoard.brushType = prevBrushType;
PaintBoard.currentColour = prevBrushColour;
}
if (e.getSource() == Eight) {
PaintBoard.brushSize = prevBrushSize = 8;
PaintBoard.brushType = prevBrushType;
PaintBoard.currentColour = prevBrushColour;
}
if (e.getSource() == Ten) {
PaintBoard.brushSize = prevBrushSize = 10;
PaintBoard.brushType = prevBrushType;
PaintBoard.currentColour = prevBrushColour;
}
if (e.getSource() == defaultType1) {
PaintBoard.brushSize = prevBrushSize;
PaintBoard.brushType = prevBrushType = 1;
PaintBoard.currentColour = prevBrushColour;
}
if (e.getSource() == defaultType2) {
PaintBoard.brushSize = prevBrushSize;
PaintBoard.brushType = prevBrushType = 2;
PaintBoard.currentColour = prevBrushColour;
}
if (e.getSource() == Custom) {
try {
Color customColour = JColorChooser.showDialog(null, "Select colour:", PaintBoard.currentColour);
PaintBoard.brushSize = prevBrushSize;
PaintBoard.brushType = prevBrushType;
PaintBoard.currentColour = prevBrushColour = customColour;
} catch (NullPointerException ex) {
}
}
if (e.getSource() == undoShape) {
try {
PaintBoard.shapes.removeFront();
repaint();
} catch (NullPointerException ex) {
}
}
if (e.getSource() == StraightLine) {
PaintBoard.brushSize = prevBrushSize;
PaintBoard.currentColour = prevBrushColour;
PaintBoard.shapeType = 1;
}
if (e.getSource() == Rectangle) {
PaintBoard.currentColour = prevBrushColour;
PaintBoard.shapeType = 2;
PaintBoard.filled = false;
}
if (e.getSource() == Oval) {
PaintBoard.currentColour = prevBrushColour;
PaintBoard.shapeType = 3;
PaintBoard.filled = false;
}
if (e.getSource() == filledRectangle) {
PaintBoard.currentColour = prevBrushColour;
PaintBoard.shapeType = 2;
PaintBoard.filled = true;
}
if (e.getSource() == filledOval) {
PaintBoard.currentColour = prevBrushColour;
PaintBoard.shapeType = 3;
PaintBoard.filled = true;
}
}
abstract static class brushLine {
private int brushSize;
private int brushType;
private Color brushColour;
public brushLine() {
brushSize = 6;
brushType = 1;
brushColour = Color.BLACK;
}
public brushLine(int brushSize, int brushType, Color brushColour) {
this.brushSize = brushSize;
this.brushType = brushType;
this.brushColour = brushColour;
}
public void setBrushSize(int brushSize) {
this.brushSize = brushSize;
}
public void setBrushType(int brushType) {
this.brushType = brushType;
}
public void setBrushColour(Color brushColour) {
this.brushColour = brushColour;
}
public int getBrushSize() {
return brushSize;
}
public int getBrushType() {
return brushType;
}
public Color getBrushColour() {
return brushColour;
}
abstract void show(Graphics window);
}
static class paintBrushLine extends brushLine {
private int x1, y1, x2, y2;
public paintBrushLine() {
super();
x1 = 0;
y1 = 0;
x2 = 0;
y2 = 0;
}
public paintBrushLine(int brushSize, int brushType, Color brushColour, int x1, int y1, int x2, int y2) {
super(brushSize, brushType, brushColour);
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public void setX1(int x1) {
this.x1 = x1;
}
public void setY1(int y1) {
this.y1 = y1;
}
public void setX2(int x2) {
this.x2 = x2;
}
public void setY2(int y2) {
this.y2 = y2;
}
public int getX1() {
return x1;
}
public int getY1() {
return y1;
}
public int getX2() {
return x2;
}
public int getY2() {
return y2;
}
public void show(Graphics window) {
window.setColor(getBrushColour());
switch (getBrushType()) {
case 1://Default brush
((Graphics2D) window).setStroke(new BasicStroke(getBrushSize(), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
window.drawLine(getX1(), getY1(), getX2(), getY2());
break;
case 2://Default brush (light stroke) --> Makes empty squares with few randomly positioned pixels
int[] pixelPos = new int[2];
for (int i = 0; i < ((getBrushSize()*getBrushSize()) / 10); i++) {
pixelPos[0] = new Random().nextInt(getBrushSize());
pixelPos[1] = new Random().nextInt(getBrushSize());
window.drawRect(getX1() + pixelPos[0], getY1() + pixelPos[1], 1, 1);
}
break;
}
}
}
abstract static class Shape {
private int x1, y1, x2, y2;
private int thickness;
private Color shapeColour;
public Shape() {
x1 = 0;
y1 = 0;
x2 = 0;
y2 = 0;
shapeColour = Color.BLACK;
}
public Shape(int x1, int y1, int x2, int y2, int thickness, Color shapeColour)
{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.thickness = thickness;
this.shapeColour = shapeColour;
}
public void setX1(int x1) {
this.x1 = x1;
}
public void setY1(int y1) {
this.y1 = y1;
}
public void setX2(int x2) {
this.x2 = x2;
}
public void setY2(int y2) {
this.y2 = y2;
}
public void setThickness(int thickness) {
this.thickness = thickness;
}
public void setShapeColour(Color shapeColour) {
this.shapeColour = shapeColour;
}
public int getX1() {
return x1;
}
public int getY1() {
return y1;
}
public int getX2() {
return x2;
}
public int getY2() {
return y2;
}
public int getThickness() {
return thickness;
}
public Color getShapeColour() {
return shapeColour;
}
abstract void sketch(Graphics window);
}
abstract static class boundedShape extends Shape {
private int shapeType;
private boolean filled;
public boundedShape() {
super();
filled = false;
}
public boundedShape(int x1, int y1, int x2, int y2, int thickness, Color shapeColour, int shapeType, boolean filled) {
super(x1, y1, x2, y2, thickness, shapeColour);
this.shapeType = shapeType;
this.filled = filled;
}
public void setShapeType(int shapeType) {
this.shapeType = shapeType;
}
public void setFilled(boolean filled) {
this.filled = filled;
}
public int getUpperLeftX() {
return Math.min(getX1(), getX2());
}
public int getUpperLeftY() {
return Math.min(getY1(), getY2());
}
public int getWidth() {
return Math.abs(getX1() - getX2());
}
public int getHeight() {
return Math.abs(getY1() - getY2());
}
public int getShapeType() {
return shapeType;
}
public boolean getFilled() {
return filled;
}
abstract public void sketch(Graphics window);
}
static class geometricShape extends boundedShape {
public geometricShape() {
super();
}
public geometricShape(int x1, int y1, int x2, int y2, int thickness, Color shapeColour, int shapeType, boolean filled) {
super(x1, y1, x2, y2, thickness, shapeColour, shapeType, filled);
}
public void sketch(Graphics window) {
window.setColor(getShapeColour());
switch(getShapeType()) {
case 1://Straight line
((Graphics2D) window).setStroke(new BasicStroke(getThickness(), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
window.drawLine(getX1(), getY1(), getX2(), getY2());
break;
case 2://Rectangle
if (getFilled())
window.fillRect(getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight());
else {
((Graphics2D) window).setStroke(new BasicStroke(getThickness(), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
window.drawRect(getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight());
}
break;
case 3://Oval
if (getFilled())
window.fillOval(getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight());
else {
((Graphics2D) window).setStroke(new BasicStroke(getThickness(), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
window.drawOval(getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight());
}
break;
}
}
}
static class PaintBoard extends JPanel implements MouseMotionListener, MouseListener {
private static final long serialVersionUID = 1L;
private boolean painting;
private int prevX, prevY;
private static Color canvasColour = Color.WHITE;
private static int brushSize = 6;
private static int brushType = 1;
private static Color currentColour = Color.BLACK;
private static LinkedList<brushLine> brushLines = new LinkedList<>();
private brushLine currentBrushLine;
private static LinkedList<Shape> shapes = new LinkedList<>();
private static int shapeType = 0;
private Shape currentShape = null;
private static boolean filled;
private JLabel mouseCoordinates = new JLabel("X: 0 pixels Y: 0 pixels");
public PaintBoard() {
setSize(getWidth(), getHeight());
setLayout(new BorderLayout());
add(mouseCoordinates, BorderLayout.SOUTH);
addMouseMotionListener(this);
addMouseListener(this);
}
@Override
public void paintComponent(Graphics board) {
super.paintComponent(board);
board.setColor(canvasColour);
board.fillRect(0, 0, getWidth(), getHeight());
ArrayList<brushLine> linesToDraw = brushLines.getArray();
for (int i = linesToDraw.size() - 1; i >= 0; i--)
linesToDraw.get(i).show(board);
if (currentBrushLine != null)
currentBrushLine.show(board);
ArrayList<Shape> shapesToDraw = shapes.getArray();
for (int j = shapesToDraw.size() - 1; j >= 0; j--)
shapesToDraw.get(j).sketch(board);
if (currentShape != null)
currentShape.sketch(board);
}
public void mouseDragged(MouseEvent e) {
mouseCoordinates.setText(String.format("X: %d pixels Y: %d pixels", e.getX(), e.getY()));
if (shapeType > 0) {
currentShape.setX2(e.getX());
currentShape.setY2(e.getY());
repaint();
} else {
if (!painting)
return;
((paintBrushLine) currentBrushLine).setX1(prevX);
((paintBrushLine) currentBrushLine).setY1(prevY);
((paintBrushLine) currentBrushLine).setX2(e.getX());
((paintBrushLine) currentBrushLine).setY2(e.getY());
repaint();
prevX = e.getX();
prevY = e.getY();
}
}
public void mouseMoved(MouseEvent e) {
mouseCoordinates.setText(String.format("X: %d pixels Y: %d pixels", e.getX(), e.getY()));
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
switch (shapeType) {
case 0://Curved line
if (painting)
return;
prevX = e.getX();
prevY = e.getY();
currentBrushLine = new paintBrushLine(brushSize, brushType, currentColour, prevX, prevY, prevX, prevY);
painting = true;
break;
default://Other shapes
currentShape = new geometricShape(e.getX(), e.getY(), e.getX(), e.getY(), brushSize, currentColour, shapeType, filled);
painting = false;
break;
}
}
public void mouseReleased(MouseEvent e) {
if (shapeType > 0) {
currentShape.setX2(e.getX());
currentShape.setY2(e.getY());
shapes.addFront(currentShape);
currentShape = null;
shapeType = 0;
repaint();
} else {
if (!painting)
return;
((paintBrushLine) currentBrushLine).setX2(e.getX());
((paintBrushLine) currentBrushLine).setY2(e.getY());
brushLines.addFront(currentBrushLine);
currentBrushLine = null;
painting = false;
repaint();
}
}
}
}
LinkedList类:
import java.util.ArrayList;
class LinkedList<T> {
private int numberOfNodes = 0;
private ListNode<T> front = null;
// Returns true if the linked list has no nodes, or false otherwise.
public boolean isEmpty() {
return (front == null);
}
// Deletes all of the nodes in the linked list.
// Note: ListNode objects will be automatically garbage collected by JVM.
public void makeEmpty() {
front = null;
numberOfNodes = 0;
}
// Returns the number of nodes in the linked list
public int size() {
return numberOfNodes;
}
// Adds a node to the front of the linked list.
public void addFront( T element ) {
front = new ListNode<T>( element, front );
numberOfNodes++;
}
// Returns a reference to the data in the first node, or null if the list is empty.
public T peek() {
if (isEmpty())
return null;
return front.getData();
}
// Removes a node from the front of the linked list (if there is one).
// Returns a reference to the data in the first node, or null if the list is empty.
@SuppressWarnings("unchecked")
public T removeFront() {
T tempData;
if (isEmpty())
return null;
tempData = front.getData();
front = front.getNext();
numberOfNodes--;
return tempData;
}
@SuppressWarnings("unchecked")
public void removeEnd(T element) {
ListNode<T> node=front;
while(node.getNext() != null)
{
node = node.getNext();
}
node.setNext(new ListNode<T>((T)element, null));
}
// Return array filled with T objects
@SuppressWarnings("unchecked")
public ArrayList<T> getArray() {
ArrayList<T> shapeArray=new ArrayList<T>();
ListNode<T> node=front;
while (node!=null)
{
shapeArray.add(node.getData());
node = node.getNext();
}
return shapeArray;
}
}
ListNode类:
public class ListNode<T> {
private T data;
private ListNode next;
// Constructor: No reference to next node provided so make it null
public ListNode( T nodeData ) {
this( nodeData, null);
}
// Constructor: Set data and reference to next node.
public ListNode( T nodeData, ListNode nodeNext ) {
data = nodeData;
next = nodeNext;
}
// Accessor: Return the data for current ListNode object
public T getData() {
return data;
}
// Accessor: Return reference to next ListNode object
public ListNode getNext() {
return next;
}
// Mutator: Set new data for current ListNode object
public void setData( T newData ) {
data = newData;
}
// Mutator: Set new reference to the next node object
public void setNext( ListNode newNext ) {
next = newNext;
}
}
答案 0 :(得分:0)
您的形状和线条都只存储起点和终点。
abstract static class Shape {
private int x1, y1, x2, y2;
private int thickness;
private Color shapeColour;
那么你的绘画方法怎么知道怎么做?当它只知道两点时,它如何绘制曲线?
您需要做什么:
一旦你完成了形状,你需要做一些数学计算,根据前一个和下一个段的坐标计算出每个弧的半径和坐标,然后在你的绘画方法中,你可以画很多很小的线条使它看起来很光滑。
另外,添加一些调试代码以找出您的绘制方法使用的值,您可能会发现只看到点或小线的原因是因为每个形状/线的值未正确存储。