kjohnson
kjohnson

Reputation: 110

Double icons with JMenuItem setHorizontalTextPosition on Win

Two icons are rendered when using JMenuItem setHorizontalTextPosition(SwingConstants.LEFT) with Windows Look and Feel. It works fine with the default Java Look and Feel.

I just filed a Java bug report, posting here for anyone else having the same problem.

Does anyone have another workaround to suggest?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingConstants;
import javax.swing.UIManager;


public class WinMenuItemIcon {

public static void main(String[] args) {
    
    //NOTE: Bug happens with Windows L&F
    String name = UIManager.getSystemLookAndFeelClassName();
    try {
        UIManager.setLookAndFeel( name );
    } catch (Exception e) {
        e.printStackTrace();
    }

    JFrame frame = new JFrame();
    frame.setTitle("Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("Menu");
    
    ImageIcon icon = createIcon();
    
    JMenuItem menuItem = new JMenuItem("Command", icon);
    menuItem.setHorizontalTextPosition(SwingConstants.LEFT);
    menu.add(menuItem);
    menuBar.add(menu);

    frame.setJMenuBar(menuBar);
    frame.setPreferredSize(new Dimension(500, 500));
    frame.pack();
    frame.setVisible(true);
}

protected static ImageIcon createIcon() {
    BufferedImage bi = new BufferedImage(25,25,BufferedImage.TYPE_INT_ARGB);
    Graphics g = bi.createGraphics();
    g.setColor(Color.RED);
    g.fillOval(0,0, 25, 25);
    return new ImageIcon(bi);
}

}

Upvotes: 4

Views: 687

Answers (3)

asmmahmud
asmmahmud

Reputation: 5044

For aligning icon and label text from left to right:

  JMenuItem menuItem3 = new JMenuItem("LEFT_TO_RIGHT", createIcon());
  menuItem3.setHorizontalTextPosition(JMenuItem.RIGHT);
  menuItem3.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

The above code worked for me.

Upvotes: 0

aterai
aterai

Reputation: 9808

enter image description here

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

public class WinMenuItemIconTest {
  private static JMenuBar makeManuBar() {
    JMenuItem menuItem0 = new JMenuItem("Command", createIcon());

    JMenuItem menuItem1 = new JMenuItem("LEFT bug?", createIcon());
    menuItem1.setHorizontalTextPosition(SwingConstants.LEFT);
    //menuItem1.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

    JMenuItem menuItem2 = new JMenuItem("CENTER bug?", createIcon());
    menuItem2.setHorizontalTextPosition(SwingConstants.CENTER);

    JMenuItem menuItem3 = new JMenuItem("RIGHT_TO_LEFT", createIcon());
    menuItem3.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

    JMenu menu = new JMenu("Menu");
    menu.add(menuItem0);
    menu.add(menuItem1);
    menu.add(menuItem2);
    menu.add(menuItem3);

    JMenuBar menuBar = new JMenuBar();
    menuBar.add(menu);
    return menuBar;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      //NOTE: Bug happens with Windows L&F
      String name = UIManager.getSystemLookAndFeelClassName();
      try {
        UIManager.setLookAndFeel(name);
      } catch (Exception e) {
        e.printStackTrace();
      }
      JFrame frame = new JFrame("Test");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setJMenuBar(makeManuBar());
      frame.setSize(320, 240);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
    });
  }
  protected static ImageIcon createIcon() {
    BufferedImage bi = new BufferedImage(25, 25, BufferedImage.TYPE_INT_ARGB);
    Graphics g = bi.createGraphics();
    g.setColor(Color.RED);
    g.fillOval(0, 0, 25, 25);
    g.dispose();
    return new ImageIcon(bi);
  }
}

Upvotes: 1

user5342366
user5342366

Reputation:

Delete the line

 menuItem.setHorizontalTextPosition(SwingConstants.LEFT);

and you will have only 1 icon

or use an if statement to exclude that line for windows look and feel as follows

if(!UIManager.getLookAndFeel().equals("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"))
{
     menuItem.setHorizontalTextPosition(SwingConstants.LEFT);
}

enter image description here

here is an alternative to @aterai's code that will work better if tweaked a bit more according to your needs, probably it is some bug but here this does it i am not sure how @aterai needs center to look like but here is what i assumed :-

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

public class WinMenuItemIconTest {
private static JMenuBar makeManuBar() {

    JMenuItem menuItem0 = new JMenuItem("Command", createIcon()); 

    JMenuItem menuItem1 = new JMenuItem("LEFT bug?", createIcon()); // always left by defaulr


    JMenuItem menuItem2 = new JMenuItem("CENTER bug?", createIcon());

     menuItem2.setMargin(new Insets(5, 50, 5, 5)); // using set margin to centerise 

    JMenuItem menuItem3 = new JMenuItem("RIGHT_TO_LEFT", createIcon());
    menuItem3.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); // Right to left seems to work

    JMenu menu = new JMenu("Menu");
    menu.add(menuItem0);
    menu.add(menuItem1);
    menu.add(menuItem2);
    menu.add(menuItem3);

    JMenuBar menuBar = new JMenuBar();
    menuBar.add(menu);
    return menuBar;

  }
      public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
          //NOTE: Bug happens with Windows L&F
          String name = UIManager.getSystemLookAndFeelClassName();
          try {
            UIManager.setLookAndFeel(name);
          } catch (Exception e) {
            e.printStackTrace();
          }
          JFrame frame = new JFrame("Test");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setJMenuBar(makeManuBar());
          frame.setSize(320, 240);
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
        });
      }
      protected static ImageIcon createIcon() {
        BufferedImage bi = new BufferedImage(25, 25, BufferedImage.TYPE_INT_ARGB);
        Graphics g = bi.createGraphics();
        g.setColor(Color.RED);
        g.fillOval(0, 0, 25, 25);
        return new ImageIcon(bi);
      }
    }

enter image description here

Note:- I am on Windows 10 too

Upvotes: 3

Related Questions