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.
Related
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.
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.
I am having some trouble with popup menu and multi-line text. When the popup menu is displayed for the first time, only the first line is visible. Here is how it looks like after first click
and after second click
What should I do to make it to show the whole text after the first click?
I tried validating, invalidating, revalidating and repainting various components. I even tried to pack the ancestor window (at that time the content of the popup menu was dynamic and I thought that that was causing the problem). It behaves the same way if I use multi-line JLabel (using html content).
Edit: More research
Preferred size of the text component is probably wrong. Before the popup menu is displayed for the first time, the preferred height is 21. After it is displayed it is 51. So it is displayed based on wrong preferred size. Is there some way to calculate the preferred size it in advance?
I boiled the problem down to following minimal example:
public class PopupMenuFail extends JFrame {
public PopupMenuFail() {
final JTextPane text = new JTextPane();
text.setText("Some text long enough to be split into several lines.");
text.setMaximumSize(new Dimension(150, 1000)); // limit the width
final JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(text);
final JButton button = new JButton();
button.setAction(new AbstractAction("Click me") {
#Override
public void actionPerformed(ActionEvent e) {
popupMenu.show(button, 0, button.getHeight());
}
});
add(button);
}
private static void createAndShowGUI() {
JFrame frame = new PopupMenuFail();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I am running a 64-bit linux,
# java -version
java version "1.7.0_72"
Java(TM) SE Runtime Environment (build 1.7.0_72-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.72-b04, mixed mode)
You could simply set a default minimum size to your JPopupMenu using popupMenu.setPopupSize(500, 500) for example and this would works.
However, if you are trying to create a menu, you should check JMenu and JMenuItem
http://docs.oracle.com/javase/7/docs/api/javax/swing/JMenu.html
http://docs.oracle.com/javase/7/docs/api/javax/swing/JMenuItem.html
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've looked at other JLabel threads and though similar, a few just don't seem to apply to what I'm experiencing. First, I want to say I am a novice when it comes to Java. Next, I am trying to follow tutorials and demos at the docs.oracle.com site. Now, I can update the label when I type something into a JTextField and there is an ActionListener on that...
But I also have a Menu, and when I select a Menu Item, that Action does not want to update the label.
Questions -
How do I have action listeners on both JTextFields and JMenuItems? Are there two ActionEvent methods or do I use one method and somehow identify each type of action?
If I use the same basic code in the JTextField ActionEvent and JMenuItem ActionEvent, the JLabel updates correctly with the JTextField event but not JMenuItem event. They both use the messageField.setText property. Could the JMenuItem action be doing something to block the setText?
I can easily copy code in here, but it's pretty spaghetti-like at the moment, so if you want to see anything, let me know specifically and I'll post it.
I would appreciate any assistance that anyone would be able to provide.
---edit---
Wow!! Thanks for all of the comments and suggestions.
1 - I know it has to be my code. As I mentioned, I am really just cobbling stuff together from demos and tutorials, and trying to learn Java along the way. I've just never gotten the hang of object oriented....
2 - I do know the individual Listeners are working. I'm using System.out.println to validate, as well as inspecting those labels in debug mode to see they have indeed changed.
3 - I will look at the various links and code posted here and see if I can figure out what's wrong with my code.
Really, thanks again!
---edit---
Here is what I originally had in my createAndShowGUI method....
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Create XML for Photo Gallery");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CreateGalleryXML window = new CreateGalleryXML();
frame.setJMenuBar(window.createMenuBar());
frame.add(new CreateGalleryXML());
frame.pack();
frame.setVisible(true);
}
Seems like you yourself are doing something wrong, in your code. Without a proper SSCCE it's hard to say what thing you doing wrong, since it works perfectly, using same ActionListener for both JMenuItem and JTextField.
Here is a sample program to match with yours :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class UpdateLabel
{
private JLabel label;
private String labelText;
private ActionListener action = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
setLabelText((String) ae.getActionCommand());
label.setText(getLabelText());
}
};
private void setLabelText(String text)
{
labelText = text;
}
private String getLabelText()
{
return labelText;
}
private void createAndDisplayGUI()
{
final JFrame frame = new JFrame("Update Label");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationByPlatform(true);
JMenuBar menuBar = new JMenuBar();
JMenu programMenu = new JMenu("Program");
JMenuItem exitMenuItem = new JMenuItem("Exit");
exitMenuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
frame.dispose();
}
});
JMenu labelMenu = new JMenu("Label");
JMenuItem updateMenuItem = new JMenuItem("Update Label");
updateMenuItem.setActionCommand("Updated by JMenuItem");
updateMenuItem.addActionListener(action);
programMenu.add(exitMenuItem);
labelMenu.add(updateMenuItem);
menuBar.add(programMenu);
menuBar.add(labelMenu);
frame.setJMenuBar(menuBar);
JPanel contentPane = new JPanel();
label = new JLabel("I am the LABEL which will be updated!!");
contentPane.add(label);
JTextField tfield = new JTextField(10);
tfield.setActionCommand("Updated by JTextField");
tfield.addActionListener(action);
frame.add(contentPane, BorderLayout.CENTER);
frame.add(tfield, BorderLayout.PAGE_END);
frame.pack();
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new UpdateLabel().createAndDisplayGUI();
}
});
}
}
And here is the output in both the cases :
and
Do check out the main method, might be you had failed to put your code inside EDT - Event Dispatcher Thread, that can lead to such issues too. All updates on the Swing GUI, must be done on the Event Dispatcher Thread.
LATEST EDIT
It seems to me that CreateGalleryXML extends JPanel by the look of it. See at Line 3 of this below code taken from your update, here you are initializing a new Object of CreateGalleryXML inside, when you already had one Object window created at Line 1:
CreateGalleryXML window = new CreateGalleryXML();
frame.setJMenuBar(window.createMenuBar());
frame.add(new CreateGalleryXML());
So try to change the above thingy to this
CreateGalleryXML window = new CreateGalleryXML();
frame.setJMenuBar(window.createMenuBar());
frame.add(window);
and see what happens and Please do revert back again :-)
Use Action to encapsulate common functionality that must be shared by menus and related components. See this example that extends AbstractAction.
Pretty much everything you could need to know is in the Java tutorials. Down the bottom they have demo's on how to do both menu's and text fields. They include source code to look at as well.
There's not much more I can say that they don't say better, but in answer to your questions:
Both, you can have separate listener's on each component, or one that figures out what component is responsible for causing the action event. I would suggest you use separate ones for each thing.
Can't really say with out seeing the code, are you sure that the action on the JMenu is even firing? Does it print something to the console etc if you use System.out.println somewhere?