Una forma sencilla y rápida de aprender JAVA, observando y deduciendo cómo se comporta el lenguaje a través de ejemplos prácticos.

Archivo del blog

domingo, 13 de abril de 2025

Proyecto Ajedrez I.3: Ventanas de Diálogo (JDialogs - Swing)

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

Con la tecnología de Blogger.