0

I'm trying to make a Java Swing calculator application, and I want to make my own set of GUI(Based on original Swing), but I've got some problems with the menu & menu item. I've tried searching on the internet, but all I get is how to add menu to your app. I want to make one on my own. What can I do?

See the code below

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

/**
 * The base menu item that can click on, achieve the functions.
 * Display on a MyMenu.
 *
 * @see MyMenuBar
 * @see MyMenu
 * @author abc, 2022/2/19
 */
public class MyMenuItem extends JMenuItem {

    DefaultButtonModel model = (DefaultButtonModel) this.getModel();

    /**
     * The constructor. Creates a menu item with a text.
     *
     * @param text The String text to be displayed on the Item.
     */
    public MyMenuItem(String text) {
        setFocusPainted(false);
        setBorderPainted(false);
        setForeground(Color.WHITE);
        setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        setText(text);
    }

    /**
     * The constructor that creates an Item with text & icon.
     *
     * @param icon The icon to be displayed.
     * @param text The text to be displayed.
     */
    public MyMenuItem(ImageIcon icon, String text) {
        setFocusPainted(false);
        setBorderPainted(false);
        setForeground(Color.WHITE);
        setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        setText(text);
        setIcon(icon);
    }

    @Override
    protected void paintComponent(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(MyFrame.baseColor);
        g2d.fillRect(0, 0, getWidth(), getHeight());

        if (model.isPressed()) {
            g2d.setColor(new Color(55, 40, 150));
            g2d.fillRect(0, 0, getWidth(), getHeight());
        }

        super.paintComponent(g);
    }
}

MyMenu code (unfinished):

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

/**
 * The base class that forms a menu. Will be used to call out Settings &
 * modes. Displays on top, in a menu bar.
 *
 * @see MyMenuBar
 * @author abc, 2022/2/18 - 2022
 */
public class MyMenu extends JMenu {

    public MyMenu(String s) {
        setContentAreaFilled(false);
        setFont(new Font("Consolas", Font.PLAIN, 18));
        setForeground(Color.WHITE);
        setText(s);
    }

    @Override
    protected void paintComponent(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setColor(new Color(34, 36, 54));
        g2d.fillRect(2, 2, this.getWidth() - 5, this.getHeight() - 5);

        if (isSelected()) {
            g2d.setColor(new Color(34, 36, 54));
            g2d.fillRect(0, 0, getWidth(), getHeight());
        }

    }
}

MyMenuBar code:

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

/**
 * The menu bar of the app. Will be used in the mode switching &
 * the call of the settings. Also, the basic Container for a MyMenu.
 *
 * @author abc, 2022/2/17 - 2022/2/18
 */
public class MyMenuBar extends JMenuBar {

    public MyMenuBar() {
        setBorderPainted(false);
    }

    @Override
    protected void paintComponent(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(MyFrame.baseColor);
        g2d.fillRect(0, 0, this.getWidth(), this.getHeight());

    }

}

MyFrame code:

import javax.swing.*;

import java.awt.*;

/**
 * The basic Frame class of the calculator.
 * The frame created will be colored & border-decorated.
 * The class extends JFrame in "javax.swing", and uses its methods.
 *
 * @author abc, 2022/2/11
 */
public class MyFrame extends JFrame {

    /**
     * The color will be used for the background of the Frame.
     */
    public static final Color baseColor = new Color(34, 36, 54);

    public String status;

    /**
     * The contentpane of the frame.
     */
    public JPanel panel = new JPanel();

    /**
     * The custom icon of the frame.
     */
    static ImageIcon icon = new ImageIcon("sources/icon.png"); // Icon image


    public MyFrame() {

        status = "Regular";  // The status will be filled into the title.

        panel.setBackground(baseColor);

        setIconImage(icon.getImage());
        setTitle(String.format("%s - Calc++", status));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  // Set the title and the close operation

        setContentPane(panel);
        setSize(800, 480);
        setLocationRelativeTo(null);
    }
}
  • https://docs.oracle.com/javase/tutorial/uiswing/ -> https://docs.oracle.com/javase/tutorial/uiswing/components/index.html -> https://docs.oracle.com/javase/tutorial/uiswing/components/menu.html. – Axel Richter Feb 19 '22 at 06:14

1 Answers1

0

Basically you are trying to set the look-and-feel*. An easy way to do this is via class javax.swing.UIManager. Hence no need to extend classes JMenuItem, JMenu and JMenuBar as you have done.

I believe the following code achieves your desired result. Note that this is not the only way and may not be the best way for your situation which I don't know all the details of. I can only go with the code in your question and how I believe you want your GUI to look.

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;

public class MyFrame extends JFrame {
    /** The color will be used for the background of the Frame. */
    public static final Color baseColor = new Color(34, 36, 54);

    public String status;

    /** The contentpane of the frame. */
    public JPanel panel = new JPanel();

    /** The custom icon of the frame. */
    static ImageIcon icon = new ImageIcon("icon.png"); // Icon image

    public MyFrame() {
        status = "Regular";  // The status will be filled into the title.
        panel.setBackground(baseColor);
        setIconImage(icon.getImage());
        setTitle(String.format("%s - Calc++", status));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  // Set the title and the close operation

        JMenuItem menuItem = new JMenuItem("Menu Item");
        menuItem.setFocusPainted(false);
        menuItem.setBorderPainted(false);
        menuItem.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));

        JMenu menu = new JMenu("Menu");
        menu.setBorderPainted(false);
        menu.setFont(new Font("Consolas", Font.PLAIN, 18));
        menu.add(menuItem);

        JMenuBar menuBar = new JMenuBar();
        menuBar.setBorderPainted(false);
        menuBar.add(menu);
        setJMenuBar(menuBar);
        setContentPane(panel);
        setSize(800, 480);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        UIDefaults uiDflts = UIManager.getDefaults();
        uiDflts.put("MenuItem.background", baseColor);
        uiDflts.put("MenuItem.foreground", Color.white);
        uiDflts.put("MenuItem.selectionBackground", new Color(55, 40, 150));
        uiDflts.put("MenuItem.selectionForeground", Color.white);
        uiDflts.put("Menu.background", baseColor);
        uiDflts.put("Menu.foreground", Color.white);
        uiDflts.put("Menu.selectionBackground", baseColor);
        uiDflts.put("Menu.selectionForeground", Color.white);
        UIManager.put("PopupMenu.border", new LineBorder(baseColor));
        uiDflts.put("MenuBar.background", baseColor);
        uiDflts.put("MenuBar.selectionBackground", baseColor);
        EventQueue.invokeLater(() -> new MyFrame());
    }
}

The list of defined keys in class UIDefaults can be obtained via code, however an online list is available here: Swing UIManager Keys. The key required to "remove" the white border around JMenu was obtained from the accepted answer to this SO question: How to take out white borders in JMenu and JMenuItems.

Since I don't know how to create an animated GIF, here are three screen captures. Note that since I don't have your icon.png file, I used one of my own.

  1. Initial display

first screen capture

  1. After clicking on Menu

second screen capture

  1. Placing mouse over Menu Item

last screen capture

*Refer to Modifying the Look and Feel lesson in Oracle's Java tutorials.

Abra
  • 19,142
  • 7
  • 29
  • 41