From ba7e16dc646dd69f26b938e47b5b0159cbb03395 Mon Sep 17 00:00:00 2001 From: dick Date: Wed, 8 Oct 2025 12:13:42 +0200 Subject: [PATCH] Fenetre et Dessin v1 --- src/Dessin.java | 99 +++++++++++++++++++++---- src/Fenetre.java | 187 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 259 insertions(+), 27 deletions(-) diff --git a/src/Dessin.java b/src/Dessin.java index a189d2c..92435cc 100644 --- a/src/Dessin.java +++ b/src/Dessin.java @@ -1,23 +1,94 @@ +import javax.swing.*; +import java.awt.*; /** -* La classe Dessin +* La classe Dessin gère uniquement le dessin du pendu * -* @version -* @author -* Date : +* @version 0.1 +* @author Adrien +* Date : 08-10-2025 * Licence : */ -public class Dessin { - //Attributs +public class Dessin extends JPanel { - //Constructeur - public Dessin() { + // --- Constructeur --- + public Dessin() { + // Taille préférée pour s'intégrer dans Fenetre + setPreferredSize(new Dimension(600, 350)); + setBackground(new Color(245, 245, 245)); + } - } - //Méthodes + // --- Dessin principal --- + @Override + protected void paintComponent(Graphics graphics) { + super.paintComponent(graphics); - //Affichage - public String toString() { - return "" ; - } + // Anti-aliasing pour des traits plus doux + Graphics2D graphics2D = (Graphics2D) graphics.create(); + graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics2D.setStroke(new BasicStroke(3f)); + graphics2D.setColor(Color.DARK_GRAY); + + // Repères et proportions + int width = getWidth(); + int height = getHeight(); + int marginPixels = Math.min(width, height) / 12; // marge proportionnelle + + // Potence : socle + int baseYCoordinate = height - marginPixels; + graphics2D.drawLine(marginPixels, baseYCoordinate, width / 2, baseYCoordinate); + + // Montant vertical + int postXCoordinate = marginPixels + (width / 12); + graphics2D.drawLine(postXCoordinate, baseYCoordinate, postXCoordinate, marginPixels); + + // Traverse horizontale + int beamLength = width / 3; + graphics2D.drawLine(postXCoordinate, marginPixels, postXCoordinate + beamLength, marginPixels); + + // Renfort diagonal + graphics2D.drawLine(postXCoordinate, marginPixels + height / 10, + postXCoordinate + width / 12, marginPixels); + + // Corde + int ropeXCoordinate = postXCoordinate + beamLength; + int ropeTopYCoordinate = marginPixels; + int ropeBottomYCoordinate = marginPixels + height / 12; + graphics2D.drawLine(ropeXCoordinate, ropeTopYCoordinate, ropeXCoordinate, ropeBottomYCoordinate); + + // Personnage : tête + int headRadiusPixels = Math.min(width, height) / 16; + int headCenterX = ropeXCoordinate; + int headCenterY = ropeBottomYCoordinate + headRadiusPixels; + graphics2D.drawOval(headCenterX - headRadiusPixels, headCenterY - headRadiusPixels, + headRadiusPixels * 2, headRadiusPixels * 2); + + // Corps + int bodyTopYCoordinate = headCenterY + headRadiusPixels; + int bodyBottomYCoordinate = bodyTopYCoordinate + height / 6; + graphics2D.drawLine(headCenterX, bodyTopYCoordinate, headCenterX, bodyBottomYCoordinate); + + // Bras + int armSpanPixels = width / 10; + int shouldersYCoordinate = bodyTopYCoordinate + height / 24; + graphics2D.drawLine(headCenterX, shouldersYCoordinate, + headCenterX - armSpanPixels, shouldersYCoordinate + height / 20); + graphics2D.drawLine(headCenterX, shouldersYCoordinate, + headCenterX + armSpanPixels, shouldersYCoordinate + height / 20); + + // Jambes + int legSpanPixels = width / 12; + graphics2D.drawLine(headCenterX, bodyBottomYCoordinate, + headCenterX - legSpanPixels, bodyBottomYCoordinate + height / 8); + graphics2D.drawLine(headCenterX, bodyBottomYCoordinate, + headCenterX + legSpanPixels, bodyBottomYCoordinate + height / 8); + + graphics2D.dispose(); + } + + // Affichage + @Override + public String toString() { + return ""; + } } diff --git a/src/Fenetre.java b/src/Fenetre.java index bec8a54..830c436 100644 --- a/src/Fenetre.java +++ b/src/Fenetre.java @@ -1,23 +1,184 @@ +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.function.Consumer; /** -* La classe Fenetre +* 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) * -* @version -* @author -* Date : -* Licence : +* 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 { - //Attributs - //Constructeur - public 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)")); } - //Méthodes - //Affichage - public String toString() { - return "" ; - } }