JPanel falsch positioniert

Ich habe ein Spiel in Java gemacht, wo du einen zufällig generierten int zwischen 1 und 100 erraten sollst. Wenn Sie zu niedrig geraten, wird ein Textfeld mit einem Text gefüllt, der “zu niedrig”, aber auf Schwedisch lautet. Gleiches, wenn Sie zu hoch geraten.

Das Problem tritt auf, wenn die Antwort richtig ist, rufe ich dann eine Methode auf, um ein unsichtbares JPanel sichtbar zu machen. Das funktioniert ganz gut, aber das Jpanel selbst wird nicht an die Spitze gehen, wo es sein sollte. Und es muss perfekt passen, da es nur ein Foto-Hintergrundbild ist. Die Eigenschaften des Hintergrunds sind: 1920 x 1080. Die Eigenschaften des Photoshop-GG WP sind 1920 x 297. Die Jpane heißt “Grattis”

Ich hoffe, ich habe nichts Wichtiges verpasst und schätze all die Hilfe, die ich bekommen kann, denn ich stecke jetzt fest.

Ps. Sorry für das schlechte Englisch und Formatierung.

package slumpatal; import java.util.Random; //This class runs the program, the main method is here. public class SlumpaTal extends callback1 { private int randomTal; Random random = new Random(); @Override public int SetValue(int value) { if (value < randomTal) return -1; else if (value == randomTal) return 0; else return 1; } //private JFrame1 frame; SlumpaTal() { GenerateRandomNumber(); JFrame1.createWindow(this); } public void GenerateRandomNumber() { randomTal = random.nextInt(100) + 1; } public static void main(String[] args) { new SlumpaTal(); } } 

.

 package slumpatal; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.*; public class JFrame1 { //public static int dittSvar; public static void createWindow(callback1 callbackArg) { //Font font = new Font("Verdana", Font.BOLD,28); JFrame frame = new JFrame("Gissa ett Tal mellan 1-100"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel contentPane = new JPanel(); contentPane.setOpaque(true); contentPane.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, Color.WHITE)); contentPane.setBackground(Color.WHITE); contentPane.setLayout(new BorderLayout(10, 10)); ImagePanel imagePanel = new ImagePanel(callbackArg); //frame properties contentPane.add(imagePanel, BorderLayout.CENTER); frame.setContentPane(contentPane); frame.setSize(1000, 600); frame.setVisible(true); } } class ImagePanel extends JPanel { callback1 callback; public int dittSvar; private BufferedImage image; JButton restartApp; JTextField dittSvarText1; JTextField dittRes1; BufferedImage myPicture; public JPanel grattis; public ImagePanel(callback1 callbackArg) { try { myPicture = ImageIO.read(new URL("https://imagizer.imageshack.us/v2/1375x213q90/843/r7f8.jpg")); } catch (Exception ex) { System.err.print("No reward image"); } callback = callbackArg; setOpaque(true); setBorder(BorderFactory.createLineBorder(Color.BLACK, 5)); try { image = ImageIO.read(new URL("http://sofde.miximages.com/java/v8k3.jpg")); } //If it doesn't work, write an error message, printStackTrace. catch (IOException e) { System.err.printf("%s", e.toString()); e.printStackTrace(); } createGUI(); createGUI2(); dittSvarText1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dittSvar = Integer.parseInt(dittSvarText1.getText()); int res = callback.SetValue(dittSvar); if (res < 0) dittRes1.setText("För lågt"); else if (res == 0) { dittRes1.setText("Rätt Svar!!!!"); makeItVisible(); } else dittRes1.setText("För Högt"); dittSvarText1.setText(""); } }); restartApp.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { callback.GenerateRandomNumber(); dittSvarText1.setText(null); dittRes1.setText(null); grattis.setVisible(false); } }); } public void makeItVisible() { System.out.print("Showing reward image"); grattis = new JPanel(); grattis.setOpaque(false); grattis.setLayout(new FlowLayout(FlowLayout.LEFT)); if (myPicture != null) { JLabel picLabel = new JLabel(new ImageIcon(myPicture)); //picLabel.setLocation(new Point(0,0)); picLabel.setLocation(new Point(0, 0)); // picLabel.setSize(1000,297); // grattis.setLocation(0, 0); picLabel.setVerticalAlignment(WIDTH); grattis.setVisible(true); grattis.setSize(1000, 600); grattis.add(picLabel); add(grattis); updateUI(); } else { System.err.print("No picture created!"); } } public void createGUI() { setLayout(new GridBagLayout()); JPanel panel1 = new JPanel(); panel1.setOpaque(false); panel1.setLayout(new GridLayout(2, 2, 2, 2)); JLabel skrivdingissning = new JLabel("Skriv din gissning här : "); skrivdingissning.setForeground(Color.WHITE); dittSvarText1 = new JTextField(10); JLabel VadBlevDet = new JLabel("Vad blev det : "); VadBlevDet.setForeground(Color.WHITE); dittRes1 = new JTextField(10); panel1.add(skrivdingissning); panel1.add(dittSvarText1); panel1.add(VadBlevDet); panel1.add(dittRes1); add(panel1); } public void createGUI2() { JPanel panel2 = new JPanel(); panel2.setLocation(100, 500); panel2.setOpaque(false); restartApp = new JButton("Starta om"); restartApp.setLocation(100, 500); restartApp.setBackground(Color.WHITE); panel2.add(restartApp); // add(panel2); } @Override public Dimension getPreferredSize() { return (new Dimension(300, 300)); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); //g.drawImage(image, 0,0,this); } } abstract class callback1 { abstract int SetValue(int value); abstract void GenerateRandomNumber(); } 

Ich habe dein gesamtes Projekt umgeschrieben. Sie können das Englische ins Schwedische übersetzen.

Hier sind ein paar Screenshots des Spiels.

Spiel erraten 1

Spiel erraten 2

Ich habe ein Modell / Ansicht / Controller-Muster verwendet, um das Projekt zu programmieren. Dies trennt Probleme und erleichtert es, sich auf einen Teil des Projekts zu konzentrieren.

Hier sind die Bilder, die ich benutzt habe.

Hintergrundbild

Sieg Bild

Hier ist der Package Explorer von Eclipse, der die Organisation des Java Swing-Projekts zeigt.

Eclipse-Paket-Explorer

Und hier ist der Code. Ich habe eine Modellklasse und 4 Sichtklassen geschrieben. Der Controller ist eine anonyme class innerhalb einer der Ansichtsklassen.

Dies ist die Haupt-GuessingGame-class.

 package com.ggl.guessing.game; import javax.swing.SwingUtilities; import com.ggl.guessing.game.model.GuessingGameModel; import com.ggl.guessing.game.view.GuessingGameFrame; public class GuessingGame implements Runnable { @Override public void run() { new GuessingGameFrame(new GuessingGameModel(1, 100)); } public static void main(String[] args) { SwingUtilities.invokeLater(new GuessingGame()); } } 

Kurz und bündig. Diese class macht 3 Dinge.

  1. Verschiebt die Swing-GUI in den Event Dispatch-Thread (EDT), indem die SwingUtilities-Methode invokeLater aufgerufen wird.
  2. Instantiiert das GUI-Modell.
  3. Instanziiert den GUI-JFrame.

Als nächstes schauen wir uns die Modellklasse an

 package com.ggl.guessing.game.model; import java.util.Random; public class GuessingGameModel { private int lowerLimit; private int upperLimit; private int randomNumber; private int numberOfGuesses; private Random random; public GuessingGameModel(int lowerLimit, int upperLimit) { this.random = new Random(); init(lowerLimit, upperLimit); } public void init(int lowerLimit, int upperLimit) { this.lowerLimit = lowerLimit; this.upperLimit = upperLimit; this.numberOfGuesses = 0; this.randomNumber = random.nextInt(upperLimit - lowerLimit + 1) + lowerLimit; } public int guess(int guess) { this.numberOfGuesses++; if (guess < randomNumber) { return -1; } else if (guess > randomNumber) { return 1; } else { return 0; } } public int getNumberOfGuesses() { return numberOfGuesses; } public String getFrameTitle() { return "Gissa ett Tal mellan " + lowerLimit + " - " + upperLimit; } } 

Diese class speichert die Spielinformationen und bietet eine bequeme Methode für den Titel. Sie können die untere und obere Grenze für die Zufallszahl festlegen, sodass Sie in Zukunft andere Bereiche hinzufügen können.

Kommen wir nun zur GUI selbst. Dies ist die GuessingGameFrame-class.

 package com.ggl.guessing.game.view; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; import com.ggl.guessing.game.model.GuessingGameModel; public class GuessingGameFrame { private GameImages gameImages; private GuessingGameModel model; private GuessingGamePanel ggPanel; private JFrame frame; public GuessingGameFrame(GuessingGameModel model) { this.model = model; this.gameImages = new GameImages(); createPartControl(); } private void createPartControl() { frame = new JFrame(); frame.setTitle(model.getFrameTitle()); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent event) { exitProcedure(); } }); Dimension d = sizeGuessesPanel(); ggPanel = new GuessingGamePanel(this, model, gameImages, d); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new FlowLayout()); mainPanel.add(ggPanel); frame.setLayout(new FlowLayout()); frame.add(mainPanel); // frame.setSize(640, 480); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } private Dimension sizeGuessesPanel() { GuessesPanel guessesPanel = new GuessesPanel(this, model); frame.setLayout(new FlowLayout()); frame.add(guessesPanel.getPanel()); frame.pack(); Dimension d = guessesPanel.getPanel().getSize(); guessesPanel.setPreferredSize(d); frame.remove(guessesPanel.getPanel()); return d; } public void exitProcedure() { frame.dispose(); System.exit(0); } public void setGuessed(boolean guessed) { ggPanel.setGuessed(guessed); } } 

Ziemlich Standard-Swing, außer für die sizeGuessesPanel-Methode. Um das Panel in der Mitte des Hintergrundbildes zu platzieren, muss ich wissen, wie groß es ist. Das sizeGuessesPanel verwendet JFrame-Packing, um mir die Größe mitzuteilen.

Die Methode setGuessed ist eine bequeme Methode, mit der ich das boolesche Flag im JPanel setzen kann, um das Siegbild zu zeichnen. Der Controller muss nicht über den JPanel Bescheid wissen.

Als nächstes schauen wir uns die GameImages-class an.

 package com.ggl.guessing.game.view; import java.awt.Dimension; import java.awt.Image; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; public class GameImages { private Image backgroundImage; private Image victoryImage; public GameImages() { readBackgroundImage(); readVictoryImage(); } private void readBackgroundImage() { Image image = null; try { URL url = getClass().getResource("/v8k3reduced.jpg"); image = ImageIO.read(url); } catch (IOException e) { e.printStackTrace(); } this.backgroundImage = image; } private void readVictoryImage() { Image image = null; try { URL url = getClass().getResource("/r7f8reduced.jpg"); image = ImageIO.read(url); } catch (IOException e) { e.printStackTrace(); } this.victoryImage = image; } public Image getBackgroundImage() { return backgroundImage; } public Dimension getPreferredSize() { return new Dimension(backgroundImage.getWidth(null), backgroundImage.getHeight(null)); } public Image getVictoryImage() { return victoryImage; } } 

Diese class liest die Bilder aus einem Bilderordner, der im Java-Erstellungspfad abgelegt ist. Dies stellt sicher, dass die Bilder sowohl aus Eclipse gelesen werden können, als auch wenn die Bilder in einer Java-Archivdatei (JAR) gepackt sind.

Als nächstes schauen wir uns das GuessingGamePanel an.

 package com.ggl.guessing.game.view; import java.awt.Dimension; import java.awt.Graphics; import javax.swing.JPanel; import com.ggl.guessing.game.model.GuessingGameModel; public class GuessingGamePanel extends JPanel { private static final long serialVersionUID = -2429103448910749064L; private boolean guessed; private Dimension guessesPanelDimension; private GameImages gameImages; private GuessesPanel guessesPanel; private GuessingGameFrame frame; private GuessingGameModel model; public GuessingGamePanel(GuessingGameFrame frame, GuessingGameModel model, GameImages gameImages, Dimension guessesPanelDimension) { this.frame = frame; this.model = model; this.gameImages = gameImages; this.guessesPanelDimension = guessesPanelDimension; this.guessed = false; createPartControl(); } private void createPartControl() { this.setLayout(null); this.setPreferredSize(gameImages.getPreferredSize()); guessesPanel = new GuessesPanel(frame, model); Dimension gp = guessesPanelDimension; Dimension tp = gameImages.getPreferredSize(); int x = (tp.width - gp.width) / 2; int y = (tp.height - gp.height) / 2; guessesPanel.getPanel().setBounds(x, y, gp.width, gp.height); this.add(guessesPanel.getPanel()); } public void setGuessed(boolean guessed) { this.guessed = guessed; repaint(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(gameImages.getBackgroundImage(), 0, 0, null); if (guessed) { g.drawImage(gameImages.getVictoryImage(), 0, 0, null); } } } 

Wir erweitern ein JPanel, weil wir die JPanel paintComponent-Methode überschreiben.

In der createPartControl-Methode werden Sie feststellen, dass ich ein Null-Layout verwende. Ein Null-Layout sollte nur mit der Aufsicht und Genehmigung eines Swing-Experten verwendet werden. In diesem Fall war es die einzige Möglichkeit, die Größe und Position des GuestsPanel zu kontrollieren.

Schließlich betrachten wir die GuestsPanel-class.

 package com.ggl.guessing.game.view; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import com.ggl.guessing.game.model.GuessingGameModel; public class GuessesPanel { private static final Insets finalInsets = new Insets(6, 6, 6, 6); private Dimension preferredSize; private GuessingGameFrame frame; private GuessingGameModel model; private JPanel panel; private JTextField dittSvarText1; private JTextField dittRes1; private JTextField guessesField; public GuessesPanel(GuessingGameFrame frame, GuessingGameModel model) { this.frame = frame; this.model = model; createPartControl(); } private void createPartControl() { panel = new JPanel(); panel.setBackground(Color.YELLOW); panel.setLayout(new FlowLayout()); JPanel insidePanel = new JPanel(); insidePanel.setLayout(new GridBagLayout()); int gridy = 0; JLabel guessLabel = new JLabel("Skriv din gissning här:"); addComponent(insidePanel, guessLabel, 0, gridy, 1, 1, finalInsets, GridBagConstraints.LINE_START, GridBagConstraints.NONE); dittSvarText1 = new JTextField(10); dittSvarText1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { int guess = Integer.valueOf(dittSvarText1.getText()); int lowHigh = model.guess(guess); if (lowHigh < 0) { dittRes1.setText("För lågt"); } else if (lowHigh > 0) { dittRes1.setText("För Högt"); } else { dittRes1.setText("Rätt Svar!!!!"); frame.setGuessed(true); } guessesField.setText(Integer.toString( model.getNumberOfGuesses())); dittSvarText1.setSelectionStart(0); dittSvarText1.setSelectionEnd( dittSvarText1.getText().length()); } }); addComponent(insidePanel, dittSvarText1, 1, gridy++, 1, 1, finalInsets, GridBagConstraints.LINE_START, GridBagConstraints.NONE); JLabel responseLabel = new JLabel("Vad blev det:"); addComponent(insidePanel, responseLabel, 0, gridy, 1, 1, finalInsets, GridBagConstraints.LINE_START, GridBagConstraints.NONE); dittRes1 = new JTextField(10); dittRes1.setEditable(false); addComponent(insidePanel, dittRes1, 1, gridy++, 1, 1, finalInsets, GridBagConstraints.LINE_START, GridBagConstraints.NONE); JLabel guessesLabel = new JLabel("Number of guesses:"); addComponent(insidePanel, guessesLabel, 0, gridy, 1, 1, finalInsets, GridBagConstraints.LINE_START, GridBagConstraints.NONE); guessesField = new JTextField(10); guessesField.setEditable(false); addComponent(insidePanel, guessesField, 1, gridy++, 1, 1, finalInsets, GridBagConstraints.LINE_START, GridBagConstraints.NONE); panel.add(insidePanel); } private void addComponent(Container container, Component component, int gridx, int gridy, int gridwidth, int gridheight, Insets insets, int anchor, int fill) { GridBagConstraints gbc = new GridBagConstraints(gridx, gridy, gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, insets, 0, 0); container.add(component, gbc); } public void setPreferredSize(Dimension preferredSize) { panel.setPreferredSize(preferredSize); panel.setMaximumSize(preferredSize); panel.setMinimumSize(preferredSize); this.preferredSize = preferredSize; } public Dimension getPreferredSize() { return preferredSize; } public JPanel getPanel() { return panel; } } 

Dies ist ein ziemlich normales JPanel, das ein GridBagLayout verwendet. Die addComponent-Methode erstellt eine GridBagConstraints für jede Swing-Komponente. Ein GridBagLayout ist das Layout, das verwendet werden soll, wenn Sie Beschriftungen und Felder ausrichten möchten.

Der Haupt- und einzige Controller ist eine anonyme Aktion Listener-class innerhalb dieser class.

Ich habe mehr classn erstellt als du und hast den Code anders angeordnet als du. Studieren Sie den Code und sehen Sie, ob er Ihnen hilft, MVC besser zu verstehen und eine Swing-Anwendung zu programmieren.