JMenuBar Menu.selectionBackground als Gradient anzeigen

  • Themenstarter Themenstarter testings
  • Beginndatum Beginndatum
T

testings

ich würde gerne das selectionBackground des JMenu im JMenuBar als gradienten Farbverlauf (statt hier im monochromen red) anzeigen:


import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import java.awt.Color;
import javax.swing.UIManager;
public class MenuCreation {

public static void main(final String args[]) {
JFrame frame = new JFrame("MenuSample Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();

UIManager.put("Menu.selectionBackground",Color.red);

JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);

JMenuItem newMenuItem = new JMenuItem("New");
fileMenu.add(newMenuItem);

frame.setJMenuBar(menuBar);
frame.setSize(350, 250);
frame.setVisible(true);
}
}
 
Hi!
Du musst dir eine eigene MenuUI - Klasse erstellen, und dort die Methode paintBackground überschreiben.
Skizze:
Java:
...
fileMenu.setUI(new GradientBackgroundUI());

Java:
public class GradientBackgroundUI extends BasicMenuUI{
...
   protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
     // Hier den Hintergrund deinen Bedürfnissen anpassen
   }
}

Hier findest du den SourceCode für die ursprüngliche paintBackground Methode, um dich daran zu orientieren: http://www.java2s.com/Open-Source/J...vax/swing/plaf/basic/BasicMenuItemUI.java.htm
Ein Beispiel für GradientColor findest du hier: http://www.roseindia.net/java/example/java/swing/GradientColor.shtml

Grüße!
 
Zuletzt bearbeitet von einem Moderator:
Für manche Operationen setze ich updateUI(). Aber das paintBackgrund arbeitet nicht beim Aufruf von
Java:
 fileMenu.updateUI();


Java:
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import java.awt.Color;
import javax.swing.UIManager;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Paint;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.geom.Point2D;
 
import javax.swing.ButtonModel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.plaf.basic.BasicMenuUI;
public class MenuCreation {
 
  public static void main(final String args[]) {
    JFrame frame = new JFrame("MenuSample Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JMenuBar menuBar = new JMenuBar();
 
    CustomMenu fileMenu = new CustomMenu("File");
    
    //paintBackground arbeitet nicht mit
    fileMenu.updateUI();
 
    fileMenu.setText("ups"); 
    menuBar.add(fileMenu);
    JMenuItem newMenuItem = new JMenuItem("New");
    fileMenu.add(newMenuItem);
 
    frame.setJMenuBar(menuBar);
    frame.setSize(350, 250);
    frame.setVisible(true);
    
    
  }
}
class CustomMenu extends JMenu{
  public CustomMenu(String text){
    super(text);
    setUI(new GradientBackgroundUI());
  }
}
class GradientBackgroundUI extends BasicMenuUI {
	 
	  Paint paint = new LinearGradientPaint(new Point2D.Double(),
	          new Point2D.Double(5, 5),
	          new float[]{0.2F, 0.9F},
	          new Color[]{Color.YELLOW, Color.PINK},
	          CycleMethod.REFLECT);
	 
	  @Override
	  protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
      System.out.println("I'm alive");   
      ButtonModel model = menuItem.getModel();
	    Color oldColor = g.getColor();
	    int menuWidth = menuItem.getWidth();
	    int menuHeight = menuItem.getHeight();
	 
	    if (menuItem.isOpaque()) {
	      if (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())) {
	        //g.setColor(bgColor);
	        ((Graphics2D) g).setPaint(paint);
	        g.fillRect(0, 0, menuWidth, menuHeight);
	      } else {
	        g.setColor(menuItem.getBackground());
	        g.fillRect(0, 0, menuWidth, menuHeight);
	      }
	      g.setColor(oldColor);
	    } else if (model.isArmed() || (menuItem instanceof JMenu
	            && model.isSelected())) {
	      //g.setColor(bgColor);
	      ((Graphics2D) g).setPaint(paint);
	      g.fillRect(0, 0, menuWidth, menuHeight);
	      g.setColor(oldColor);
	    }
	  }
	}
 
Zuletzt bearbeitet von einem Moderator:
sry, wusste nicht, dass der zwei Jahre alt ist.

Ich schalte in meiner App mein LAF um. Wenn ich von
setLookAndFeel(UIManager.getSystemLookAndFeelClassName()) auf
setLookAndFeel(UIManager.getLookAndFeel()) umschalte, werden die Komponenten JMenuBar und die JMenu immer noch in Win 7-LAF angezeigt. Das "MetalLookAndFeel" wird richtig angezeigt, wenn ich updateUI() durchführe. Aber der Aufruf von updateUI() 'deaktiviert' die Ausführung von paintBackgrund. Im "MetalLookAndFeel" erscheint dann die monochrome Standard-Hintergrundfarbe, das .setPaint(paint); wird nicht mehr ausgeführt.

Dann habe ich nach der Ausführung von updateUI() nochmals setUI(new GradientBackgroundUI()) auf jedes JMenu gesetzt, was dazu führte, dass einige JMenu als "MetalLookAndFeel", andere als Win 7-LAF angezeigt wurden, von mal zu mal wie zufällig einmal "MetalLookAndFeel" oder Win 7-LAF.

Daher die Idee, über die paintComponent zu gehen, da wird '100%' .setPaint(paint); ausgeführt. Aber jetzt wird natürlich alles von dem .setPaint(paint); überdeckt, der Text des JMenu ist im Hintergrund. Ich will den Text aber in den Vordergrund setzen:
Poste noch mal den Code mit paintComponent
Java:
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import java.awt.Color;
import javax.swing.UIManager;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Paint;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.geom.Point2D;
 
import javax.swing.ButtonModel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.plaf.basic.BasicMenuUI;
public class MenuCreation {
 
  public static void main(final String args[]) {
    JFrame frame = new JFrame("MenuSample Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JMenuBar menuBar = new JMenuBar();
 
    CustomMenu fileMenu = new CustomMenu("File");

    fileMenu.updateUI();
 
    menuBar.add(fileMenu);
    JMenuItem newMenuItem = new JMenuItem("New");
    fileMenu.add(newMenuItem);
 
    frame.setJMenuBar(menuBar);
    frame.setSize(350, 250);
    frame.setVisible(true);
   
   
  }
}
class CustomMenu extends JMenu{
  public CustomMenu(String text){
    super(text);
  }
          Paint paint = new LinearGradientPaint(new Point2D.Double(),
                  new Point2D.Double(5, 5),
                  new float[]{0.2F, 0.9F},
                  new Color[]{Color.YELLOW, Color.PINK},
                  CycleMethod.REFLECT);
    protected void paintComponent(Graphics g){
    boolean selected=isSelected();
    super.paintComponent(g);
    setOpaque(false);
    if(selected){
      int width=getWidth();
      int height=getHeight();
      ((Graphics2D)g).setPaint(paint);
      ((Graphics2D)g).fillRect(0,0,width,height);
//                                super.paintComponent(g);                       
    }
  }
}
 
Mir gehts nicht darum, dass der Sun Thread 2 Jahre alt ist.
Du hättest gleich mal auf den Thread verweisen, und deine Probleme damit ansprechen sollen, anstattt hier die gleichen Fragen und den gleichen Code zu posten. So hätte man sich ein wenig Arbeit ersparen können!

Zur Info: Es ist klar, dass die paintBackground Methode nicht mehr aufgerufen wird, nachdem du updateUI() aufrufst. Denn updateUI resettet die L&F Einstellungen wieder, d.h. setzt die ursprüngliche UI-Klasse wieder. Das hättest du auch in der API-Dokumentation nachlesen können.



Poste doch mal einen entsprechend lauffähigen Code, in dem du, wie beschreiben, auch das Look-and Feel änderst. Aus deiner Problembeschreibung bin ich nämlich nicht sehr schlau geworden..

Grüße!
 
Zurück