How to create a custom JMenuBar? - java

I want to create a custom menu bar class that i can add close and minimize buttons to. I want to extend the JMenuBar class but I don't know which methods to override or how to override them. I tried checking the java docs but that only tells you what a method does, not how it works. Can someone please help?

Yes, you can extend JMenuBar to create your own one. In order to have some custom menu buttons, you should ensure
Create a constructor with an ActionListener parameter
public MyMenuBarClass(ActionListener p_objAl) {
super();
this.objal = p_objAl;
initComponents();
}
When you initial the menu buttons, you should add the ActionListener object into the added JMenuItem such as
JMenu menu1 = new JMenu("menu 1");
this.add(menu1);
JMenuItem menuitem1_1 = new JMenuItem("menu item 1.1");
menuitem1_1.setMnemonic(KeyEvent.VK_F10);
menuitem1_1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0));
menuitem1_1.setActionCommand("command1_1");
menuitem1_1.addActionListener(this.objal);
menu1.add(menuitem1_1);
Implement the ActionListener object to handle the command such as command1_1 in the above example.

This is how i modified the JMenuBar class to except all JComponents instead of just menu's.
public class CustomMenuBar extends JMenuBar{
public JComponent addComponent(JComponent c) {
super.add(c);
return c;
}
}

Related

how to create new window with swing when clicking JButton

I need to create a bank account management program for school, I created the "skeleton" of the first page but I do not understand some things:
How to open a new window with Swing when I click a button?
How can I have different ActionListener for each button?
If I change strategy and I want to use just one big window and let appear and disappear the working text fields/Labels, how would I do it?
Code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
public class CreditUnion extends JFrame
{
//declare buttons
private JButton openAccount;
private JButton closeAccount;
private JButton makeLodgement;
private JButton makeWithdrawal;
private JButton requestOverdraft;
//constructor
public CreditUnion()
{
super("ATM#CreditUnion");
Container c = getContentPane();
c.setLayout(new FlowLayout() );
openAccount = new JButton("Open account");
c. add(openAccount);
closeAccount = new JButton("Close account");
c. add(closeAccount);
makeLodgement = new JButton("Make lodgement");
c. add(makeLodgement);
makeWithdrawal = new JButton("Make withdrawal");
c. add(makeWithdrawal);
requestOverdraft = new JButton("Request overdraft");
c. add(requestOverdraft);
/*create instance of inner class ButtonHandler
to use for button event handling*/
ButtonHandler handler = new ButtonHandler();
openAccount.addActionListener(handler);
closeAccount.addActionListener(handler);
makeLodgement.addActionListener(handler);
makeWithdrawal.addActionListener(handler);
requestOverdraft.addActionListener(handler);
setSize(800,600);
show();
}
public static void main (String args[])
{
CreditUnion app = new CreditUnion();
app.addWindowListener(
new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
);
}
//inner class for button event handling
private class ButtonHandler implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
JOptionPane.showMessageDialog(null, "You Pressed: " + e.getActionCommand() );
}
}
how to open a new window with Swing when I click a button?
Don't, use a CardLayout, it's less distracting to the user
Have a look at How to use CardLayout for more details
how can I have different ActionListener for each button?
You can use a separate class, inner class or anonymous class depending on what you to achieve
Have a look at Nested classes for more details
if I change strategy and I want to use just one big window and let appear and disappear the working Textfields/Labels, how would I do it
See the first point
1- how to open a new window with Swing when I click a button?
The same way that you would display any window. In the button's ActionListener, create a new window -- I would suggest that you create a JDialog and not a JFrame, but this will depend on your assignment requirements too, and display it
2- how can I have different ActionListener for each button?
Add a different ActionListener to each button. An anonymous inner class (search on this) would work great for this.
3- if I change strategy and I want to use just one big window and let appear and disappear the working Textfields/Labels, how would I do it?
Use a CardLayout to swap "views", usually JPanels with components that you want to swap.

call actionperformed method on clicking jmenu

can i call actionperformed method with jmenu using swing
i am using the following code
JMenu menu1= new JMenu("File");
MenuBar mb= new MenuBar();
mb.add(menu1);
set JmenuBar(mb)
menu1.addActionListener(this);
public void actionPerformed(ActionEvent ae)
{
JOptionPane.showMessaageDialog(null,"menu clicked");
// but its not working
}
thanks in Advance
The action a JMenu is designed to perform is to open a popup with JMenuItems, it doesn't support doing anything else (and even if it did, it would confuse your users). Custom actions are supposed to be handled by JMenuItems in the popup. Install them with something like:
JMenu menu ..
Action myAction = new AbstractAction("Do XY") {
public void actionPerformed(..) {
// implement doing XY
}
};
menu.add(myAction);

JMenuItem Constructor Not Accepting Action

JMenuItem has the following constructor: (Source: GrepCode)
public JMenuItem(Action a) {
this();
setAction(a);
}
However, when my code has
import javax.swing.*;
import java.awt.event.ActionEvent;
public class ActionTest extends JApplet {
private final JFrame frame = new JFrame("Title");
private final JMenuBar menuBar = new JMenuBar();
private final JMenu fileMenu = new JMenu("File");
protected Action someAction;
private JMenuItem someButton = new JMenuItem(someAction);
public ActionTest() {}
#Override
public final void init() {
frame.setJMenuBar(menuBar);
menuBar.add(fileMenu);
fileMenu.add(someButton);
someButton.setText("Button");
someAction = new AbstractAction("Title") {
public void actionPerformed(ActionEvent event) {
//do stuff
}
};
frame.setVisible(true);
}
public static void main(String[] args) {
JApplet applet = new ActionTest();
applet.init();
}
}
and I press the JMenuItem, actionPerformed() is not even called.
Is this a bug, or is my approach completely wrong?
After doing more research, I find that this is the method that it eventually boils down to. It seems to implement a shallow copy, which should simply point to the same memory block that I gave it in the constructor.
The same thing should be occurring when I add the file menu to the menu bar. When the file menu is added, it references the memory block. Whatever is inside that memory block is what is displayed. Then, I add the menu item and it appears in the JMenu.
Somehow it is different when I'm dealing with Actions or constructors. Could somebody explain the difference?
It seems like from what you've posted that you haven't defined your Action when you initialize the JMenuItem. Therefore, because you are passing in null, no action is being triggered
someButton is initialized before someAction, so you are passing null to the JMenuItem. Initialize someButton after you have created someAction and everything will go fine.

Update JMenuItem via ActionListener

I am trying to create a JMenuItem that is disabled by default, but a method can be called to enable it. Just for the moment whilst I'm testing out my code, I want the method to be called when I click on another menu item. I have had a look at the documentation for JMenuItem, but I'm pretty new to Java and I'm having trouble finding exactly what I need. I've tried using the updateUI() command, but I that hasn't worked, so I'm totally stuck. Thanks in advance for any help :)
This is what I have so far:
public class initialScreen extends JFrame implements ActionListener{
Dimension screenSize = new Dimension(800,600);
JMenuItem runE, newP;
public initialScreen(){
super("Experiment Control Suite");
setSize(screenSize);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar bar = new JMenuBar();
JMenuItem newP = new JMenuItem("New");
newP.addActionListener(this);
runE = new JMenuItem("Run");
runE.setEnabled(false);
runE.addActionListener(this);
JMenu exp = new JMenu("Experiment");
exp.add(runE);
JMenu par = new JMenu("Participant");
par.add(newP);
bar.add(exp);
bar.add(par);
setJMenuBar(bar);
setVisible(true);
}
public void enableRun(){
runE.setEnabled(true);
runE.updateUI();
}
public void actionPerformed(java.awt.event.ActionEvent e){
if(e.getSource() == newP) {
enableRun();
}
else if(e.getSource() == runE) {
System.out.println("run has been clicked");
}
}
}
Your method enableRun is never invoked because of the following line:
JMenuItem newP = new JMenuItem("New");
Instead, refactor it as such,
newP = new JMenuItem("New");
Now, the field will be correctly initialized and registered as an ActionListener. And thus, when checking the source, enableRun will be invoked and the menu item will be enabled.
Note that in this case, updateUI is completely unnecessary (I suggest you read the javadoc to learn its purpose).

One jPopup for several controls

I have code like this:
jTextArea1.add(jPopupMenu1);
jTextArea1.setComponentPopupMenu(jPopupMenu1);
jTextField1.add(jPopupMenu2);
jTextField1.setComponentPopupMenu(jPopupMenu2);
and for menu items I have actions:
private void CopyActionPerformed(java.awt.event.ActionEvent evt) {
jTextArea1.copy();
}
private void Copy1ActionPerformed(java.awt.event.ActionEvent evt) {
jTextField1.copy();
}
Now I think it would be better to use one popup for all text components, how to pass info about which component was clicked to copy text? Maybe there is some more general solution for such case?
Actions should be created by extending TextAction. The TextAction class has a method that will return the text component that last has focus. This action can then be used on a popup menu or on a menu added to the menu bar. So the basic code to create the menu item would be:
JMenuItem copy = new JMenuItem( new CustomAction() );
However, its even easier than that because the DefaultEditorKit already provides a default copy action so all you need to do is:
JMenuItem copy = new JMenuItem( new DefaultEditorKit.CopyAction() );
the Event class has a getSource() method that tells you what component was the cause of the event.

Categories