import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.function.Consumer; /** * La classe Fenetre gère uniquement l'interface graphique : * - zone de dessin (remplaçable par la classe Dessin) * - affichage du mot masqué * - saisie d'une lettre (événement remonté via un handler) * * Aucune logique de jeu (choix/vérification du mot) n'est ici. * * * @version 0.3 * @author Adrien * Date : 08-10-25 * Licence : */ public class Fenetre { // --- Composants de l'interface (UI only) --- private JFrame window; private JLabel wordLabel; private JTextField letterInput; private JButton sendButton; private JPanel drawZone; // remplaçable par la classe Dessin // Handler externe pour la lettre soumise (fourni par la classe Partie / contrôleur) private Consumer onLetterSubmitted; // --- Constructeur (courte orchestration uniquement) --- public Fenetre() { setupWindow(); JPanel root = createRoot(); window.setContentPane(root); drawZone = createDrawZone(); root.add(drawZone); wordLabel = createWordLabel(); root.add(wordLabel); JPanel inputPanel = createInputPanel(); root.add(inputPanel); window.setVisible(true); letterInput.requestFocusInWindow(); } // --- Initialisation fenêtre --- /** Configure la fenêtre principale (titre, taille, fermeture). */ private void setupWindow() { window = new JFrame("Jeu du Pendu"); window.setSize(600, 600); window.setLocationRelativeTo(null); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } /** Crée le conteneur principal vertical. */ private JPanel createRoot() { JPanel root = new JPanel(); root.setLayout(new BoxLayout(root, BoxLayout.Y_AXIS)); return root; } // --- Sous-composants UI --- /** Crée la zone de dessin placeholder (à remplacer par Dessin). */ private JPanel createDrawZone() { JPanel panel = new PlaceholderDrawPanel(); panel.setPreferredSize(new Dimension(600, 350)); panel.setBackground(new Color(245, 245, 245)); return panel; } /** Crée le label d'affichage du mot (placeholder jusqu'à injection par Partie). */ private JLabel createWordLabel() { JLabel label = new JLabel("_ _ _ _ _", SwingConstants.CENTER); label.setFont(new Font("Segoe UI", Font.BOLD, 32)); label.setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 10)); label.setAlignmentX(Component.CENTER_ALIGNMENT); return label; } /** Crée la zone de saisie (champ + bouton) et branche l'action. */ private JPanel createInputPanel() { JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10)); JLabel prompt = new JLabel("Entrez une lettre :"); letterInput = new JTextField(2); letterInput.setHorizontalAlignment(JTextField.CENTER); letterInput.setFont(new Font("Segoe UI", Font.BOLD, 24)); sendButton = new JButton("Envoyer"); Action sendAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { submitLetter(); } }; sendButton.addActionListener(sendAction); letterInput.addActionListener(sendAction); letterInput.addKeyListener(new KeyAdapter() { @Override public void keyTyped(KeyEvent e) { char c = e.getKeyChar(); if (!Character.isLetter(c) || letterInput.getText().length() >= 1) e.consume(); else e.setKeyChar(Character.toUpperCase(c)); } }); inputPanel.add(prompt); inputPanel.add(letterInput); inputPanel.add(sendButton); return inputPanel; } // --- Partie et Dessin --- /** Définit le texte du mot affiché (ex: "_ _ A _ _") fourni par la classe Partie. */ public void setWordDisplay(String maskedWord) { wordLabel.setText(maskedWord != null ? maskedWord : ""); } /** Définit le panneau de dessin (remplace le placeholder par la classe Dessin). */ public void setDrawPanel(JPanel dessinPanel) { if (dessinPanel == null) return; Container parent = drawZone.getParent(); int index = -1; for (int i = 0; i < parent.getComponentCount(); i++) { if (parent.getComponent(i) == drawZone) { index = i; break; } } if (index != -1) { parent.remove(index); drawZone = dessinPanel; drawZone.setPreferredSize(new Dimension(600, 350)); parent.add(drawZone, index); parent.revalidate(); parent.repaint(); } } /** Définit le handler appelé quand l'utilisateur soumet une lettre. */ public void setOnLetterSubmitted(Consumer handler) { this.onLetterSubmitted = handler; } // --- Méthodes privées UI --- /** Récupère la lettre et notifie le handler externe (aucune logique de jeu ici). */ private void submitLetter() { String text = letterInput.getText().trim().toUpperCase(); letterInput.setText(""); if (text.length() != 1 || !text.matches("[A-Z]")) { JOptionPane.showMessageDialog(window, "Veuillez entrer une seule lettre (A-Z)."); return; } if (onLetterSubmitted != null) onLetterSubmitted.accept(text.charAt(0)); else JOptionPane.showMessageDialog(window, "Lettre soumise (placeholder) : " + text); } // --- Placeholder de dessin (pour tester la fenêtre seule) --- private static class PlaceholderDrawPanel extends JPanel { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; g2.setStroke(new BasicStroke(2f)); g2.drawRect(10, 10, getWidth() - 20, getHeight() - 20); g2.setFont(getFont().deriveFont(Font.BOLD, 16f)); String txt = "Zone de dessin (remplacer par Dessin)"; FontMetrics fm = g2.getFontMetrics(); int x = (getWidth() - fm.stringWidth(txt)) / 2; int y = (getHeight() + fm.getAscent()) / 2; g2.drawString(txt, x, y); } } // --- Méthode principale de test : exécuter Fenetre seule (sans Partie/Dessin) --- public static void main(String[] args) { Fenetre f = new Fenetre(); f.setWordDisplay("_ _ _ _ _"); // placeholder f.setDrawPanel(new Dessin()); // dessin f.setOnLetterSubmitted(ch -> JOptionPane.showMessageDialog(null,"Lettre reçue : " + ch + " (sans logique de jeu)")); } }