Abordaremos el proyecto paso a paso. Antes de comenzar con la siguiente fase, mostraremos el punto en el que nos encontramos actualmente en el proyecto:
1 Primer esbozo del tablero de ajedrez (2018)
2 Explicación normativa y reglas del juego (2024)
3 Creando Interfaz Gráfica Principal (2025)
.AjedrezGrafico.java
.PanelTablero.java
.SplashScreen.java
.GuiUtils.java
>4 Ventanas de Diálogo
.ConfiguracionDialog.java
.ElegirLadoDialog.java
.PromocionDialog.java
.ConfirmarFinalizarDialog.java
.ConfirmarCierreAppDialog.java
En este post nos centraremos el punto 4 que es visualizar las ventanas de diálogo correspondientes a las distintas funciones.
Código Java 1 (ConfiguracionDialog.java):
package ajedrez_gui;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import static ajedrez_gui.AjedrezGrafico.ModoJuego;
/**
* Diálogo para configurar el modo de juego y la velocidad de la CPU. Ahora con
* barra de título personalizada.
*/
public class ConfiguracionDialog extends JDialog {
private static final ModoJuego DEFAULT_MODO_JUEGO = ModoJuego.HUMANO_VS_CPU;
private static final String DEFAULT_VELOCIDAD_CPU = "Medio";
private static final String DIALOG_TITLE = "Menú Configurar";
private static final Font FONT_CUSTOM_TITLE = new Font("Tahoma", Font.BOLD, 14);
private static final Color COLOR_CUSTOM_TITLE_BG = Color.LIGHT_GRAY;
private static final Color COLOR_CUSTOM_TITLE_FG = Color.BLACK;
private static final int CUSTOM_TITLE_BAR_HEIGHT = 30;
private static final int CUSTOM_TITLE_PADDING = 5;
private static final Font FONT_LABEL = new Font("Tahoma", Font.PLAIN, 14);
private static final Font FONT_COMBO = new Font("Tahoma", Font.PLAIN, 14);
private static final Font FONT_BUTTON = new Font("Tahoma", Font.PLAIN, 14);
private static final Dimension BUTTON_SIZE = new Dimension(120, 30);
private static final int DIALOG_WIDTH = 400;
private static final int DIALOG_HEIGHT = 250; // Aumentar altura para barra de título
private JComboBox<ModoJuego> comboModo;
private JComboBox<String> comboVelocidad;
private JButton botonAplicar;
private JButton botonDefault;
private JButton botonCancelar;
private ModoJuego modoSeleccionado;
private String velocidadSeleccionada;
private boolean cambiosAplicados = false;
public ConfiguracionDialog(Frame owner, boolean modal,
ModoJuego modoActual,
String velocidadActual) {
// Llamar a super sin título, ya que es undecorated ---
super(owner, modal);
setUndecorated(true);
this.modoSeleccionado = modoActual;
this.velocidadSeleccionada = velocidadActual;
initComponents();
initListeners();
setValoresActuales(modoActual, velocidadActual);
actualizarControlesDependientes();
setPreferredSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT));
pack();
setLocationRelativeTo(owner);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
}
private void initComponents() {
var mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
mainPanel.setBackground(new Color(230, 230, 230));
// --- Crear y añadir barra de título personalizada ---
var titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, CUSTOM_TITLE_PADDING)); // Centrar título
titlePanel.setBackground(COLOR_CUSTOM_TITLE_BG);
titlePanel.setPreferredSize(new Dimension(DIALOG_WIDTH, CUSTOM_TITLE_BAR_HEIGHT));
// Asegurar que ocupe todo el ancho horizontalmente si el layout principal lo permite
titlePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, CUSTOM_TITLE_BAR_HEIGHT));
var titleLabel = new JLabel(DIALOG_TITLE);
titleLabel.setFont(FONT_CUSTOM_TITLE);
titleLabel.setForeground(COLOR_CUSTOM_TITLE_FG);
titlePanel.add(titleLabel);
// Añadir titlePanel PRIMERO al mainPanel
mainPanel.add(titlePanel);
// Panel de contenido (con padding)
var contentPanel = new JPanel();
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
contentPanel.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20)); // Padding interno
contentPanel.setOpaque(false); // Hacer transparente para ver fondo de mainPanel
// Panel de opciones con GridBagLayout
var optionsPanel = new JPanel(new GridBagLayout());
optionsPanel.setOpaque(false);
var gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 5, 10, 5);
gbc.anchor = GridBagConstraints.WEST;
// Fila Modo
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0.0;
var labelModo = new JLabel("Modo:");
labelModo.setFont(FONT_LABEL);
optionsPanel.add(labelModo, gbc);
gbc.gridx = 1;
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
comboModo = new JComboBox<>(ModoJuego.values());
comboModo.setFont(FONT_COMBO);
optionsPanel.add(comboModo, gbc);
gbc.fill = GridBagConstraints.NONE;
// Fila Velocidad
gbc.gridx = 0;
gbc.gridy++;
gbc.weightx = 0.0;
var labelVelocidad = new JLabel("Velocidad CPU:");
labelVelocidad.setFont(FONT_LABEL);
optionsPanel.add(labelVelocidad, gbc);
gbc.gridx = 1;
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
comboVelocidad = new JComboBox<>(new String[]{"Rápido", "Medio", "Lento"});
comboVelocidad.setFont(FONT_COMBO);
optionsPanel.add(comboVelocidad, gbc);
gbc.fill = GridBagConstraints.NONE;
optionsPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
contentPanel.add(optionsPanel); // Añadir options al contentPanel
contentPanel.add(Box.createVerticalGlue()); // Empuja botones al final del contentPanel
// Panel de botones
var panelBotones = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
panelBotones.setOpaque(false);
botonAplicar = new JButton("Aceptar");
botonDefault = new JButton("Restaurar");
GuiUtils.applyButtonStyle(botonAplicar, FONT_BUTTON, BUTTON_SIZE);
GuiUtils.applyButtonStyle(botonDefault, FONT_BUTTON, BUTTON_SIZE);
panelBotones.add(botonAplicar);
panelBotones.add(botonDefault);
panelBotones.setAlignmentX(Component.CENTER_ALIGNMENT);
contentPanel.add(panelBotones); // Añadir botones al contentPanel
// Añadir el contentPanel (con opciones y botones) al mainPanel
mainPanel.add(contentPanel);
// Establecer el mainPanel como el panel de contenido del JDialog
setContentPane(mainPanel);
}
private void initListeners() {
comboModo.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
actualizarControlesDependientes();
}
});
botonAplicar.addActionListener(e -> aplicarCambios());
botonDefault.addActionListener(e -> restaurarDefaults());
getRootPane().registerKeyboardAction(e -> cancelar(),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ESCAPE, 0),
JComponent.WHEN_IN_FOCUSED_WINDOW);
}
private void setValoresActuales(ModoJuego modo, String velocidad) {
comboModo.setSelectedItem(modo != null ? modo : DEFAULT_MODO_JUEGO);
comboVelocidad.setSelectedItem(velocidad != null ? velocidad : DEFAULT_VELOCIDAD_CPU);
}
private void actualizarControlesDependientes() {
var modoSel = (ModoJuego) comboModo.getSelectedItem();
if (modoSel == null) {
return;
}
boolean habilitaVelocidad = modoSel != ModoJuego.HUMANO_VS_HUMANO;
comboVelocidad.setEnabled(habilitaVelocidad);
}
private void aplicarCambios() {
this.modoSeleccionado = (ModoJuego) comboModo.getSelectedItem();
this.velocidadSeleccionada = comboVelocidad.isEnabled() ? (String) comboVelocidad.getSelectedItem() : DEFAULT_VELOCIDAD_CPU;
this.cambiosAplicados = true;
this.dispose();
}
private void restaurarDefaults() {
setValoresActuales(DEFAULT_MODO_JUEGO, DEFAULT_VELOCIDAD_CPU);
actualizarControlesDependientes();
}
private void cancelar() {
this.cambiosAplicados = false;
this.dispose();
}
public boolean seAplicaronCambios() {
return cambiosAplicados;
}
public ModoJuego getModoSeleccionado() {
return modoSeleccionado != null ? modoSeleccionado : DEFAULT_MODO_JUEGO;
}
public String getVelocidadSeleccionada() {
return velocidadSeleccionada != null ? velocidadSeleccionada : DEFAULT_VELOCIDAD_CPU;
}
}
Resultado:
Código Java 2 (ElegirLadoDialog.java):
package ajedrez_gui;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* Diálogo para elegir bando. Tamaño de ventana estándar, contenido mantiene tamaño original.
*/
public class ElegirLadoDialog extends JDialog {
private static final String DIALOG_TITLE = "Elige tu Bando ChessMate";
// Tamaño de ventana estándar (similar a otros diálogos) ***
private static final int DIALOG_WIDTH = 400;
private static final int DIALOG_HEIGHT = 250;
// Barra de título personalizada (tamaño original)
private static final Font FONT_CUSTOM_TITLE = new Font("Tahoma", Font.BOLD, 14);
private static final Color COLOR_CUSTOM_TITLE_BG = Color.LIGHT_GRAY;
private static final Color COLOR_CUSTOM_TITLE_FG = Color.BLACK;
private static final int CUSTOM_TITLE_BAR_HEIGHT = 30; // Altura original
private static final int CUSTOM_TITLE_PADDING = 5;
// Apariencia de Reyes (tamaño original)
private static final String RUTA_FUENTE_PIEZAS = "/ajedrez_gui/assets/CASEFONT.TTF";
private static final float FONT_SIZE_PIEZAS_DIALOG = 58f;
private static final String FUENTE_FALLBACK_POR_DEFECTO = "Dialog";
private static final String REY_CHAR = "l";
private static final Color COLOR_PIEZA_BLANCA = Color.WHITE;
private static final Color COLOR_PIEZA_NEGRA = Color.BLACK;
private static final Color COLOR_FONDO_REY = new Color(190, 190, 190);
private static final Color BORDER_COLOR_NORMAL = Color.GRAY;
private static final Color BORDER_COLOR_HOVER = Color.BLACK;
private static final int BORDER_THICKNESS = 2;
private static final int PADDING_REY = 10; // Padding original
// Componentes UI
private JLabel labelReyBlanco;
private JLabel labelReyNegro;
private Font fontPiezasDialogo;
// Estado
private boolean ladoSeleccionadoBlancas = true;
private boolean empezarPartida = false;
public ElegirLadoDialog(Frame owner, boolean defaultEsBlancas) {
super(owner, true);
setUndecorated(true);
this.fontPiezasDialogo = GuiUtils.cargarFuenteDesdeRecurso(
RUTA_FUENTE_PIEZAS,
FONT_SIZE_PIEZAS_DIALOG, // Usa tamaño 46f
FUENTE_FALLBACK_POR_DEFECTO
);
this.ladoSeleccionadoBlancas = defaultEsBlancas;
initComponents();
initListeners();
// *** Usar setPreferredSize y pack() para que se ajuste al contenido ***
setPreferredSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT));
pack();
setLocationRelativeTo(owner);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
}
/**
* Inicializa y organiza los componentes gráficos del diálogo.
*/
private void initComponents() {
var mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
mainPanel.setBackground(new Color(230, 230, 230));
// Barra de Título Personalizada (altura original 30)
var titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, CUSTOM_TITLE_PADDING));
titlePanel.setBackground(COLOR_CUSTOM_TITLE_BG);
titlePanel.setPreferredSize(new Dimension(0, CUSTOM_TITLE_BAR_HEIGHT)); // Ancho 0 -> FlowLayout calcula
titlePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, CUSTOM_TITLE_BAR_HEIGHT));
var titleLabel = new JLabel(DIALOG_TITLE);
titleLabel.setFont(FONT_CUSTOM_TITLE);
titleLabel.setForeground(COLOR_CUSTOM_TITLE_FG);
titlePanel.add(titleLabel);
mainPanel.add(titlePanel);
// Panel de Contenido Principal
var contentPanel = new JPanel();
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
contentPanel.setBorder(BorderFactory.createEmptyBorder(15, 20, 20, 20)); // Padding original
contentPanel.setOpaque(false);
// Panel específico para los Reyes
var kingPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 40, 10)); // Espaciado original
kingPanel.setOpaque(false);
// Crear borde para reyes con padding original
Border padding = new EmptyBorder(PADDING_REY, PADDING_REY, PADDING_REY, PADDING_REY); // Usa padding 10
Border lineBorderNormal = new LineBorder(BORDER_COLOR_NORMAL, BORDER_THICKNESS);
Border compoundBorderNormal = new CompoundBorder(lineBorderNormal, padding);
// Crear y añadir los JLabels de los reyes (usarán fuente 46f y padding 10)
labelReyBlanco = createKingLabel(REY_CHAR, COLOR_PIEZA_BLANCA, COLOR_FONDO_REY, compoundBorderNormal);
labelReyNegro = createKingLabel(REY_CHAR, COLOR_PIEZA_NEGRA, COLOR_FONDO_REY, compoundBorderNormal);
kingPanel.add(labelReyBlanco);
kingPanel.add(labelReyNegro);
kingPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
// Añadir componentes al contentPanel para centrado vertical
contentPanel.add(Box.createVerticalGlue());
contentPanel.add(kingPanel);
contentPanel.add(Box.createVerticalGlue());
mainPanel.add(contentPanel);
setContentPane(mainPanel);
}
/**
* Helper para crear y configurar un JLabel para mostrar un rey.
*/
private JLabel createKingLabel(String text, Color foreground, Color background, Border border) {
var label = new JLabel(text, SwingConstants.CENTER);
if (fontPiezasDialogo != null) {
label.setFont(fontPiezasDialogo);
}
label.setForeground(foreground);
label.setBackground(background);
label.setOpaque(true);
label.setBorder(border);
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
return label;
}
/**
* Configura los listeners de eventos.
*/
private void initListeners() {
// Crear bordes reutilizables para efecto hover (con padding original)
Border padding = new EmptyBorder(PADDING_REY, PADDING_REY, PADDING_REY, PADDING_REY); // Usa padding 10
Border lineBorderNormal = new LineBorder(BORDER_COLOR_NORMAL, BORDER_THICKNESS);
Border lineBorderHover = new LineBorder(BORDER_COLOR_HOVER, BORDER_THICKNESS);
Border compoundBorderNormal = new CompoundBorder(lineBorderNormal, padding);
Border compoundBorderHover = new CompoundBorder(lineBorderHover, padding);
MouseAdapter reyListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
ladoSeleccionadoBlancas = (e.getSource() == labelReyBlanco);
empezarPartida = true;
dispose();
}
@Override public void mouseEntered(MouseEvent e) { ((JLabel) e.getSource()).setBorder(compoundBorderHover); }
@Override public void mouseExited(MouseEvent e) { ((JLabel) e.getSource()).setBorder(compoundBorderNormal); }
};
labelReyBlanco.addMouseListener(reyListener);
labelReyNegro.addMouseListener(reyListener);
getRootPane().registerKeyboardAction(e -> {
empezarPartida = false;
dispose();
}, KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
}
// Getters
public boolean seDebeEmpezar() { return empezarPartida; }
public boolean getLadoSeleccionadoBlancas() { return ladoSeleccionadoBlancas; }
}
Resultado:
Código Java 3 (PromocionDialog.java):
package ajedrez_gui;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* Diálogo modal para que el usuario seleccione a qué pieza promocionar un peón.
* Con barra de título personalizada, panel de piezas centrado verticalmente y
* color de piezas corregido.
*/
public class PromocionDialog extends JDialog {
private static final String DIALOG_TITLE = "Selecciona Pieza de Promoción";
// --- Constantes Barra de Título ---
private static final Font FONT_CUSTOM_TITLE = new Font("Tahoma", Font.BOLD, 14);
private static final Color COLOR_CUSTOM_TITLE_BG = Color.LIGHT_GRAY;
private static final Color COLOR_CUSTOM_TITLE_FG = Color.BLACK;
private static final int CUSTOM_TITLE_BAR_HEIGHT = 30;
private static final int CUSTOM_TITLE_PADDING = 5;
// --- Constantes Diálogo ---
private static final int DIALOG_WIDTH = 400;
private static final int DIALOG_HEIGHT = 230;
// --- Constantes Piezas ---
private static final String RUTA_FUENTE_PIEZAS = "/ajedrez_gui/assets/CASEFONT.TTF";
private static final float FONT_SIZE_PIEZAS_DIALOG = 52f;
private static final String FUENTE_FALLBACK_POR_DEFECTO = "Dialog";
private static final String DAMA_CHAR = "w";
private static final String TORRE_CHAR = "t";
private static final String ALFIL_CHAR = "v";
private static final String CABALLO_CHAR = "m";
private static final Color COLOR_PIEZA_BLANCA = Color.BLACK;
private static final Color COLOR_PIEZA_NEGRA = Color.WHITE;
private static final Color COLOR_FONDO_PIEZA = new Color(210, 210, 210); // Fondo gris claro
private static final Color BORDER_COLOR_NORMAL = Color.GRAY;
private static final Color BORDER_COLOR_HOVER = Color.BLACK;
private static final int BORDER_THICKNESS = 2;
private static final int PADDING_PIEZA = 8;
// --- Componentes y Estado ---
private JLabel labelDama;
private JLabel labelTorre;
private JLabel labelAlfil;
private JLabel labelCaballo;
private Font fontPiezasDialogo;
private char piezaSeleccionada = 'Q';
private boolean seleccionRealizada = false;
public PromocionDialog(Frame owner, boolean esPiezaBlanca) {
super(owner, true);
setUndecorated(true);
this.fontPiezasDialogo = GuiUtils.cargarFuenteDesdeRecurso(
RUTA_FUENTE_PIEZAS, FONT_SIZE_PIEZAS_DIALOG, FUENTE_FALLBACK_POR_DEFECTO);
initComponents(esPiezaBlanca); // Pasar color al inicializar
initListeners();
setPreferredSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT));
pack();
setLocationRelativeTo(owner);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
}
private void initComponents(boolean esPiezaBlanca) {
var mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
mainPanel.setBackground(new Color(230, 230, 230));
// Barra de título personalizada
var titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, CUSTOM_TITLE_PADDING));
titlePanel.setBackground(COLOR_CUSTOM_TITLE_BG);
titlePanel.setPreferredSize(new Dimension(DIALOG_WIDTH, CUSTOM_TITLE_BAR_HEIGHT));
titlePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, CUSTOM_TITLE_BAR_HEIGHT));
var titleLabel = new JLabel(DIALOG_TITLE);
titleLabel.setFont(FONT_CUSTOM_TITLE);
titleLabel.setForeground(COLOR_CUSTOM_TITLE_FG);
titlePanel.add(titleLabel);
mainPanel.add(titlePanel);
// Panel de contenido
var contentPanel = new JPanel();
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
contentPanel.setBorder(BorderFactory.createEmptyBorder(15, 20, 20, 20));
contentPanel.setOpaque(false);
// Panel para las piezas
var piecePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 12, 5));
piecePanel.setOpaque(false);
Color colorPieza = esPiezaBlanca ? COLOR_PIEZA_BLANCA : COLOR_PIEZA_NEGRA;
// Crear labels usando el color determinado
labelDama = createPieceLabel(DAMA_CHAR, colorPieza); // Pasar colorPieza
labelTorre = createPieceLabel(TORRE_CHAR, colorPieza); // Pasar colorPieza
labelAlfil = createPieceLabel(ALFIL_CHAR, colorPieza); // Pasar colorPieza
labelCaballo = createPieceLabel(CABALLO_CHAR, colorPieza); // Pasar colorPieza
piecePanel.add(labelDama);
piecePanel.add(labelTorre);
piecePanel.add(labelAlfil);
piecePanel.add(labelCaballo);
piecePanel.setAlignmentX(Component.CENTER_ALIGNMENT);
// Centrar piecePanel verticalmente
contentPanel.add(Box.createVerticalGlue());
contentPanel.add(piecePanel);
contentPanel.add(Box.createVerticalGlue());
mainPanel.add(contentPanel);
setContentPane(mainPanel);
}
private JLabel createPieceLabel(String pieceChar, Color pieceColor) {
var label = new JLabel(pieceChar, SwingConstants.CENTER);
if (fontPiezasDialogo != null) {
label.setFont(fontPiezasDialogo);
}
label.setForeground(pieceColor);
label.setBackground(COLOR_FONDO_PIEZA);
label.setOpaque(true);
Border padding = new EmptyBorder(PADDING_PIEZA, PADDING_PIEZA, PADDING_PIEZA, PADDING_PIEZA);
Border lineBorderNormal = new LineBorder(BORDER_COLOR_NORMAL, BORDER_THICKNESS);
label.setBorder(new CompoundBorder(lineBorderNormal, padding));
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
return label;
}
// initListeners, getters
private void initListeners() {
Border padding = new EmptyBorder(PADDING_PIEZA, PADDING_PIEZA, PADDING_PIEZA, PADDING_PIEZA);
Border lineBorderNormal = new LineBorder(BORDER_COLOR_NORMAL, BORDER_THICKNESS);
Border lineBorderHover = new LineBorder(BORDER_COLOR_HOVER, BORDER_THICKNESS);
Border compoundBorderNormal = new CompoundBorder(lineBorderNormal, padding);
Border compoundBorderHover = new CompoundBorder(lineBorderHover, padding);
MouseAdapter pieceListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Object source = e.getSource();
if (source == labelDama) {
piezaSeleccionada = 'Q';
} else if (source == labelTorre) {
piezaSeleccionada = 'R';
} else if (source == labelAlfil) {
piezaSeleccionada = 'B';
} else if (source == labelCaballo) {
piezaSeleccionada = 'N';
}
seleccionRealizada = true;
dispose();
}
@Override
public void mouseEntered(MouseEvent e) {
((JLabel) e.getSource()).setBorder(compoundBorderHover);
}
@Override
public void mouseExited(MouseEvent e) {
((JLabel) e.getSource()).setBorder(compoundBorderNormal);
}
};
labelDama.addMouseListener(pieceListener);
labelTorre.addMouseListener(pieceListener);
labelAlfil.addMouseListener(pieceListener);
labelCaballo.addMouseListener(pieceListener);
getRootPane().registerKeyboardAction(e -> {
seleccionRealizada = false;
dispose();
}, KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
}
public boolean isSeleccionRealizada() {
return seleccionRealizada;
}
public char getPiezaSeleccionada() {
return piezaSeleccionada;
}
}
Resultado:
Código Java (ConfirmarFinalizarDialog.java):
package ajedrez_gui;
import javax.swing.*;
import java.awt.*;
/**
* Diálogo simple para confirmar si el usuario desea finalizar la partida
* Con barra de título personalizada.
*/
public class ConfirmarFinalizarDialog extends JDialog {
private static final String DIALOG_TITLE = "Confirmar Finalización";
private static final String DIALOG_TEXT = "¿Seguro que quieres Finalizar?";
private static final Font FONT_CUSTOM_TITLE = new Font("Tahoma", Font.BOLD, 14);
private static final Color COLOR_CUSTOM_TITLE_BG = Color.LIGHT_GRAY;
private static final Color COLOR_CUSTOM_TITLE_FG = Color.BLACK;
private static final int CUSTOM_TITLE_BAR_HEIGHT = 30;
private static final int CUSTOM_TITLE_PADDING = 5;
private static final Font FONT_TEXT = new Font("Tahoma", Font.BOLD, 16);
private static final Font FONT_BUTTON = new Font("Tahoma", Font.PLAIN, 14);
private static final Dimension BUTTON_SIZE = new Dimension(100, 30);
private static final int DIALOG_WIDTH = 400;
private static final int DIALOG_HEIGHT = 210; // Aumentar altura para barra
private JButton botonSi;
private JButton botonNo;
private boolean confirmado = false;
public ConfirmarFinalizarDialog(Frame owner) {
super(owner, true);
setUndecorated(true);
initComponents();
initListeners();
setPreferredSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT));
pack();
setLocationRelativeTo(owner);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
}
private void initComponents() {
// Panel principal con borde
var mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
mainPanel.setBackground(new Color(230, 230, 230));
// --- Crear y añadir barra de título personalizada ---
var titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, CUSTOM_TITLE_PADDING));
titlePanel.setBackground(COLOR_CUSTOM_TITLE_BG);
titlePanel.setPreferredSize(new Dimension(DIALOG_WIDTH, CUSTOM_TITLE_BAR_HEIGHT));
titlePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, CUSTOM_TITLE_BAR_HEIGHT));
var titleLabel = new JLabel(DIALOG_TITLE);
titleLabel.setFont(FONT_CUSTOM_TITLE);
titleLabel.setForeground(COLOR_CUSTOM_TITLE_FG);
titlePanel.add(titleLabel);
mainPanel.add(titlePanel); // Añadir barra de título primero
// Panel de contenido (con padding)
var contentPanel = new JPanel();
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
contentPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // Padding interno
contentPanel.setOpaque(false);
// Texto de confirmación
var labelTexto = new JLabel(DIALOG_TEXT, SwingConstants.CENTER);
labelTexto.setFont(FONT_TEXT);
labelTexto.setAlignmentX(Component.CENTER_ALIGNMENT);
contentPanel.add(labelTexto);
contentPanel.add(Box.createRigidArea(new Dimension(0, 30))); // Espacio
// Panel de botones
var panelBotones = new JPanel(new FlowLayout(FlowLayout.CENTER, 25, 10));
panelBotones.setOpaque(false);
botonSi = new JButton("Si");
botonNo = new JButton("No");
GuiUtils.applyButtonStyle(botonSi, FONT_BUTTON, BUTTON_SIZE);
GuiUtils.applyButtonStyle(botonNo, FONT_BUTTON, BUTTON_SIZE);
panelBotones.add(botonSi);
panelBotones.add(botonNo);
panelBotones.setAlignmentX(Component.CENTER_ALIGNMENT);
contentPanel.add(panelBotones); // Añadir botones al contentPanel
// Añadir contentPanel al mainPanel
mainPanel.add(contentPanel);
setContentPane(mainPanel);
}
// initListeners, isConfirmado
private void initListeners() {
botonSi.addActionListener(e -> {
this.confirmado = true;
this.dispose();
});
botonNo.addActionListener(e -> {
this.confirmado = false;
this.dispose();
});
getRootPane().registerKeyboardAction(e -> {
confirmado = false;
dispose();
}, KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
}
public boolean isConfirmado() {
return confirmado;
}
}
Resultado:
Código Java (ConfirmarCierreAppDialog.java):
package ajedrez_gui;
import javax.swing.*;
import java.awt.*;
/**
* Diálogo personalizado para confirmar si el usuario desea cerrar la
* aplicación. Sigue el estilo de los otros diálogos.
*/
public class ConfirmarCierreAppDialog extends JDialog {
// --- Constantes específicas ---
private static final String DIALOG_TITLE = "Confirmar Salida"; // Título para barra personalizada
private static final String DIALOG_TEXT = "¿Abandonar la Aplicación?";
// --- Constantes de Estilo (copiadas de ConfirmarFinalizarDialog para consistencia) ---
private static final Font FONT_CUSTOM_TITLE = new Font("Tahoma", Font.BOLD, 14);
private static final Color COLOR_CUSTOM_TITLE_BG = Color.LIGHT_GRAY;
private static final Color COLOR_CUSTOM_TITLE_FG = Color.BLACK;
private static final int CUSTOM_TITLE_BAR_HEIGHT = 30;
private static final int CUSTOM_TITLE_PADDING = 5;
private static final Font FONT_TEXT = new Font("Tahoma", Font.BOLD, 16);
private static final Font FONT_BUTTON = new Font("Tahoma", Font.PLAIN, 14);
private static final Dimension BUTTON_SIZE = new Dimension(100, 30);
private static final int DIALOG_WIDTH = 400;
private static final int DIALOG_HEIGHT = 210; // Misma altura que ConfirmarFinalizar
// --- Componentes y Estado ---
private JButton botonSi;
private JButton botonNo;
private boolean confirmado = false; // true si se pulsa "Sí"
public ConfirmarCierreAppDialog(Frame owner) {
super(owner, true); // Modal
setUndecorated(true); // Sin barra de título del SO
initComponents(); // Crear UI
initListeners(); // Configurar botones y ESC
setPreferredSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT));
pack(); // Ajustar tamaño
setLocationRelativeTo(owner); // Centrar
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); // Comportamiento al cerrar
}
private void initComponents() {
// Panel principal con borde
var mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
mainPanel.setBackground(new Color(230, 230, 230)); // Fondo gris claro
// Barra de título personalizada
var titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, CUSTOM_TITLE_PADDING));
titlePanel.setBackground(COLOR_CUSTOM_TITLE_BG);
titlePanel.setPreferredSize(new Dimension(DIALOG_WIDTH, CUSTOM_TITLE_BAR_HEIGHT));
titlePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, CUSTOM_TITLE_BAR_HEIGHT));
var titleLabel = new JLabel(DIALOG_TITLE); // Usar título específico
titleLabel.setFont(FONT_CUSTOM_TITLE);
titleLabel.setForeground(COLOR_CUSTOM_TITLE_FG);
titlePanel.add(titleLabel);
mainPanel.add(titlePanel); // Añadir barra de título primero
// Panel de contenido (con padding)
var contentPanel = new JPanel();
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
contentPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // Padding interno
contentPanel.setOpaque(false); // Transparente para ver fondo mainPanel
// Texto de confirmación
var labelTexto = new JLabel(DIALOG_TEXT, SwingConstants.CENTER);
labelTexto.setFont(FONT_TEXT);
labelTexto.setAlignmentX(Component.CENTER_ALIGNMENT);
contentPanel.add(labelTexto);
contentPanel.add(Box.createRigidArea(new Dimension(0, 30))); // Espacio vertical
// Panel de botones
var panelBotones = new JPanel(new FlowLayout(FlowLayout.CENTER, 25, 10)); // Espaciado entre botones
panelBotones.setOpaque(false);
botonSi = new JButton("Sí"); // Botón Sí
botonNo = new JButton("No"); // Botón No
GuiUtils.applyButtonStyle(botonSi, FONT_BUTTON, BUTTON_SIZE); // Aplicar estilo
GuiUtils.applyButtonStyle(botonNo, FONT_BUTTON, BUTTON_SIZE); // Aplicar estilo
panelBotones.add(botonSi);
panelBotones.add(botonNo);
panelBotones.setAlignmentX(Component.CENTER_ALIGNMENT);
contentPanel.add(panelBotones); // Añadir botones al contentPanel
mainPanel.add(contentPanel); // Añadir contentPanel al mainPanel
setContentPane(mainPanel); // Establecer como panel principal del diálogo
}
private void initListeners() {
// Acción para el botón "Sí"
botonSi.addActionListener(e -> {
this.confirmado = true; // Marcar como confirmado
this.dispose(); // Cerrar el diálogo
});
// Acción para el botón "No"
botonNo.addActionListener(e -> {
this.confirmado = false; // Marcar como no confirmado
this.dispose(); // Cerrar el diálogo
});
// Acción para la tecla ESC (equivale a "No")
getRootPane().registerKeyboardAction(e -> {
confirmado = false; // Marcar como no confirmado
dispose(); // Cerrar el diálogo
}, KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
}
/**
* Devuelve true si el usuario presionó "Sí", false en caso contrario.
*
* @return boolean indicando la confirmación.
*/
public boolean isConfirmado() {
return confirmado;
}
}
Resultado:
No hay comentarios:
Publicar un comentario