首页 > 解决方案 > drawImage() 方法未在 Java Swing 中完全绘制图像

问题描述

我正在尝试用 Java Swing 为我的游戏编写主菜单。我有一个普通View班和一个单独的MainMenuView班。在我View的扩展类中,JFrame我创建了Jpanel一个具有CardLayout. 卡片的第一个“卡片”是我的主菜单
重要的部分来了:我重写了paintComponent(Graphics g)使用方法的drawImage()方法。它绘制了我想要的图像,但它会从每一侧进行裁剪。

这是我覆盖该paintComponent(Graphics g)方法的方式:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    Image img = new ImageIcon("Project_2_files/menu_background.png").getImage();
    g2d.drawImage(img, 0, 0, this);
}

另一个问题:抗锯齿也不适用于绘制的图像。

提前感谢您的回答!

编辑:我在下面发布我的完整代码:

查看.java:

import javax.swing.*;
import java.awt.*;

public class View extends JFrame {
    private final MainMenuModel mainMenuModel;
    public MainMenuView mainMenuView;

    public MainMenuView getMainMenuView() {
        return mainMenuView;
    }

    public void setMainMenuView(MainMenuView mainMenuView) {
        this.mainMenuView = mainMenuView;
    }

    public View(MainMenuModel mainMenuModel) {
        this.mainMenuModel = mainMenuModel;
        mainMenuView = new MainMenuView(mainMenuModel);

        CardLayout cl = new CardLayout();
        JPanel cards = new JPanel();//the main panel which contains all other panels

        JPanel mainMenuCard = mainMenuView;//panel card for main menu

        add(cards);
        cards.setLayout(cl);
        cards.add(mainMenuCard);
        cl.show(cards, "abc");

        pack();

        setVisible(true);
        setTitle("__Main_View__");
        setSize(new Dimension(1280,720));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
}

主菜单视图.java:

import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;

public class MainMenuView extends JPanel {
    private MainMenuModel model;
    public MainMenuSurface surface;

    public MainMenuModel getModel() {
        return model;
    }

    public void setModel(MainMenuModel model) {
        this.model = model;
    }

    public MainMenuView(MainMenuModel model) {
        this.model = model;

        surface = new MainMenuSurface(model);
        JLabel label1 = new JLabel("AntiPlague", SwingConstants.CENTER);
        label1.setFont(new Font("Serif", Font.PLAIN, 25));
        label1.setBorder(new LineBorder(Color.GREEN));

        GridBagConstraints c = new GridBagConstraints();

        c.fill = GridBagConstraints.BOTH;
        c.gridx = 0;
        c.gridy = 1;
        c.weightx = 0.5;
        c.insets = new Insets(150,0,150,0);

        GridBagConstraints b = new GridBagConstraints();

        b.fill = GridBagConstraints.BOTH;
        b.weightx = 0.5;
        b.gridx = 0;
        b.gridy = 0;
        b.anchor = GridBagConstraints.CENTER;

        setLayout(new GridBagLayout());
        add(surface, c);
        add(label1, b);
        setVisible(true);
        setBounds(0,0,1280,720);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        Image img = new ImageIcon("Project_2_files/menu_background.png").getImage();
        g2d.drawImage(img, 0, 0, this);
    }
}

包含一些按钮的MainMenuSurface.java类(不是问题所必需的):

import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;

public class MainMenuSurface extends JPanel {
    private MainMenuModel model;
    private JButton btnNewGame, btnHighScores, btnExit;

    public MainMenuSurface(MainMenuModel model) {
        this.model = model;

        btnNewGame = new JButton(model.choices[0]);
        btnHighScores = new JButton(model.choices[1]);
        btnExit = new JButton(model.choices[2]);

        add(Box.createVerticalGlue());

        add(btnNewGame);
        add(Box.createRigidArea(new Dimension(0, 15)));
        add(btnHighScores);
        add(Box.createRigidArea(new Dimension(0, 15)));
        add(btnExit);

        btnNewGame.setAlignmentX(CENTER_ALIGNMENT);
        btnHighScores.setAlignmentX(CENTER_ALIGNMENT);
        btnExit.setAlignmentX(CENTER_ALIGNMENT);

        add(Box.createVerticalGlue());

        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        setVisible(true);
        setBorder(new LineBorder(Color.BLACK));
        setOpaque(false);
    }

    public JButton getBtnNewGame() {
        return btnNewGame;
    }

    public JButton getBtnExit() {
        return btnExit;
    }
}

这是我的main.java :

import java.awt.*;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        EventQueue.invokeLater(() -> {//for concurrency-safety purposes
            MainMenuModel mainMenuModel = new MainMenuModel();
            View ex = new View(mainMenuModel);
            MainMenuController mainMenuController = new MainMenuController(mainMenuModel, ex);
            mainMenuController.initController();
            ex.setVisible(true);
        });
    }
}

编辑2:我发现出了什么问题。我必须使用```drawImage()` 方法,不仅要给出x 和y,还要给出宽度和高度。

标签: javaswing

解决方案


1 - 在调用之前加载图像paintComponent- 可以经常调用此方法来实现组件(例如滚动,重绘,......)(除非图像文件正在更改并且必须重新加载,即使这样也可能用那种方法读错了)

2 -ImageIcon加载图像不是最好的方法 - 我认为在加载图像时它不会阻塞。我建议使用ImageIO

在问题更新/浏览器缓存更新之前写


推荐阅读