1

I'm trying to write a Main Menu for my game in Java Swing. I have a general View class and a separate MainMenuView class. In my View class, which extends JFrame, I created a Jpanel named cards which has CardLayout. cards' first "card" is my Main Menu.
Here comes the important part: I override the paintComponent(Graphics g) method to use drawImage() method. It draws the image I want, but it kind of crops it from each side.

Here is how I override the paintComponent(Graphics g) method:

@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);
}

An additional question: the antialiasing also doesn't work on the drawn image.

Thanks in advance for you answers!

Edit: I'm posting my full code down below:

View.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);
    }
}

MainMenuView.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);
    }
}

The MainMenuSurface.java class which contains some buttons(not neccessary for the question) :

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;
    }
}

And here is my 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);
        });
    }
}

Edit 2: I found what was wrong. I had to use the ```drawImage()`` method, by giving not only x and y, but also the width and height.

olimpiabaku
  • 151
  • 11
  • Anti-aliasing only works on pixels you draw with a Graphics or Graphics2D method. Please post a [mre] that we can copy into our IDE, test, and possibly tell you what you coded incorrectly. – Gilbert Le Blanc May 09 '21 at 16:13
  • Thanks for mentioning about the **minimal reproducible example**, I'm adding it right now to my quesiton – olimpiabaku May 09 '21 at 16:18
  • 3
    One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). E.G. The code in [this answer](https://stackoverflow.com/a/10862262/418556) hot links to an image embedded in [this question](https://stackoverflow.com/q/10861852/418556). But as a tip on the code shown. **Don't load images from within a paint method!** Declare them as an attribute of the class and load them when it is constructed. – Andrew Thompson May 09 '21 at 16:25
  • That code is NOT an [mre], it is a dump of your application. Looks like you are attempting to paint the image as a background. Well the size of the panel is determined by the size of the components added to the panel. Since the components are smaller than the image, part of the image is cropped. Read the drawImage(...) API. You can provide more parameters so the image will be scaled to the size of the panel. – camickr May 09 '21 at 16:29

1 Answers1

0

1 - load the image before paintComponent is called - this method can be called very often to actualize the component (e.g. scrolling, redrawing, .... ) (unless the image file is being changed and must be reloaded, and even then it is probably wrong to read it in that method)

2 - ImageIcon to load an image is not the best way - I think it does not block while the image is being loaded. I recommend using ImageIO

written before the question was updated/browser cache updated