This commit is contained in:
2025-10-15 22:03:52 +02:00
parent 9e46b869e6
commit e009d95ffb
8 changed files with 739 additions and 0 deletions

View 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
View 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
View 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>

View 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
});
}
}

View 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();
}
}

View 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);
}
}

View 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; }
}

View 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);
}
}