java - 设置对象/图像在背景上的位置

标签 java user-interface graphics

我目前正在开发 Ludo/Dude 游戏的一个版本,不要生气,我遇到了一些问题,其中一个更大的问题是我无法将 token 放置在我想要的位置是。我需要在开始时将标记设置在某些位置,并且需要一种方法来计算将它们移动到屏幕上的位置,这里是代码:

public class Ludo extends JFrame{

   private BackgroundPanel imagePanel=null;
   private JLabel jlTokenBlue1=null;
   private JLabel jlTokenBlue2=null;
   ...

   public Ludo(){
          try{         
         //Creating background panel  
         imagePanel = new BackgroundPanel("ludoBoard.png");
         add(imagePanel);

         //create tokens for play
         BufferedImage imageTokenBlue1 = ImageIO.read(new File("blue1.png"));
         jlTokenBlue1 = new JLabel(new ImageIcon(imageTokenBlue1));

         BufferedImage imageTokenBlue2 = ImageIO.read(new File("blue2.png"));
         jlTokenBlue2 = new JLabel(new ImageIcon(imageTokenBlue2));

         BufferedImage imageTokenBlue3 = ImageIO.read(new File("blue3.png"));
         jlTokenBlue3 = new JLabel(new ImageIcon(imageTokenBlue3));

         BufferedImage imageTokenBlue4 = ImageIO.read(new File("blue4.png"));
         jlTokenBlue4 = new JLabel(new ImageIcon(imageTokenBlue4));

         BufferedImage imageTokenRed1 = ImageIO.read(new File("red1.png"));
         jlTokenRed1 = new JLabel(new ImageIcon(imageTokenRed1));

         BufferedImage imageTokenRed2 = ImageIO.read(new File("red2.png"));
         jlTokenRed2 = new JLabel(new ImageIcon(imageTokenRed2));

         BufferedImage imageTokenRed3 = ImageIO.read(new File("red3.png"));
         jlTokenRed3 = new JLabel(new ImageIcon(imageTokenRed3));

         BufferedImage imageTokenRed4 = ImageIO.read(new File("red4.png"));
         jlTokenRed4 = new JLabel(new ImageIcon(imageTokenRed4));

         imagePanel.add(jlTokenBlue1);
         imagePanel.add(jlTokenBlue2);
         imagePanel.add(jlTokenBlue3);
         imagePanel.add(jlTokenBlue4);
         imagePanel.add(jlTokenRed1);
         imagePanel.add(jlTokenRed2);
         imagePanel.add(jlTokenRed3);
         imagePanel.add(jlTokenRed4);

         jlTokenRed1.setLocation(250,500);
         }//End of try
      catch(IOException ioe){
         System.out.println("The background image cannot be loaded...");
      }catch(NullPointerException npe){
         npe.getMessage();
      }
.
.
.
class BackgroundPanel extends JPanel
{
  Image image;
  public BackgroundPanel(String imageName)
  {
    try
    {
      image = javax.imageio.ImageIO.read(new java.net.URL(getClass().getResource(imageName), imageName));
    }
    catch (Exception e) { /*handled in paintComponent()*/ }
  }

  @Override
  protected void paintComponent(Graphics g)
  {
    super.paintComponent(g); 
    if (image != null)
      g.drawImage(image, 0,0,this.getWidth(),this.getHeight(),this);
  }
}

我尝试使用 setLocation 和 repaint 但无法将 token 设置为放置在我想要的位置。我想将 token 以其各自的颜色放入白色字段中,非常感谢任何帮助和/或建议。下面是它现在的样子。 如果您想自己检查文件,这里是包含所有内容的驱动器的链接。 drive.google.com/open?id=1xap_xz2K3SF37XQfRN3Y_LHoTHg0HNox !

İmage

最佳答案

我已经为您的游戏编写了一些代码。您必须完成代码。

这是我创建的 GUI。

Ludo  board

我做的第一件事就是雇用 model / view / controller图案。通过分离游戏的逻辑功能,我可以一次专注于一个部分。

这是我创建的模型。它并不完整,但我想你可以看到我正在尝试做的事情。我把他的类放在自己的模型包中。

package com.ggl.ludo.model;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;

public class LudoModel {

    private final BufferedImage gameBoard;

    private final BufferedImage[] imageTokenBlue;

    public LudoModel() {
        imageTokenBlue = new BufferedImage[4];
        imageTokenBlue[0] = getImage("blue1.png");
        imageTokenBlue[1] = getImage("blue2.png");
        imageTokenBlue[2] = getImage("blue3.png");
        imageTokenBlue[3] = getImage("blue4.png");
        gameBoard = getImage("ludoBoard.png");
    }

    public BufferedImage getGameBoard() {
        return gameBoard;
    }

    public BufferedImage[] getImageTokenBlue() {
        return imageTokenBlue;
    }

    private BufferedImage getImage(String fileName) {
        try {
            return ImageIO.read(getClass().getResourceAsStream("/" + fileName));
        } catch (IOException e) {
            return null;
        }
    }

}

所有这些代码所做的就是读取图像,并最终创建游戏的逻辑模型。它根本不关心 View 或 Controller 代码。

我创建的下一个类是 DrawingPanel 类。本类(class)绘制游戏棋盘,并最终在棋盘上绘制棋子。碎片信息的位置进入模型。

package com.ggl.ludo.view;

import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JPanel;

import com.ggl.ludo.model.LudoModel;

public class DrawingPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    private LudoFrame frame;

    private LudoModel model;

    public DrawingPanel(LudoFrame frame, LudoModel model) {
        this.frame = frame;
        this.model = model;
        int width = model.getGameBoard().getWidth();
        int height = model.getGameBoard().getHeight();
        this.setPreferredSize(new Dimension(width, height));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(model.getGameBoard(), 0, 0, this);
        // Your piece drawing code goes here
    }

}

接下来,我创建了一个类来保存 JFrame。 JScrollPane 代码可以删除。我的旧笔记本电脑无法显示像你的那么大的游戏板。如果您希望其他人玩这个游戏,请记住一些事情。

我将菜单代码放在它自己的方法中。我喜欢将不同的事物分开。我弱小的头脑无法同时处理太多的进程。

package com.ggl.ludo.view;

import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;

import com.ggl.ludo.model.LudoModel;

public class LudoFrame {

    private DrawingPanel drawingPanel;

    private LudoModel ludoModel;

    public LudoFrame(LudoModel ludoModel) {
        this.ludoModel = ludoModel;
        generateGUIControl();
    }

    private void generateGUIControl() {
        JFrame frame = new JFrame("Ludo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(createMenu());

        drawingPanel = new DrawingPanel(this, ludoModel);
        JScrollPane scrollPane = new JScrollPane(drawingPanel);
        scrollPane.setPreferredSize(new Dimension(400, 400));

        frame.add(scrollPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JMenuBar createMenu() {
        JMenuBar ludoMenuBar = new JMenuBar();
        JMenu ludoMenuFirst = new JMenu("Information");
        ludoMenuBar.add(ludoMenuFirst);

        JMenuItem jmiDescription = new JMenuItem("Description");
        JMenuItem jmiHelp = new JMenuItem("Help");
        JMenuItem jmiRestart = new JMenuItem("Restart");
        JMenuItem jmiExit = new JMenuItem("Exit");

        ludoMenuFirst.add(jmiDescription);
        ludoMenuFirst.add(jmiHelp);
        ludoMenuFirst.add(jmiRestart);
        ludoMenuFirst.add(jmiExit);
        ludoMenuBar.add(ludoMenuFirst);
        return ludoMenuBar;
    }
}

最后是启动整个过程的驱动程序类。您必须在事件调度线程 (EDT) 上启动 Swing 应用程序。对 SwingUtilities invokeLater 的调用可确保您的应用程序在 EDT 上启动。

package com.ggl.ludo;

import javax.swing.SwingUtilities;

import com.ggl.ludo.model.LudoModel;
import com.ggl.ludo.view.LudoFrame;

public class Ludo implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Ludo());
    }

    @Override
    public void run() {
        new LudoFrame(new LudoModel());
    }
}

希望这对您有所帮助。至于 Controller ,我建议您使用鼠标监听器并在游戏板上绘制游戏棋子。

请记住,有关游戏棋子位置的信息会进入模型。 View 绘制代码从模型中的信息中提取。

关于java - 设置对象/图像在背景上的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60569836/

相关文章:

java - 使用 Scene Builder 8.0 在 JavaFX 中使用 setCenter() 方法获取空指针异常

java - Spring boot 2.1 error.html 页面不显示

java - 通用类型的访问者被调用错误的类型

user-interface - 在 Unity 中创建一个螺旋形 UI 栏

java - 如何使所有 JFrame 都可以访问 ArrayList 以及如何更新它?

math - 蒙特卡罗路径追踪算法这部分的目的是什么?

graphics - 模拟老式 Sprite 的闪烁(理论和概念)

java - 奇怪的 SQLite 行为 - 非功能性 UPDATE SQLite 方法

android - 将 iPhone 图形移植到 Android 时有经验法则吗?

python - 在 OpenGL 和 Pygame 中旋转 3D 立方体时出现问题