I am using BeautyEye look and feel in a Java Desktop program but recently found out JMenuBar shows empy JMenuItems as shown in the screenshot below.
As you can see the area of the menu is there but with the same colour as the Jframe contentPane and with no Menu text visible.
a sample program to test this (download the BeautyEye library from here) is:
import java.awt.*;
import javax.swing.*;
import org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper;
public class JavaMenuBarExample implements Runnable
{
private JFrame frame;
private JMenuBar menuBar;
private JMenu fileMenu;
private JMenuItem openMenuItem;
public static void main(String[] args)
{
try
{
BeautyEyeLNFHelper.frameBorderStyle = BeautyEyeLNFHelper.FrameBorderStyle.osLookAndFeelDecorated;
org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper.launchBeautyEyeLNF();
UIManager.put("RootPane.setupButtonVisible", Boolean.FALSE);
}
catch (Exception ex)
{
ex.printStackTrace();
}
// the proper way to show a jframe (invokeLater)
SwingUtilities.invokeLater(new JavaMenuBarExample());
}
#Override
public void run()
{
frame = new JFrame("Java Menubar Example");
menuBar = new JMenuBar();
fileMenu = new JMenu("File");
openMenuItem = new JMenuItem("Open");
fileMenu.add(openMenuItem);
// add menus to menubar
menuBar.add(fileMenu);
// put the menubar on the frame
frame.setJMenuBar(menuBar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(400, 300));
frame.pack();
frame.setVisible(true);
}
}
I am the author of BeautyEye project.
A few things to note:
BeautyEye has migrated to
GitHub: https://github.com/JackJiang2011/beautyeye, you can find
the latest version there. But I'm so sorry, there is no English
introduction.
Because the JDK version updates too fast, I just
do few tests with jdk8 (and just for Windows), so I can't guarantee
full compatibility with jdk8 in all platform temporarily.
I think that problem is caused by Java transparent API, you can fetch the latest source code to debug it: for example use system frame style but not use transparent frame border etc.
You can contact me at jb2011 at 163.com, I hope you can resolve this issue.
I have been debug it use jdk 1.8_u45, it is normal at Windows platform.
I guess this may be a bug for linux platform java1.8_u45.
Related
for an exercise I need to have a frame consisting of 2 buttons, and, if you click one, some text displaying. I need to also add a menubar. This works fine, it shows in the frame, but only the first menu. As I already found out, the problem is that using the pack() method, only the buttons size is considered, not the size of the menubar. And because the buttons are smaller than the menubar, it gets cutoff.
import java.awt.*;
public class Example extends Frame{
private MenuBar menuBar;
private Menu program;
private Menu messageSettings;
private MenuItem itmClose;
private MenuItem
public Example() {
menuBar = new MenuBar();
program = new Menu("Programm");
messageSettings = new Menu("Nachrichtenverwaltung");
itmClose = new MenuItem("Schließen");
itmWelcome = new MenuItem("Willkommen");
setLayout(new BorderLayout());
menuBar.add(program);
menuBar.add(messageSettings);
program.add(itmClose);
messageSettings.add(itmWelcome);
setMenuBar(menuBar);
pack(); //this one doesn't show a window
//setSize(400,600); //this one shows a Window
setVisible(true);
}
public static void main(String args[]) {
Example wnd = new Example();
}
}
For this minimal example, I only showed the menubar, for me, this code now opens an empty window. If I uncomment the setSize, I see the whole menubar.
I would be very glad if someone could help me out and get this to work, using pack() or another method not using fixed values. I also have to use AWT for this course.
Without a Component that has a preferred size, your window's content pane is empty. As an example, I've added a small, colored Panel below. As an exercise, try removing the arbitrary size and adding a Component such as Label or Button; experiment with different layout managers on the Panel.
import java.awt.*;
public class Example extends Frame {
private MenuBar menuBar = new MenuBar();
private Menu program = new Menu("Program");
private Menu message = new Menu("Nachrichtenverwaltung");
private MenuItem itmClose = new MenuItem("Schließen");
private MenuItem itmWelcome = new MenuItem("Willkommen");
public Example() {
menuBar.add(program);
menuBar.add(message);
program.add(itmClose);
message.add(itmWelcome);
setMenuBar(menuBar);
Panel panel = new Panel(){
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
};
panel.setBackground(Color.cyan.darker());
add(panel);
pack();
setVisible(true);
}
public static void main(String args[]) {
Example wnd = new Example();
}
}
Note that the platform pictured above moves the MenuBar to a place expected by users.
I would recommend using Java Swing library instead of using the old Java AWT library, unless you have to.
EDIT for detail:
The Swing library is much more portable than the AWT library. This is because it is a purely Java based GUI as opposed to AWT which uses most of the OS based GUI features. So, in terms of the OS, the swing library is just putting some pixels on the screen.
I find that the swing library is easier to use than AWT, although you do still have to use AWT for Listeners. I feel that it would be better for you to have a look into the swing API, as it should make it easier for you to do what you are trying.
Not getting any errors however the program only displays the word "menu" at the top in the program. It doesn't display the 3 JMenu items: "home", "about" and "explore".
JPanel p5 = new JPanel(new GridBagLayout());
p5.setVisible(true);
fw.add(p5, BorderLayout.PAGE_START);
JMenu menu = new JMenu("Menu");
menu.setVisible(true);
menu.add("home");
menu.add("about");
menu.add("explore");
JMenuBar menubar = new JMenuBar();
fw.setJMenuBar(menubar); //ADDED THIS LINE. STILL DOESN'T WORK.
menubar.setVisible(true);
menubar.add(menu);
p5.add(menu);
I've added JMenu to JMenuBar (everything JMenu, JMenubar and JPanel is set to visible). Also I added JPanel (p5) to "first window (fw) and added menu to p5. I'm not sure why my menu items are not being displayed.
UPDATE: MCVE (Minimal Complete and Verifiable Example) as requested.
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
public class TestingClass extends JFrame {
public static void main(String[] args) {
FirstWindow fw = new FirstWindow();
fw.setSize(400, 600);
fw.setDefaultCloseOperation(EXIT_ON_CLOSE);
fw.setVisible(true);
JPanel p5 = new JPanel(new GridBagLayout());
p5.setVisible(true);
fw.add(p5);
JMenu menu = new JMenu("Menu");
menu.setVisible(true);
menu.add("home");
menu.add("about");
menu.add("explore");
JMenuBar menubar = new JMenuBar();
fw.setJMenuBar(menubar); // THE UPDATED LINE OF CODE.
menubar.setVisible(true);
menubar.add(menu);
p5.add(menu);
}
}
As you run the program, you will see the words "menu" displayed. The items: "home, about and explore" from JMenu are not displayed. Does anybody know what I'm doing wrong?
An MCVE of a run-time problem should compile cleanly. That shows 3 compilation errors. One is a missing import (easily fixable), but the other two relate to the missing FirstWindow.
Nevertheless, once a few tweaks were made, the problem becomes clear. A component can only appear in one place. By adding it to the panel as well (commented out below), it cannot appear in the menu.
import java.awt.*;
import javax.swing.*;
public class TestingClass extends JFrame {
public static void main(String[] args) {
JFrame fw = new JFrame();
fw.setSize(400, 200); // for screenshot
fw.setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel p5 = new JPanel(new GridBagLayout());
p5.setVisible(true);
fw.add(p5);
JMenu menu = new JMenu("Menu");
//menu.setVisible(true);
menu.add("home");
menu.add("about");
menu.add("explore");
JMenuBar menubar = new JMenuBar();
fw.setJMenuBar(menubar); // THE UPDATED LINE OF CODE.
//menubar.setVisible(true);
menubar.add(menu);
//p5.add(menu); // WTF?
fw.setVisible(true); //should be done after all components are added
}
}
You need to add the menuBar to the frame:
frame.setJMenuBar( menuBar );
Also, you don't need do make Swing components visible since they are visible by default (except for top level contains, like JFrame which you do need to set visible).
You need to call setVisible() after adding component! So first add all components. Add the highest level component to the JFrame(JPanel in your case) and the only call setVisible() for the JFrame. No need to call on every component.
JMenu menu = new JMenu("Menu");
menu.add("home");
menu.add("about");
menu.add("explore");
//rest of the components
//add panelto the frame
frame.getContentPane.add(p5);
//set menubar for the frame
frame.setJMenuBar( menuBar );
//set visibility for frame to true
frame.setVisible(true);
I try to make my JMenuBar to activate first JMenu on Alt KeyEvent, but without opening popup, so that one could open popup with arrows keystrokes later. Just like it is done in NetBeans, Mozilla, any other program window.
Here is the code that works not as intended. The worst side effect is that it reacts on alt+tab combination, and it definitely should not popup menu on alt+tab. I just need to make a menu go to the "armed" state and be able to traverse menus by arrow keys (arrows right & left to "arm" menus and arrow down to open "armed" menu popup). Is there any simple way to make this happen?
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
public class Test5 extends JFrame {
public Test5() {
super("test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel pan = new JPanel(new BorderLayout());
final JMenuBar bar = new JMenuBar();
final JMenu menu = new JMenu("File", false);
menu.setMnemonic(KeyEvent.VK_ALT);
JMenuItem item = new JMenuItem("All");
JMenuItem item2 = new JMenuItem("Exit");
menu.add(item);
menu.add(item2);
JMenu menu1 = new JMenu("Test");
JMenuItem item1 = new JMenuItem("All");
menu1.add(item1);
bar.add(menu);
bar.add(menu1);
setJMenuBar(bar);
setSize(200, 200);
setVisible(true);
}
public static void main(String[] args) {
new Test5();
}
}
Solved thanks to Guillaume Polet:
There is some code in com.sun.java.swing.plaf.windows.WindowsLookAndFeel class, wich works with Alt keystrokes:
public void initialize() {
super.initialize();
// some more initialization here
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventPostProcessor(WindowsRootPaneUI.altProcessor);
}
And the AltProcessor class does all the magic.
If you don't have any custom LaF, you can just use WindowsLookAndFeel as it is, or there is proper example how to process Alt events in menus for your own special LaF.
Before starting your GUI, invoke this line:
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
And remove the mnemonic.
This will automatically install the desired behaviour on Windows.
If you need this on all platforms, then you will have to go with KeyBindings, but since this behaviour is only observed on Windows, I don't find it problematic to recreate it only on Windows.
no idea why, but about answering the question
1st step
have to use KeyBindings and with output to the Swing Action (adviced) or ActionListener
there are two methods menu.setArmed(true) or menu.setSelected(true)
but in both cases JMenu is selected forever then to required 2nd. step to add MenuListener and restore previous selected or armed to false
I am facing a problem with my JMenuBar location in my Java application.
I am actually using ComponentResizer.java code from the article.
and everything with the resizing works fine except from the north area of my application
(undecorated JFrame) and its corners (of North Area) because the JMenuBar is preventing me from resizing from that area.
Is there a solution or maybe a hack to move the JMenuBar down a little or enable the Resizing
in the north area?
I also use setJMenuBar() method to add the JMenuBar to the north area of my application.
Code:
public class MyApp extends JFrame {
private MyApp frame;
private JMenuBar menuBar;
public static void main(String[] args) {
frame = new MyApp();
frame.setUndecorated(true);
frame.setVisible(true);
}
public MyApp(){
initComponents();
}
private void initComponents(){
setTitle("MediaForm");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 673, 482);
menuBar = new JMenuBar();
setJMenuBar(menuBar);
}
}
JMenuBar extends JComponent, therefore you can put it anywhere you would put an ordinary component. Note that it could be confusing to the users if you put it to unexpected locations.
Also see this: add JMenuBar to a JPanel?
I've not tested this, but JRootPane is a JComponet, it may be possible to add a EmptyBorder to it, allowing the JMenuBar to be offset.
Failing that, you'll probably need to implement your own JRootPane to manage the layout of the JMenuBar & content pane
UPDATE with Testing
public class TestMenuFrame extends JFrame {
public TestMenuFrame() throws HeadlessException {
setTitle("Test");
getRootPane().setBorder(new EmptyBorder(10, 10, 10, 10));
JMenuBar mb = new JMenuBar();
mb.add(new JMenu("Test"));
setJMenuBar(mb);
setSize(100, 100);
getContentPane().setBackground(Color.RED);
setLocationRelativeTo(null);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new TestMenuFrame().setVisible(true);
}
}
I am trying to write a simple desktop application for managing accounts. I am in the beginning phase.
I am running it in my old computer and I sometimes get strange behavior.
Java Version
java version "1.6.0_05"
Java(TM) SE Runtime Environment (build 1.6.0_05-b13)
Java HotSpot(TM) Client VM (build 10.0-b19, mixed mode, sharing)
My computer configuration
Microsoft Windows XP SP2
Intel(R) Celeron(R) CPU 2.53GHz 1.96GHz 736MB of RAM
I get strange behaviour. When I compile my program and the jframe loads, i sometimes get menu and sometimes I don't get menu as shown in the figure. Also when I try to resize my jframe, jframe shows menu.
My code
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.AWTException;
public class Main {
public static void main(String[] args) {
new Login();
}
}
class Login extends JFrame{
private int height=450;
private int width=300;
private Container container;
private GridBagLayout layout;
private GridBagConstraints constraints;
JTextArea textArea1, textArea2;
public Login()
{
initWindow();
initMenu();
}
private void initWindow()
{
setVisible(true);
setSize(this.height, this.width);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolkit toolkit = Toolkit.getDefaultToolkit ();
Dimension dim = toolkit.getScreenSize();
setLocation((dim.width-this.width)/2, (dim.height-this.height)/2);
Image image = toolkit.createImage("account.gif");
setIconImage(image);
}
private void initMenu()
{
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu fileMenu = new JMenu("File");
JMenu helpMenu = new JMenu("Help");
menuBar.add(fileMenu);
menuBar.add(helpMenu);
JMenuItem configureAction = new JMenuItem("Configure");
JMenuItem exitAction = new JMenuItem("Exit");
fileMenu.add(configureAction);
fileMenu.add(exitAction);
JMenuItem helpAction = new JMenuItem("Help");
JMenuItem aboutAction = new JMenuItem("About");
helpMenu.add(helpAction);
helpMenu.add(aboutAction);
}
}
Window with no menu
Window with menu
Any suggestion to improve code with be highly appreciated.
Thank you
Note that you get this erratic behaviour (rather than a consistent fail or consistent success) because of what “events” are delivered. For instance if you mouse over where the menubar is, or change window sizes you will see bits being painted “properly” because the underlying graphics stack detected these events and marked the affected regions for update.
You can mark GUI components for update as well using repaint() and/or revalidate().
Note that the above doesn't explain why your code did not work, the reason for that is as explained by the first answer, that you made the window visible before it was realised.
A few other tips: it's good practice to ensure all GUI creation occurs on the AWT EventQueue, by using something like
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
// call code which creates the GUI in here
}
}
Or the SwingUtilities.invokeLater() version.
Additionally, it is a good idea to call pack() on the frame before making it visible, since this will make the Window size it components properly and validate them (and without such validation, scrollpanes for instance won't update the scrollbars properly).
Don't call setVisible(true) until the window is completely built, ie. do that statement as the last thing you do with the window.
Once the window is visible, any changes you make to the window must be done on the GUI thread.