2 Stimmen

Wie man ein Bild in einem Panel in Java Swing anpasst?

Ich habe einige Code-Schnipsel mit viel Hilfe von anderen Programmierern in SO. Zunächst einmal vielen Dank dafür. Jetzt habe ich diesen Code für Galgenmännchen. Ich möchte, dass das Textfeld unter dem Bild erscheint, im Moment schießt es darüber. Ich habe den Link für das Bild im Code bereitgestellt, aber Sie müssen es vielleicht herunterladen, um eine Ausnahme zu vermeiden. Ich möchte die obere rechte Ecke frei halten für den Timer, für den ich noch nicht überlegt habe, wie ich das machen soll. Ich brauche Hilfe, um Bild und Textfeld an die richtigen Positionen zu bringen. Bitte führen Sie den Code aus, um zu sehen, wie es momentan aussieht. Ich habe sowohl BorderLayout.SOUTH als auch BorderLayout.PAGE_END ausprobiert, aber es hat nicht geholfen. Vielen Dank

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.text.MaskFormatter;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;

public class HangmanGUI {
   private DetailsPanel myPanel;
   private ImagePanel imagePanel = new ImagePanel();

   public HangmanGUI() throws ParseException {
      myPanel = new DetailsPanel();
      JFrame myframe = new JFrame();
      // myframe.getContentPane().setLayout(new BorderLayout());
      myframe.getContentPane().add(imagePanel, BorderLayout.CENTER);
      myframe.getContentPane().add(myPanel, BorderLayout.SOUTH);
      myframe.setTitle("Hangman Game");
      // myframe.setVisible(true);
      // myframe.setLocationRelativeTo(null);
      myframe.pack();
      myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      myframe.setLocationRelativeTo(null);
      myframe.setVisible(true);
   }

   public static void main(String[] args) throws ParseException {
      new HangmanGUI();
   }
}

class ImagePanel extends JPanel {
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private static final String TITLE = "Hangman Image";
   private BufferedImage image;

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public ImagePanel() {
      setBorder(BorderFactory.createTitledBorder(TITLE));
      try {
          image = ImageIO.read(new File("http://upload.wikimedia.org/wikipedia/commons/8/8b/Hangman-0.png"));
      } catch (IOException ex) {
           ex.printStackTrace();
      }

      add(createFormattedPanel(),BorderLayout.SOUTH);
  //add(createFormattedPanel(),BorderLayout.PAGE_END);
   }

   @Override
   protected void paintComponent(Graphics g) {
       super.paintComponent(g);
       g.drawImage(image, 0, 0, null); // siehe javadoc für weitere Informationen zu den Parametern
   }

   public JPanel createFormattedPanel() {
          JPanel panel = new JPanel();
          MaskFormatter formatter = null;
          try {
             JLabel label = new JLabel("Geraten");
             formatter = new MaskFormatter("? ? ? ? ? ? ?");
             formatter.setPlaceholderCharacter('?');
             JFormattedTextField input = new JFormattedTextField(formatter);
             input.setColumns(20);
             panel.add(label);
             panel.add(input);
          } catch (java.text.ParseException exc) {
             System.err.println("formatter ist fehlerhaft: " + exc.getMessage());
             System.exit(-1);
          }

          return panel;
       }

   }

class DetailsPanel extends JPanel {
   public DetailsPanel() {
      setLayout(new BorderLayout());

      setBorder(BorderFactory.createTitledBorder(" Klicke hier "));
      //add(createFormattedPanel(), BorderLayout.PAGE_START);

      JPanel letterPanel = new JPanel(new GridLayout(0, 5));
      for (char alphabet = 'A'; alphabet <= 'Z'; alphabet++) {
         String buttonText = String.valueOf(alphabet);
         JButton letterButton = new JButton(buttonText);
         letterButton.addActionListener(clickedbutton());
         letterPanel.add(letterButton, BorderLayout.CENTER);
      }
      add(letterPanel, BorderLayout.CENTER);
   }

   private ActionListener clickedbutton() {
      return new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            String actionCommand = e.getActionCommand();
            System.out.println("actionCommand ist: " + actionCommand);
         }
      };
   }

}

4voto

MadProgrammer Punkte 334745

Weil Sie benutzerdefiniertes Malen und Komponenten in einer einzigen Komponente mischen, verlieren Sie die Kontrolle darüber, wie Ihre Komponenten angeordnet sind.

Zwei Lösungen kommen in den Sinn...

Verwenden Sie ein JLabel

Verwenden Sie ein JLabel, um das Bild anzuzeigen, platzieren Sie es in der Position CENTER des ImagePane und das "formatierte Panel" in der Position SOUTH

Trennen Sie Ihre Komponenten in logische Gruppen auf

Teilen Sie Ihre Benutzeroberfläche auf, sodass jede Komponente isoliert ist...

-- Hangman-Bild --------------
| --------------------------- |
| | ----------------------- | |
| | |                     | | |
| | |                     | | |
| | | (Bildbereich)       | | |
| | |                     | | |
| | |                     | | |
| | ----------------------- | |
| | ----------------------- | |
| | | Raten: ? ? ? ? ?   | | |
| | ----------------------- | |
| --------------------------- |
| -- hier klicken ----------- |
| |                         | |
| |                         | |
| | (Schaltflächen)         | |
| |                         | |
| |                         | |
| --------------------------- |
-------------------------------

Grundsätzlich sind der ImagePane, der GuessPane und der ClickPane alle separate Komponenten.

Sie würden dann den ImagePane und den GuessPane auf ein weiteres JPanel hinzufügen (unter Verwendung von BorderLayout) und dann dies zusammen mit dem ClickPane auf das Hauptpanel hinzufügen (unter Verwendung von BorderLayout).

Dadurch haben Sie eine bessere Kontrolle darüber, wie die einzelnen Komponenten angeordnet und kombiniert werden können.

\== Beispiel für die Verwendung von JLabel ==

Dies ist ein grundlegendes Beispiel für die Verwendung eines JLabel anstelle von benutzerdefiniertem Malen.

Der ImagePane und der GuessPane werden einem separaten Panel hinzugefügt, das in die Position CENTER des Frames hinzugefügt wird. Das DetailsPane wird dann in die Position SOUTH des Frames hinzugefügt...

Bildbeschreibung hier eingeben

import javax.swing.*;
import javax.swing.text.MaskFormatter;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

public class HangmanGUI {

    private DetailsPanel myPanel;

    public HangmanGUI() throws ParseException {
        myPanel = new DetailsPanel();
        JFrame myframe = new JFrame();

        JPanel content = new JPanel(new BorderLayout());
        content.add(new ImagePane());
        content.add(new GuessPane(), BorderLayout.SOUTH);
        content.setBorder(BorderFactory.createTitledBorder("Hangman-Bild"));

        myframe.getContentPane().add(content, BorderLayout.CENTER);
        myframe.getContentPane().add(myPanel, BorderLayout.SOUTH);
        myframe.setTitle("Galgenmännchen-Spiel");
        myframe.pack();
        myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myframe.setLocationRelativeTo(null);
        myframe.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
                try {
                    new HangmanGUI();
                } catch (ParseException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class ImagePane extends JPanel {

        private JLabel label;

        public ImagePane() {
            setLayout(new BorderLayout());
            label = new JLabel();
            add(label);
            try {
                label.setIcon(new ImageIcon(ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/commons/8/8b/Hangman-0.png"))));
            } catch (IOException ex) {
                label.setText("Schlechtes Bild");
                ex.printStackTrace();
            }
        }

    }

    public static class GuessPane extends JPanel {

        public GuessPane() {
            MaskFormatter formatter = null;
            try {
                JLabel label = new JLabel("Raten");
                formatter = new MaskFormatter("? ? ? ? ? ? ?");
                formatter.setPlaceholderCharacter('?');
                JFormattedTextField input = new JFormattedTextField(formatter);
                input.setColumns(20);
                add(label);
                add(input);
            } catch (java.text.ParseException exc) {
                System.err.println("formatter ist falsch: " + exc.getMessage());
                System.exit(-1);
            }
        }

    }

    public static class DetailsPanel extends JPanel {

        public DetailsPanel() {
            setLayout(new BorderLayout());

            setBorder(BorderFactory.createTitledBorder("hier klicken"));
            //add(createFormattedPanel(), BorderLayout.PAGE_START);

            JPanel letterPanel = new JPanel(new GridLayout(0, 5));
            for (char alphabet = 'A'; alphabet <= 'Z'; alphabet++) {
                String buttonText = String.valueOf(alphabet);
                JButton letterButton = new JButton(buttonText);
                letterButton.addActionListener(clickedbutton());
                letterPanel.add(letterButton, BorderLayout.CENTER);
            }
            add(letterPanel, BorderLayout.CENTER);
        }

        private ActionListener clickedbutton() {
            return new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    String actionCommand = e.getActionCommand();
                    System.out.println("actionCommand ist: " + actionCommand);
                }
            };
        }

    }
}

Diese Art der Trennung erfordert die Verwendung eines Modells zur Brücke zwischen den Komponenten.

Das heißt, wenn der Benutzer eine Vermutung anstellt, müssen Sie das Modell aktualisieren, das die anderen Komponenten über Änderungen informiert (über eine Art Listener-API). Dies ermöglicht es den anderen UI-Elementen, sich entsprechend den Anforderungen des Modells zu aktualisieren.

Das Modell sollte die Logik des Spiels enthalten und die Benutzeroberfläche steuern.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X