M11 Java Paint App Session 4
Aaron Hernandez Jimenez
12 jun 2025
Group 131
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.border.TitledBorder;
public class PaintApp extends JFrame {
private DrawingPanel drawingPanel;
private JPanel toolPanel;
private JPanel colorPanel;
private JPanel fillColorPanel;
private JPanel epicPanel;
private JLabel strokeColorDisplay;
private JLabel fillColorDisplay;
private ButtonGroup toolGroup;
private Color currentColor = Color.BLACK;
private Color fillColor = Color.RED;
private Color backgroundColor = Color.WHITE;
private String currentTool = "PENCIL";
private int brushSize = 2;
private int strokeWidth = 2;
private boolean rainbowMode = false;
private Random random = new Random();
// Colores épicos expandidos
private final Color[] colors = {
Color.BLACK, Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW,
Color.ORANGE, Color.PINK, Color.CYAN, Color.MAGENTA,
Color.GRAY,
new Color(255, 20, 147), // Deep Pink
new Color(138, 43, 226), // Blue Violet
new Color(50, 205, 50), // Lime Green
new Color(255, 215, 0), // Gold
new Color(220, 20, 60) // Crimson
};
public PaintApp() {
setTitle(" 🚀 PAINT APP🎨");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
initializeComponents();
setupLayout();
setSize(1000, 700);
setLocationRelativeTo(null);
setVisible(true);
// Easter egg: mensaje épico al iniciar
showEpicWelcome();
}
private void showEpicWelcome() {
Timer timer = new Timer(1000, e -> {
JOptionPane.showMessageDialog(this,
"🎉 ¡Bienvenido al PAINT APP 🎉\n" +
"🌈 Modo Arcoíris disponible\n" +
"✨ Efectos de partículas activados\n" +
"🎯 Formas automáticas implementadas\n" +
"💫 ¡Prepárate para crear arte!",
"¡MODO ÉPICO ACTIVADO!",
JOptionPane.INFORMATION_MESSAGE);
});
timer.setRepeats(false);
timer.start();
}
private void initializeComponents() {
drawingPanel = new DrawingPanel();
toolPanel = new JPanel();
toolPanel.setLayout(new FlowLayout());
toolPanel.setBackground(new Color(70, 70, 70));
toolPanel.setBorder(new TitledBorder(" 🛠️ HERRAMIENTAS"));
colorPanel = new JPanel();
colorPanel.setLayout(new FlowLayout());
colorPanel.setBackground(new Color(50, 50, 50));
colorPanel.setBorder(new TitledBorder(" 🎨 STROKE COLOR"));
fillColorPanel = new JPanel();
fillColorPanel.setLayout(new FlowLayout());
fillColorPanel.setBackground(new Color(60, 60, 60));
fillColorPanel.setBorder(new TitledBorder(" 🎨 FILL COLOR"));
epicPanel = new JPanel();
epicPanel.setLayout(new FlowLayout());
epicPanel.setBackground(new Color(30, 30, 30));
epicPanel.setBorder(new TitledBorder(" ✨ FUNCIONES"));
createToolButtons();
createColorButtons();
createFillColorButtons();
createColorDisplays();
createEpicFeatures();
}
private void createToolButtons() {
toolGroup = new ButtonGroup();
// Herramientas básicas con iconos
addIconToolButton("✏", "Lápiz", "PENCIL", true);
addIconToolButton("▭", "Rectángulo", "RECTANGLE", false);
addIconToolButton("○", "Óvalo", "OVAL", false);
addIconToolButton("⌫", "Borrador", "ERASER", false);
// ¡NUEVAS HERRAMIENTAS ÉPICAS!
addIconToolButton("★", "Estrella", "STAR", false);
addIconToolButton("♥", "Corazón", "HEART", false);
addIconToolButton(" ⚡", "Rayo", "LIGHTNING", false);
addIconToolButton("◉", "Espiral", "SPIRAL", false);
// Botón Clear épico
JButton clearBtn = new JButton(" 🗑️ BORRAR TODO");
clearBtn.setBackground(Color.RED);
clearBtn.setForeground(Color.WHITE);
clearBtn.setFont(new Font("Arial", Font.BOLD, 12));
clearBtn.addActionListener(e -> {
int result = JOptionPane.showConfirmDialog(this,
⚠️ ¿Estás SEGURO de que quieres borrar tu OBRA
"
MAESTRA JAJJAJA?",
"¡CONFIRMACIÓN!",
JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
drawingPanel.clearCanvas();
JOptionPane.showMessageDialog(this, " 💥 ¡CANVAS DESTRUIDO!
Listo para una nueva creación 🎨");
}
});
toolPanel.add(clearBtn);
}
private void addIconToolButton(String icon, String name, String tool,
boolean selected) {
JToggleButton btn = new JToggleButton(icon);
btn.setSelected(selected);
btn.setBackground(selected ? new Color(70, 130, 180) : new
Color(100, 100, 100));
btn.setForeground(Color.WHITE);
btn.setFont(new Font("Dialog", Font.BOLD, 18));
btn.setToolTipText(name);
btn.setPreferredSize(new Dimension(50, 45));
btn.setFocusPainted(false);
btn.setBorder(BorderFactory.createRaisedBevelBorder());
btn.setHorizontalTextPosition(SwingConstants.CENTER);
btn.setVerticalTextPosition(SwingConstants.CENTER);
// Add action listener
btn.addActionListener(e -> {
currentTool = tool;
// Update button colors for visual feedback
for (AbstractButton button :
java.util.Collections.list(toolGroup.getElements())) {
button.setBackground(new Color(100, 100, 100));
}
btn.setBackground(new Color(70, 130, 180));
});
toolGroup.add(btn);
toolPanel.add(btn);
}
private void createColorButtons() {
for (Color color : colors) {
JButton colorBtn = new JButton();
colorBtn.setBackground(color);
colorBtn.setPreferredSize(new Dimension(35, 35));
colorBtn.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
currentColor = color;
rainbowMode = false;
updateStrokeColorDisplay();
}
}
});
colorBtn.setBorder(BorderFactory.createRaisedBevelBorder());
colorBtn.setToolTipText("Left click for stroke color: " +
getColorName(color));
colorPanel.add(colorBtn);
}
}
private void createFillColorButtons() {
for (Color color : colors) {
JButton colorBtn = new JButton();
colorBtn.setBackground(color);
colorBtn.setPreferredSize(new Dimension(35, 35));
colorBtn.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
fillColor = color;
updateFillColorDisplay();
}
}
});
colorBtn.setBorder(BorderFactory.createRaisedBevelBorder());
colorBtn.setToolTipText("Right click for fill color: " +
getColorName(color));
fillColorPanel.add(colorBtn);
}
}
private void createColorDisplays() {
// Stroke color display
strokeColorDisplay = new JLabel(" ");
strokeColorDisplay.setOpaque(true);
strokeColorDisplay.setBackground(currentColor);
strokeColorDisplay.setPreferredSize(new Dimension(50, 30));
strokeColorDisplay.setBorder(BorderFactory.createTitledBorder("Current
Stroke"));
colorPanel.add(strokeColorDisplay);
// Fill color display
fillColorDisplay = new JLabel(" ");
fillColorDisplay.setOpaque(true);
fillColorDisplay.setBackground(fillColor);
fillColorDisplay.setPreferredSize(new Dimension(50, 30));
fillColorDisplay.setBorder(BorderFactory.createTitledBorder("Current
Fill"));
fillColorPanel.add(fillColorDisplay);
}
private void updateStrokeColorDisplay() {
if (strokeColorDisplay != null) {
strokeColorDisplay.setBackground(currentColor);
strokeColorDisplay.repaint();
}
}
private void updateFillColorDisplay() {
if (fillColorDisplay != null) {
fillColorDisplay.setBackground(fillColor);
fillColorDisplay.repaint();
}
}
private void createEpicFeatures() {
// MODO ARCOÍRIS ÉPICO
JToggleButton rainbowBtn = new JToggleButton(" 🌈 MODO ARCOÍRIS");
rainbowBtn.setBackground(new Color(255, 20, 147));
rainbowBtn.setForeground(Color.WHITE);
rainbowBtn.setFont(new Font("Arial", Font.BOLD, 11));
rainbowBtn.addActionListener(e -> {
rainbowMode = rainbowBtn.isSelected();
if (rainbowMode) {
JOptionPane.showMessageDialog(this,
🌈 ¡MODO ARCOÍRIS ACTIVADO! Cada trazo será de un
"
color diferente 🎨");
}
});
epicPanel.add(rainbowBtn);
// CONTROL DE TAMAÑO DE PINCEL ÉPICO
JLabel sizeLabel = new JLabel(" 📏 Brush:");
sizeLabel.setForeground(Color.WHITE);
epicPanel.add(sizeLabel);
JSlider sizeSlider = new JSlider(1, 20, 2);
sizeSlider.addChangeListener(e -> brushSize =
sizeSlider.getValue());
sizeSlider.setBackground(new Color(30, 30, 30));
epicPanel.add(sizeSlider);
// CONTROL DE GROSOR DE TRAZO
JLabel strokeLabel = new JLabel(" 🖊️ Stroke:");
strokeLabel.setForeground(Color.WHITE);
epicPanel.add(strokeLabel);
JSlider strokeSlider = new JSlider(1, 15, 2);
strokeSlider.addChangeListener(e -> strokeWidth =
strokeSlider.getValue());
strokeSlider.setBackground(new Color(30, 30, 30));
epicPanel.add(strokeSlider);
// BOTÓN DE EFECTOS ESPECIALES
JButton effectsBtn = new JButton(" ✨ EFECTOS MÁGICOS");
effectsBtn.setBackground(new Color(138, 43, 226));
effectsBtn.setForeground(Color.WHITE);
effectsBtn.setFont(new Font("Arial", Font.BOLD, 11));
effectsBtn.addActionListener(e -> drawingPanel.addMagicEffects());
epicPanel.add(effectsBtn);
// BOTÓN RANDOM ART
JButton randomBtn = new JButton(" 🎲 ARTE RANDOM");
randomBtn.setBackground(new Color(255, 140, 0));
randomBtn.setForeground(Color.WHITE);
randomBtn.setFont(new Font("Arial", Font.BOLD, 11));
randomBtn.addActionListener(e ->
drawingPanel.generateRandomArt());
epicPanel.add(randomBtn);
}
private String getColorName(Color color) {
if (color.equals(Color.BLACK))
return "Negro Absoluto";
if (color.equals(Color.RED))
return "Rojo Fuego";
if (color.equals(Color.BLUE))
return "Azul Océano";
if (color.equals(Color.GREEN))
return "Verde Naturaleza";
return "Color Épico";
}
private void setupLayout() {
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(toolPanel, BorderLayout.NORTH);
JPanel colorPanels = new JPanel(new BorderLayout());
colorPanels.add(colorPanel, BorderLayout.NORTH);
colorPanels.add(fillColorPanel, BorderLayout.CENTER);
topPanel.add(colorPanels, BorderLayout.CENTER);
topPanel.add(epicPanel, BorderLayout.SOUTH);
add(topPanel, BorderLayout.NORTH);
add(new JScrollPane(drawingPanel), BorderLayout.CENTER);
// Panel de estado épico
JLabel statusLabel = new JLabel(" 🎨 Listo para crear ARTE |
Herramienta: Lápiz | Modo: Normal");
statusLabel.setOpaque(true);
statusLabel.setBackground(new Color(20, 20, 20));
statusLabel.setForeground(Color.CYAN);
statusLabel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5,
10));
add(statusLabel, BorderLayout.SOUTH);
}
private class DrawingPanel extends JPanel {
private BufferedImage canvas;
private Graphics2D g2d;
private Point startPoint;
private Point endPoint;
private boolean isDrawing = false;
private int colorHue = 0;
public DrawingPanel() {
setPreferredSize(new Dimension(800, 600));
setBackground(backgroundColor);
canvas = new BufferedImage(800, 600,
BufferedImage.TYPE_INT_RGB);
g2d = canvas.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(backgroundColor);
g2d.fillRect(0, 0, 800, 600);
addMouseListeners();
}
private void addMouseListeners() {
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
startPoint = e.getPoint();
isDrawing = true;
if (currentTool.equals("PENCIL") ||
currentTool.equals("ERASER")) {
drawPoint(e.getPoint());
repaint();
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (isDrawing && SwingUtilities.isLeftMouseButton(e))
{
endPoint = e.getPoint();
switch (currentTool) {
case "RECTANGLE":
drawRectangle();
break;
case "OVAL":
drawOval();
break;
case "STAR":
drawStar(); // ¡ÉPICO!
break;
case "HEART":
drawHeart(); // ¡SÚPER ÉPICO!
break;
case "LIGHTNING":
drawLightning(); // ¡MEGA ÉPICO!
break;
case "SPIRAL":
drawSpiral(); // ¡ULTRA ÉPICO!
break;
}
isDrawing = false;
repaint();
}
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (isDrawing && SwingUtilities.isLeftMouseButton(e)
&& (currentTool.equals("PENCIL") ||
currentTool.equals("ERASER"))) {
drawLine(startPoint, e.getPoint());
startPoint = e.getPoint();
repaint();
}
}
});
}
private Color getRainbowColor() {
colorHue = (colorHue + 5) % 360;
return Color.getHSBColor(colorHue / 360.0f, 1.0f, 1.0f);
}
private void drawPoint(Point point) {
Color drawColor = currentTool.equals("ERASER") ?
backgroundColor
: (rainbowMode ? getRainbowColor() : currentColor);
g2d.setColor(drawColor);
int size = currentTool.equals("ERASER") ? brushSize :
strokeWidth;
g2d.setStroke(new BasicStroke(size, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND));
g2d.fillOval(point.x - size / 2, point.y - size / 2, size,
size);
}
private void drawLine(Point start, Point end) {
Color drawColor = currentTool.equals("ERASER") ?
backgroundColor
: (rainbowMode ? getRainbowColor() : currentColor);
g2d.setColor(drawColor);
int size = currentTool.equals("ERASER") ? brushSize :
strokeWidth;
g2d.setStroke(new BasicStroke(size, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND));
g2d.drawLine(start.x, start.y, end.x, end.y);
}
private void drawRectangle() {
int x = Math.min(startPoint.x, endPoint.x);
int y = Math.min(startPoint.y, endPoint.y);
int width = Math.abs(endPoint.x - startPoint.x);
int height = Math.abs(endPoint.y - startPoint.y);
// Fill the rectangle with fill color
g2d.setColor(fillColor);
g2d.fillRect(x, y, width, height);
// Draw the outline with stroke color
g2d.setColor(rainbowMode ? getRainbowColor() : currentColor);
g2d.setStroke(new BasicStroke(strokeWidth));
g2d.drawRect(x, y, width, height);
}
private void drawOval() {
int x = Math.min(startPoint.x, endPoint.x);
int y = Math.min(startPoint.y, endPoint.y);
int width = Math.abs(endPoint.x - startPoint.x);
int height = Math.abs(endPoint.y - startPoint.y);
// Fill the oval with fill color
g2d.setColor(fillColor);
g2d.fillOval(x, y, width, height);
// Draw the outline with stroke color
g2d.setColor(rainbowMode ? getRainbowColor() : currentColor);
g2d.setStroke(new BasicStroke(strokeWidth));
g2d.drawOval(x, y, width, height);
}
// ¡FUNCIONES ÉPICAS NUEVAS!
private void drawStar() {
int centerX = (startPoint.x + endPoint.x) / 2;
int centerY = (startPoint.y + endPoint.y) / 2;
int radius = Math.abs(endPoint.x - startPoint.x) / 2;
int[] xPoints = new int[10];
int[] yPoints = new int[10];
for (int i = 0; i < 10; i++) {
double angle = Math.PI * i / 5.0;
int r = (i % 2 == 0) ? radius : radius / 2;
xPoints[i] = (int) (centerX + r * Math.cos(angle - Math.PI
/ 2));
yPoints[i] = (int) (centerY + r * Math.sin(angle - Math.PI
/ 2));
}
// Fill the star with fill color
g2d.setColor(fillColor);
g2d.fillPolygon(xPoints, yPoints, 10);
// Draw the outline with stroke color
g2d.setColor(rainbowMode ? getRainbowColor() : currentColor);
g2d.setStroke(new BasicStroke(strokeWidth));
g2d.drawPolygon(xPoints, yPoints, 10);
}
private void drawHeart() {
g2d.setColor(Color.RED); // Los corazones siempre rojos ❤️
g2d.setStroke(new BasicStroke(strokeWidth));
int width = Math.abs(endPoint.x - startPoint.x);
int height = Math.abs(endPoint.y - startPoint.y);
int x = Math.min(startPoint.x, endPoint.x);
int y = Math.min(startPoint.y, endPoint.y);
// Dibujar corazón con curvas
g2d.drawArc(x, y, width / 2, height / 2, 0, 180);
g2d.drawArc(x + width / 2, y, width / 2, height / 2, 0, 180);
g2d.drawLine(x, y + height / 4, x + width / 2, y + height);
g2d.drawLine(x + width, y + height / 4, x + width / 2, y +
height);
}
private void drawLightning() {
g2d.setColor(Color.YELLOW); // Rayos amarillos ⚡
g2d.setStroke(new BasicStroke(strokeWidth + 2));
int[] xPoints = { startPoint.x, startPoint.x + 20,
startPoint.x - 5, endPoint.x, endPoint.x - 20,
endPoint.x + 5 };
int[] yPoints = { startPoint.y, startPoint.y + 30,
startPoint.y + 40, endPoint.y, endPoint.y - 30,
endPoint.y - 40 };
g2d.drawPolyline(xPoints, yPoints, 6);
}
private void drawSpiral() {
g2d.setColor(rainbowMode ? getRainbowColor() : currentColor);
g2d.setStroke(new BasicStroke(strokeWidth));
int centerX = (startPoint.x + endPoint.x) / 2;
int centerY = (startPoint.y + endPoint.y) / 2;
int maxRadius = Math.abs(endPoint.x - startPoint.x) / 2;
Point lastPoint = new Point(centerX, centerY);
for (double angle = 0; angle < 6 * Math.PI; angle += 0.1) {
double radius = (angle / (6 * Math.PI)) * maxRadius;
int x = (int) (centerX + radius * Math.cos(angle));
int y = (int) (centerY + radius * Math.sin(angle));
if (rainbowMode)
g2d.setColor(getRainbowColor());
g2d.drawLine(lastPoint.x, lastPoint.y, x, y);
lastPoint = new Point(x, y);
}
}
// ¡EFECTOS MÁGICOS ÉPICOS!
public void addMagicEffects() {
for (int i = 0; i < 50; i++) {
int x = random.nextInt(getWidth());
int y = random.nextInt(getHeight());
Color sparkleColor = new Color(random.nextInt(256),
random.nextInt(256), random.nextInt(256));
g2d.setColor(sparkleColor);
g2d.fillOval(x, y, 3, 3);
// Añadir pequeñas estrellas
g2d.drawLine(x - 5, y, x + 5, y);
g2d.drawLine(x, y - 5, x, y + 5);
}
repaint();
JOptionPane.showMessageDialog(PaintApp.this, " ✨ ¡EFECTOS
MÁGICOS APLICADOS! Tu canvas ahora brilla ✨");
}
// ¡GENERADOR DE ARTE RANDOM ÉPICO!
public void generateRandomArt() {
for (int i = 0; i < 20; i++) {
g2d.setColor(new Color(random.nextInt(256),
random.nextInt(256), random.nextInt(256)));
g2d.setStroke(new BasicStroke(random.nextInt(10) + 1));
int shape = random.nextInt(4);
int x = random.nextInt(getWidth() - 100);
int y = random.nextInt(getHeight() - 100);
int size = random.nextInt(100) + 20;
switch (shape) {
case 0:
g2d.drawRect(x, y, size, size);
break;
case 1:
g2d.drawOval(x, y, size, size);
break;
case 2:
g2d.drawLine(x, y, x + size, y + size);
break;
case 3:
g2d.fillOval(x, y, size / 2, size / 2);
break;
}
}
repaint();
JOptionPane.showMessageDialog(PaintApp.this, " 🎲 ¡ARTE RANDOM
GENERADO! 🎨");
}
public void clearCanvas() {
g2d.setColor(backgroundColor);
g2d.fillRect(0, 0, getWidth(), getHeight());
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(canvas, 0, 0, null);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new PaintApp());
}
}