This commit is contained in:
18
eventapp/nb-configuration.xml
Normal file
18
eventapp/nb-configuration.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project-shared-configuration>
|
||||||
|
<!--
|
||||||
|
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||||
|
The configuration is intended to be shared among all the users of project and
|
||||||
|
therefore it is assumed to be part of version control checkout.
|
||||||
|
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||||
|
-->
|
||||||
|
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||||
|
<!--
|
||||||
|
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||||
|
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||||
|
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||||
|
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||||
|
-->
|
||||||
|
<netbeans.hint.jdkPlatform>JDK_25</netbeans.hint.jdkPlatform>
|
||||||
|
</properties>
|
||||||
|
</project-shared-configuration>
|
||||||
55
eventapp/nbactions.xml
Normal file
55
eventapp/nbactions.xml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<actions>
|
||||||
|
<action>
|
||||||
|
<actionName>run</actionName>
|
||||||
|
<packagings>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
</packagings>
|
||||||
|
<goals>
|
||||||
|
<goal>process-classes</goal>
|
||||||
|
<goal>org.codehaus.mojo:exec-maven-plugin:3.1.0:exec</goal>
|
||||||
|
</goals>
|
||||||
|
<properties>
|
||||||
|
<exec.vmArgs></exec.vmArgs>
|
||||||
|
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
|
||||||
|
<exec.appArgs></exec.appArgs>
|
||||||
|
<exec.mainClass>com.mycompany.eventapp.Eventapp</exec.mainClass>
|
||||||
|
<exec.executable>java</exec.executable>
|
||||||
|
</properties>
|
||||||
|
</action>
|
||||||
|
<action>
|
||||||
|
<actionName>debug</actionName>
|
||||||
|
<packagings>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
</packagings>
|
||||||
|
<goals>
|
||||||
|
<goal>process-classes</goal>
|
||||||
|
<goal>org.codehaus.mojo:exec-maven-plugin:3.1.0:exec</goal>
|
||||||
|
</goals>
|
||||||
|
<properties>
|
||||||
|
<exec.vmArgs>-agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}</exec.vmArgs>
|
||||||
|
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
|
||||||
|
<exec.appArgs></exec.appArgs>
|
||||||
|
<exec.mainClass>com.mycompany.eventapp.Eventapp</exec.mainClass>
|
||||||
|
<exec.executable>java</exec.executable>
|
||||||
|
<jpda.listen>true</jpda.listen>
|
||||||
|
</properties>
|
||||||
|
</action>
|
||||||
|
<action>
|
||||||
|
<actionName>profile</actionName>
|
||||||
|
<packagings>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
</packagings>
|
||||||
|
<goals>
|
||||||
|
<goal>process-classes</goal>
|
||||||
|
<goal>org.codehaus.mojo:exec-maven-plugin:3.1.0:exec</goal>
|
||||||
|
</goals>
|
||||||
|
<properties>
|
||||||
|
<exec.vmArgs></exec.vmArgs>
|
||||||
|
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
|
||||||
|
<exec.mainClass>com.mycompany.eventapp.Eventapp</exec.mainClass>
|
||||||
|
<exec.executable>java</exec.executable>
|
||||||
|
<exec.appArgs></exec.appArgs>
|
||||||
|
</properties>
|
||||||
|
</action>
|
||||||
|
</actions>
|
||||||
13
eventapp/pom.xml
Normal file
13
eventapp/pom.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.mycompany</groupId>
|
||||||
|
<artifactId>eventapp</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.release>25</maven.compiler.release>
|
||||||
|
<exec.mainClass>com.mycompany.eventapp.Eventappa</exec.mainClass>
|
||||||
|
</properties>
|
||||||
|
</project>
|
||||||
25
eventapp/src/main/java/com/mycompany/eventapp/Eventapp.java
Normal file
25
eventapp/src/main/java/com/mycompany/eventapp/Eventapp.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
package com.mycompany.eventapp;
|
||||||
|
|
||||||
|
import controlador.Controlador;
|
||||||
|
import modelo.Modelo;
|
||||||
|
import vista.Vista;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class Eventapp
|
||||||
|
{
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
// Buenas prácticas: iniciar Swing en el EDT
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
Modelo modelo = new Modelo();
|
||||||
|
Vista vista = new Vista();
|
||||||
|
new Controlador(modelo, vista).iniciar(); // cableado MVC
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
312
eventapp/src/main/java/controlador/Controlador.java
Normal file
312
eventapp/src/main/java/controlador/Controlador.java
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||||||
|
*/
|
||||||
|
package controlador;
|
||||||
|
|
||||||
|
import modelo.Modelo;
|
||||||
|
import vista.DialogoNombre;
|
||||||
|
import vista.Vista;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CONTROLADOR:
|
||||||
|
* - Registra listeners sobre la Vista.
|
||||||
|
* - Llama al Modelo y actualiza la Vista según corresponda.
|
||||||
|
* - Contiene toda la lógica de interacción.
|
||||||
|
*/
|
||||||
|
public class Controlador implements
|
||||||
|
ActionListener, ItemListener, ChangeListener,
|
||||||
|
KeyListener, MouseListener, MouseMotionListener,
|
||||||
|
WindowListener, ListSelectionListener, PropertyChangeListener {
|
||||||
|
|
||||||
|
private final Modelo modelo;
|
||||||
|
private final Vista vista;
|
||||||
|
|
||||||
|
// Para el área de dibujo
|
||||||
|
private Point ultimoPunto = null;
|
||||||
|
|
||||||
|
public Controlador(Modelo modelo, Vista vista) {
|
||||||
|
this.modelo = modelo;
|
||||||
|
this.vista = vista;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void iniciar() {
|
||||||
|
// === Suscripción a eventos de VISTA ===
|
||||||
|
|
||||||
|
// Menú
|
||||||
|
vista.getMiNuevo().addActionListener(this);
|
||||||
|
vista.getMiSalir().addActionListener(this);
|
||||||
|
|
||||||
|
// Botones
|
||||||
|
vista.getBtnMas().addActionListener(this);
|
||||||
|
vista.getBtnMenos().addActionListener(this);
|
||||||
|
vista.getBtnAdd().addActionListener(this);
|
||||||
|
vista.getBtnRemove().addActionListener(this);
|
||||||
|
vista.getBtnTareaLarga().addActionListener(this);
|
||||||
|
|
||||||
|
// ItemListener (checkbox y combobox)
|
||||||
|
vista.getChkHabilitarTexto().addItemListener(this);
|
||||||
|
vista.getCboOpciones().addItemListener(this);
|
||||||
|
|
||||||
|
// Slider (ChangeListener)
|
||||||
|
vista.getSldValor().addChangeListener(this);
|
||||||
|
|
||||||
|
// DocumentListener para cambios en texto de nombre
|
||||||
|
vista.addNombreDocumentListener(new DocumentListener() {
|
||||||
|
@Override public void insertUpdate(DocumentEvent e) { actualizarNombreDesdeVista(); }
|
||||||
|
@Override public void removeUpdate(DocumentEvent e) { actualizarNombreDesdeVista(); }
|
||||||
|
@Override public void changedUpdate(DocumentEvent e) { actualizarNombreDesdeVista(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Teclado sobre el canvas
|
||||||
|
vista.getCanvas().setFocusable(true);
|
||||||
|
vista.getCanvas().addKeyListener(this);
|
||||||
|
|
||||||
|
// Ratón sobre el canvas
|
||||||
|
vista.getCanvas().addMouseListener(this);
|
||||||
|
vista.getCanvas().addMouseMotionListener(this);
|
||||||
|
|
||||||
|
// Selección en la lista
|
||||||
|
vista.getLstElementos().addListSelectionListener(this);
|
||||||
|
|
||||||
|
// Cambio de pestañas
|
||||||
|
vista.getTabs().addChangeListener(this);
|
||||||
|
|
||||||
|
// WindowListener
|
||||||
|
vista.addWindowListener(this);
|
||||||
|
|
||||||
|
// === Suscripción a cambios del MODELO ===
|
||||||
|
modelo.addPropertyChangeListener(this);
|
||||||
|
|
||||||
|
// Pinta estado inicial
|
||||||
|
vista.getLblContador().setText(String.valueOf(modelo.getContador()));
|
||||||
|
vista.getLblHora().setText(modelo.getHora());
|
||||||
|
vista.getListModel().clear();
|
||||||
|
modelo.getElementos().forEach(vista.getListModel()::addElement);
|
||||||
|
|
||||||
|
// Mostrar la ventana al final
|
||||||
|
vista.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== ActionListener ==================
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
Object src = e.getSource();
|
||||||
|
|
||||||
|
if (src == vista.getBtnMas()) {
|
||||||
|
modelo.incrementar();
|
||||||
|
vista.getLblEstado().setText("Se incrementó el contador.");
|
||||||
|
} else if (src == vista.getBtnMenos()) {
|
||||||
|
modelo.decrementar();
|
||||||
|
vista.getLblEstado().setText("Se decrementó el contador.");
|
||||||
|
} else if (src == vista.getBtnAdd()) {
|
||||||
|
String txt = vista.getTxtNuevo().getText().trim();
|
||||||
|
if (!txt.isEmpty()) {
|
||||||
|
modelo.addElemento(txt);
|
||||||
|
vista.getTxtNuevo().setText("");
|
||||||
|
vista.getLblEstado().setText("Elemento añadido.");
|
||||||
|
}
|
||||||
|
} else if (src == vista.getBtnRemove()) {
|
||||||
|
int idx = vista.getLstElementos().getSelectedIndex();
|
||||||
|
modelo.removeElemento(idx);
|
||||||
|
vista.getLblEstado().setText("Elemento eliminado (si había selección).");
|
||||||
|
} else if (src == vista.getMiNuevo()) {
|
||||||
|
// Abrimos un diálogo modal controlado desde el controlador
|
||||||
|
DialogoNombre dlg = new DialogoNombre(vista);
|
||||||
|
// Listeners del diálogo
|
||||||
|
dlg.getBtnOk().addActionListener(ev -> {
|
||||||
|
modelo.setNombre(dlg.getTxt().getText());
|
||||||
|
dlg.dispose();
|
||||||
|
});
|
||||||
|
dlg.getBtnCancel().addActionListener(ev -> dlg.dispose());
|
||||||
|
dlg.setVisible(true);
|
||||||
|
} else if (src == vista.getMiSalir()) {
|
||||||
|
solicitarSalida();
|
||||||
|
} else if (src == vista.getBtnTareaLarga()) {
|
||||||
|
ejecutarTareaLarga();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== ItemListener ==================
|
||||||
|
@Override
|
||||||
|
public void itemStateChanged(ItemEvent e) {
|
||||||
|
Object src = e.getSource();
|
||||||
|
|
||||||
|
if (src == vista.getChkHabilitarTexto()) {
|
||||||
|
boolean habilitar = vista.getChkHabilitarTexto().isSelected();
|
||||||
|
vista.getTxtNombre().setEnabled(habilitar);
|
||||||
|
vista.getLblEstado().setText(habilitar ? "Texto habilitado." : "Texto deshabilitado.");
|
||||||
|
} else if (src == vista.getCboOpciones() && e.getStateChange() == ItemEvent.SELECTED) {
|
||||||
|
String color = (String) vista.getCboOpciones().getSelectedItem();
|
||||||
|
vista.getLblEstado().setText("Color favorito: " + color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== ChangeListener ==================
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
Object src = e.getSource();
|
||||||
|
|
||||||
|
if (src == vista.getSldValor()) {
|
||||||
|
vista.getLblEstado().setText("Slider: " + vista.getSldValor().getValue());
|
||||||
|
} else if (src == vista.getTabs()) {
|
||||||
|
vista.getLblEstado().setText("Pestaña: " + vista.getTabs().getTitleAt(vista.getTabs().getSelectedIndex()));
|
||||||
|
// Dar foco al canvas si entramos a su pestaña para poder usar teclas
|
||||||
|
if (vista.getTabs().getSelectedComponent() == vista.getCanvas().getParent()) {
|
||||||
|
vista.getCanvas().requestFocusInWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== DocumentListener helper ==================
|
||||||
|
private void actualizarNombreDesdeVista() {
|
||||||
|
if (vista.getTxtNombre().isEnabled()) {
|
||||||
|
// Actualizamos solo la VISTA (placeholder en estado), el modelo se cambia con el diálogo o podrías sincronizar aquí
|
||||||
|
vista.getLblEstado().setText("Nombre (vista) editándose: " + vista.getTxtNombre().getText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== KeyListener (canvas) ==================
|
||||||
|
@Override public void keyTyped(KeyEvent e) {}
|
||||||
|
@Override public void keyPressed(KeyEvent e) {
|
||||||
|
// Cambiar color de fondo del canvas con teclas numéricas
|
||||||
|
switch (e.getKeyCode()) {
|
||||||
|
case KeyEvent.VK_1 -> vista.getCanvas().setBackground(Color.PINK);
|
||||||
|
case KeyEvent.VK_2 -> vista.getCanvas().setBackground(Color.LIGHT_GRAY);
|
||||||
|
case KeyEvent.VK_3 -> vista.getCanvas().setBackground(new Color(220, 240, 255));
|
||||||
|
}
|
||||||
|
vista.getLblEstado().setText("Tecla: " + KeyEvent.getKeyText(e.getKeyCode()));
|
||||||
|
}
|
||||||
|
@Override public void keyReleased(KeyEvent e) {}
|
||||||
|
|
||||||
|
// ================== MouseListener / MouseMotionListener (canvas) ==================
|
||||||
|
@Override public void mouseClicked(MouseEvent e) {
|
||||||
|
vista.getLblEstado().setText("Clic en: " + e.getPoint());
|
||||||
|
}
|
||||||
|
@Override public void mousePressed(MouseEvent e) {
|
||||||
|
ultimoPunto = e.getPoint();
|
||||||
|
}
|
||||||
|
@Override public void mouseReleased(MouseEvent e) {
|
||||||
|
ultimoPunto = null;
|
||||||
|
}
|
||||||
|
@Override public void mouseEntered(MouseEvent e) {
|
||||||
|
vista.getCanvas().requestFocusInWindow(); // Para captar teclas
|
||||||
|
}
|
||||||
|
@Override public void mouseExited(MouseEvent e) {}
|
||||||
|
|
||||||
|
@Override public void mouseDragged(MouseEvent e) {
|
||||||
|
// “Dibujar” una línea simple con borde (realmente pintamos un borde temporal usando un icono)
|
||||||
|
if (ultimoPunto != null) {
|
||||||
|
Graphics g = vista.getCanvas().getGraphics();
|
||||||
|
g.setColor(Color.DARK_GRAY);
|
||||||
|
g.drawLine(ultimoPunto.x, ultimoPunto.y, e.getX(), e.getY());
|
||||||
|
ultimoPunto = e.getPoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override public void mouseMoved(MouseEvent e) {
|
||||||
|
vista.getLblEstado().setText("Mouse: " + e.getPoint());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== WindowListener ==================
|
||||||
|
@Override public void windowOpened(WindowEvent e) {}
|
||||||
|
@Override public void windowClosing(WindowEvent e) { solicitarSalida(); }
|
||||||
|
@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) {}
|
||||||
|
|
||||||
|
private void solicitarSalida() {
|
||||||
|
int r = JOptionPane.showConfirmDialog(vista,
|
||||||
|
"¿Desea salir?", "Confirmación",
|
||||||
|
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||||
|
if (r == JOptionPane.YES_OPTION) {
|
||||||
|
vista.dispose();
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== ListSelectionListener (lista) ==================
|
||||||
|
@Override
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
if (!e.getValueIsAdjusting()) {
|
||||||
|
int idx = vista.getLstElementos().getSelectedIndex();
|
||||||
|
vista.getLblEstado().setText(idx >= 0 ? "Seleccionado índice " + idx : "Sin selección");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== PropertyChangeListener (modelo) ==================
|
||||||
|
@Override
|
||||||
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
switch (evt.getPropertyName()) {
|
||||||
|
case "contador" -> {
|
||||||
|
int valor = (int) evt.getNewValue();
|
||||||
|
vista.getLblContador().setText(String.valueOf(valor));
|
||||||
|
}
|
||||||
|
case "nombre" -> {
|
||||||
|
// Reflejamos el nombre de modelo en la vista (si está habilitado para editar)
|
||||||
|
if (!vista.getTxtNombre().isFocusOwner()) {
|
||||||
|
vista.getTxtNombre().setText((String) evt.getNewValue());
|
||||||
|
}
|
||||||
|
vista.getLblEstado().setText("Nombre (modelo) = " + evt.getNewValue());
|
||||||
|
}
|
||||||
|
case "elementos" -> {
|
||||||
|
vista.getListModel().clear();
|
||||||
|
for (String s : modelo.getElementos()) {
|
||||||
|
vista.getListModel().addElement(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "hora" -> {
|
||||||
|
vista.getLblHora().setText((String) evt.getNewValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== Ejemplo SwingWorker (tarea larga) ==================
|
||||||
|
private void ejecutarTareaLarga() {
|
||||||
|
vista.getBtnTareaLarga().setEnabled(false);
|
||||||
|
vista.getProgress().setValue(0);
|
||||||
|
vista.getLblEstado().setText("Procesando...");
|
||||||
|
|
||||||
|
SwingWorker<Void, Integer> worker = new SwingWorker<>() {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Exception {
|
||||||
|
// Simulación de trabajo (100 pasos)
|
||||||
|
for (int i = 1; i <= 100; i++) {
|
||||||
|
Thread.sleep(15); // simula carga
|
||||||
|
setProgress(i); // dispara PropertyChange "progress"
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void process(java.util.List<Integer> chunks) {
|
||||||
|
// No usamos publish() en este ejemplo, usamos progress
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
vista.getLblEstado().setText("Tarea terminada.");
|
||||||
|
vista.getBtnTareaLarga().setEnabled(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Escucha de progreso
|
||||||
|
worker.addPropertyChangeListener(evt -> {
|
||||||
|
if ("progress".equals(evt.getPropertyName())) {
|
||||||
|
int p = (int) evt.getNewValue();
|
||||||
|
vista.getProgress().setValue(p);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
worker.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
102
eventapp/src/main/java/modelo/Modelo.java
Normal file
102
eventapp/src/main/java/modelo/Modelo.java
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||||||
|
*/
|
||||||
|
package modelo;
|
||||||
|
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.beans.PropertyChangeSupport;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MODELO:
|
||||||
|
* - Mantiene el estado (contador, nombre, lista, hora).
|
||||||
|
* - Lanza eventos de cambio (PropertyChangeSupport) para notificar a la Vista/Controlador.
|
||||||
|
* - No conoce nada de Swing (salvo el Timer para ejemplo simple).
|
||||||
|
*/
|
||||||
|
public class Modelo {
|
||||||
|
|
||||||
|
private int contador = 0;
|
||||||
|
private String nombre = "Sin nombre";
|
||||||
|
private final List<String> elementos = new ArrayList<>();
|
||||||
|
|
||||||
|
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||||
|
private final Timer reloj; // actualiza propiedad "hora"
|
||||||
|
|
||||||
|
private String hora = LocalTime.now().withNano(0).toString();
|
||||||
|
|
||||||
|
public Modelo() {
|
||||||
|
// Reloj que actualiza cada segundo la propiedad "hora"
|
||||||
|
reloj = new Timer(1000, e -> {
|
||||||
|
String old = this.hora;
|
||||||
|
this.hora = LocalTime.now().withNano(0).toString();
|
||||||
|
pcs.firePropertyChange("hora", old, this.hora);
|
||||||
|
});
|
||||||
|
reloj.start();
|
||||||
|
|
||||||
|
// Datos iniciales
|
||||||
|
elementos.add("Elemento A");
|
||||||
|
elementos.add("Elemento B");
|
||||||
|
elementos.add("Elemento C");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContador() {
|
||||||
|
return contador;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incrementar() {
|
||||||
|
int old = contador;
|
||||||
|
contador++;
|
||||||
|
pcs.firePropertyChange("contador", old, contador);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decrementar() {
|
||||||
|
int old = contador;
|
||||||
|
contador--;
|
||||||
|
pcs.firePropertyChange("contador", old, contador);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNombre() {
|
||||||
|
return nombre;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNombre(String nombre) {
|
||||||
|
String old = this.nombre;
|
||||||
|
this.nombre = nombre;
|
||||||
|
pcs.firePropertyChange("nombre", old, nombre);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getElementos() {
|
||||||
|
return new ArrayList<>(elementos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addElemento(String txt) {
|
||||||
|
elementos.add(txt);
|
||||||
|
// Notificamos cambio en la lista completa para mantenerlo simple
|
||||||
|
pcs.firePropertyChange("elementos", null, getElementos());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeElemento(int index) {
|
||||||
|
if (index >= 0 && index < elementos.size()) {
|
||||||
|
elementos.remove(index);
|
||||||
|
pcs.firePropertyChange("elementos", null, getElementos());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHora() {
|
||||||
|
return hora;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||||
|
pcs.addPropertyChangeListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||||
|
pcs.removePropertyChangeListener(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
39
eventapp/src/main/java/vista/DialogoNombre.java
Normal file
39
eventapp/src/main/java/vista/DialogoNombre.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||||||
|
*/
|
||||||
|
package vista;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pequeño diálogo modal para demostrar control desde el Controlador.
|
||||||
|
*/
|
||||||
|
public class DialogoNombre extends JDialog {
|
||||||
|
|
||||||
|
private final JTextField txt = new JTextField(20);
|
||||||
|
private final JButton btnOk = new JButton("Aceptar");
|
||||||
|
private final JButton btnCancel = new JButton("Cancelar");
|
||||||
|
|
||||||
|
public DialogoNombre(JFrame owner) {
|
||||||
|
super(owner, "Cambiar nombre", true); // modal
|
||||||
|
setLayout(new BorderLayout(8,8));
|
||||||
|
JPanel center = new JPanel(new FlowLayout());
|
||||||
|
center.add(new JLabel("Nuevo nombre:"));
|
||||||
|
center.add(txt);
|
||||||
|
add(center, BorderLayout.CENTER);
|
||||||
|
JPanel south = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||||
|
south.add(btnCancel);
|
||||||
|
south.add(btnOk);
|
||||||
|
add(south, BorderLayout.SOUTH);
|
||||||
|
pack();
|
||||||
|
setLocationRelativeTo(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JTextField getTxt() { return txt; }
|
||||||
|
public JButton getBtnOk() { return btnOk; }
|
||||||
|
public JButton getBtnCancel() { return btnCancel; }
|
||||||
|
}
|
||||||
|
|
||||||
175
eventapp/src/main/java/vista/Vista.java
Normal file
175
eventapp/src/main/java/vista/Vista.java
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||||||
|
*/
|
||||||
|
package vista;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.DocumentListener;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VISTA:
|
||||||
|
* - Solo define y organiza componentes Swing.
|
||||||
|
* - Expone getters para que el Controlador se suscriba a eventos.
|
||||||
|
* - No contiene lógica de negocio.
|
||||||
|
*/
|
||||||
|
public class Vista extends JFrame {
|
||||||
|
|
||||||
|
// Menú
|
||||||
|
private final JMenuItem miNuevo = new JMenuItem("Nuevo");
|
||||||
|
private final JMenuItem miSalir = new JMenuItem("Salir");
|
||||||
|
|
||||||
|
// Panel principal con pestañas
|
||||||
|
private final JTabbedPane tabs = new JTabbedPane();
|
||||||
|
|
||||||
|
// Pestaña 1: Controles básicos
|
||||||
|
private final JButton btnMas = new JButton("+1");
|
||||||
|
private final JButton btnMenos = new JButton("-1");
|
||||||
|
private final JLabel lblContador = new JLabel("0", SwingConstants.CENTER);
|
||||||
|
private final JCheckBox chkHabilitarTexto = new JCheckBox("Habilitar texto");
|
||||||
|
private final JTextField txtNombre = new JTextField(15);
|
||||||
|
private final JComboBox<String> cboOpciones = new JComboBox<>(new String[]{"Rojo", "Verde", "Azul"});
|
||||||
|
private final JSlider sldValor = new JSlider(0, 100, 50);
|
||||||
|
|
||||||
|
// Pestaña 2: Lista y acciones
|
||||||
|
private final DefaultListModel<String> listModel = new DefaultListModel<>();
|
||||||
|
private final JList<String> lstElementos = new JList<>(listModel);
|
||||||
|
private final JButton btnAdd = new JButton("Añadir");
|
||||||
|
private final JButton btnRemove = new JButton("Eliminar");
|
||||||
|
private final JTextField txtNuevo = new JTextField(12);
|
||||||
|
|
||||||
|
// Pestaña 3: Área de dibujo simple (Mouse/Key)
|
||||||
|
private final JLabel canvas = new JLabel("Haz clic o arrastra aquí", SwingConstants.CENTER);
|
||||||
|
|
||||||
|
// Barra inferior
|
||||||
|
private final JLabel lblEstado = new JLabel("Listo.");
|
||||||
|
private final JProgressBar progress = new JProgressBar(0, 100);
|
||||||
|
private final JButton btnTareaLarga = new JButton("Tarea larga (SwingWorker)");
|
||||||
|
|
||||||
|
// Hora (propiedad enlazada del modelo)
|
||||||
|
private final JLabel lblHora = new JLabel("--:--:--");
|
||||||
|
|
||||||
|
public Vista() {
|
||||||
|
setTitle("Demo MVC + Eventos (Swing)");
|
||||||
|
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // Controlado por WindowListener
|
||||||
|
setSize(800, 600);
|
||||||
|
setLocationRelativeTo(null);
|
||||||
|
|
||||||
|
// Menú
|
||||||
|
JMenuBar mb = new JMenuBar();
|
||||||
|
JMenu menuArchivo = new JMenu("Archivo");
|
||||||
|
menuArchivo.add(miNuevo);
|
||||||
|
menuArchivo.addSeparator();
|
||||||
|
menuArchivo.add(miSalir);
|
||||||
|
mb.add(menuArchivo);
|
||||||
|
setJMenuBar(mb);
|
||||||
|
|
||||||
|
// --- Pestaña 1 ---
|
||||||
|
JPanel p1 = new JPanel(new GridBagLayout());
|
||||||
|
GridBagConstraints c = new GridBagConstraints();
|
||||||
|
c.insets = new Insets(6,6,6,6);
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
|
||||||
|
lblContador.setFont(lblContador.getFont().deriveFont(Font.BOLD, 28f));
|
||||||
|
c.gridx = 0; c.gridy = 0; c.gridwidth = 2;
|
||||||
|
p1.add(lblContador, c);
|
||||||
|
|
||||||
|
c.gridwidth = 1; c.gridy = 1; c.gridx = 0;
|
||||||
|
p1.add(btnMenos, c);
|
||||||
|
c.gridx = 1;
|
||||||
|
p1.add(btnMas, c);
|
||||||
|
|
||||||
|
c.gridy = 2; c.gridx = 0;
|
||||||
|
p1.add(new JLabel("Nombre:"), c);
|
||||||
|
c.gridx = 1;
|
||||||
|
p1.add(txtNombre, c);
|
||||||
|
|
||||||
|
c.gridy = 3; c.gridx = 0; c.gridwidth = 2;
|
||||||
|
p1.add(chkHabilitarTexto, c);
|
||||||
|
|
||||||
|
c.gridy = 4; c.gridx = 0; c.gridwidth = 1;
|
||||||
|
p1.add(new JLabel("Color favorito:"), c);
|
||||||
|
c.gridx = 1;
|
||||||
|
p1.add(cboOpciones, c);
|
||||||
|
|
||||||
|
c.gridy = 5; c.gridx = 0;
|
||||||
|
p1.add(new JLabel("Valor:"), c);
|
||||||
|
c.gridx = 1;
|
||||||
|
p1.add(sldValor, c);
|
||||||
|
|
||||||
|
// --- Pestaña 2 ---
|
||||||
|
JPanel p2 = new JPanel(new BorderLayout(8,8));
|
||||||
|
lstElementos.setVisibleRowCount(10);
|
||||||
|
p2.add(new JScrollPane(lstElementos), BorderLayout.CENTER);
|
||||||
|
JPanel p2South = new JPanel();
|
||||||
|
p2South.add(new JLabel("Nuevo:"));
|
||||||
|
p2South.add(txtNuevo);
|
||||||
|
p2South.add(btnAdd);
|
||||||
|
p2South.add(btnRemove);
|
||||||
|
p2.add(p2South, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
// --- Pestaña 3 ---
|
||||||
|
JPanel p3 = new JPanel(new BorderLayout());
|
||||||
|
canvas.setOpaque(true);
|
||||||
|
canvas.setBackground(new Color(245,245,245));
|
||||||
|
canvas.setPreferredSize(new Dimension(400, 300));
|
||||||
|
p3.add(canvas, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
// Añadir pestañas
|
||||||
|
tabs.addTab("Controles", p1);
|
||||||
|
tabs.addTab("Lista", p2);
|
||||||
|
tabs.addTab("Canvas", p3);
|
||||||
|
|
||||||
|
// Barra inferior de estado
|
||||||
|
JPanel south = new JPanel(new BorderLayout(8,8));
|
||||||
|
JPanel right = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||||
|
right.add(new JLabel("Hora:"));
|
||||||
|
right.add(lblHora);
|
||||||
|
right.add(btnTareaLarga);
|
||||||
|
right.add(progress);
|
||||||
|
south.add(lblEstado, BorderLayout.WEST);
|
||||||
|
south.add(right, BorderLayout.EAST);
|
||||||
|
|
||||||
|
add(tabs, BorderLayout.CENTER);
|
||||||
|
add(south, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
// Estado inicial
|
||||||
|
txtNombre.setEnabled(false);
|
||||||
|
progress.setStringPainted(true);
|
||||||
|
progress.setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Getters para el Controlador ===
|
||||||
|
public JMenuItem getMiNuevo() { return miNuevo; }
|
||||||
|
public JMenuItem getMiSalir() { return miSalir; }
|
||||||
|
|
||||||
|
public JButton getBtnMas() { return btnMas; }
|
||||||
|
public JButton getBtnMenos() { return btnMenos; }
|
||||||
|
public JCheckBox getChkHabilitarTexto() { return chkHabilitarTexto; }
|
||||||
|
public JTextField getTxtNombre() { return txtNombre; }
|
||||||
|
public JComboBox<String> getCboOpciones() { return cboOpciones; }
|
||||||
|
public JSlider getSldValor() { return sldValor; }
|
||||||
|
|
||||||
|
public DefaultListModel<String> getListModel() { return listModel; }
|
||||||
|
public JList<String> getLstElementos() { return lstElementos; }
|
||||||
|
public JButton getBtnAdd() { return btnAdd; }
|
||||||
|
public JButton getBtnRemove() { return btnRemove; }
|
||||||
|
public JTextField getTxtNuevo() { return txtNuevo; }
|
||||||
|
|
||||||
|
public JLabel getCanvas() { return canvas; }
|
||||||
|
public JTabbedPane getTabs() { return tabs; }
|
||||||
|
|
||||||
|
public JLabel getLblContador() { return lblContador; }
|
||||||
|
public JLabel getLblEstado() { return lblEstado; }
|
||||||
|
public JLabel getLblHora() { return lblHora; }
|
||||||
|
public JProgressBar getProgress() { return progress; }
|
||||||
|
public JButton getBtnTareaLarga() { return btnTareaLarga; }
|
||||||
|
|
||||||
|
// Ayuda para conectar DocumentListener fácilmente
|
||||||
|
public void addNombreDocumentListener(DocumentListener dl) {
|
||||||
|
txtNombre.getDocument().addDocumentListener(dl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user