I am wondering why the JTabbedPane only adds 1 tab. When I use the method addTab and then reuse it to create a new tab, it overrides the first tab created. Here is the code: BTW, most of the code that might be related to the problem is at actionlistener.
package com.james.client;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.Element;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String [] args)
{
//JTextArea
final JTextArea code = new JTextArea();
final JTextArea lines = new JTextArea("1");
final JScrollPane scroll = new JScrollPane(code);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
lines.setBackground(Color.LIGHT_GRAY);
lines.setEditable(false);
code.getDocument().addDocumentListener(new DocumentListener(){
public String getText(){
int caretPosition = code.getDocument().getLength();
Element root = code.getDocument().getDefaultRootElement();
String text = "1" + System.getProperty("line.separator");
for(int i = 2; i < root.getElementIndex( caretPosition ) + 2; i++){
text += i + System.getProperty("line.separator");
}
return text;
}
#Override
public void changedUpdate(DocumentEvent de) {
lines.setText(getText());
}
#Override
public void insertUpdate(DocumentEvent de) {
lines.setText(getText());
}
#Override
public void removeUpdate(DocumentEvent de) {
lines.setText(getText());
}
});
scroll.getViewport().add(code);
scroll.setRowHeaderView(lines);
//JFrame
JFrame window = new JFrame("MinecraftProgrammer++");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(1000, 700);
window.setResizable(false);
window.setLocationRelativeTo(null);
//JMenuBar
JMenuBar menu = new JMenuBar();
JMenu file = new JMenu("File");
JMenu newfile = new JMenu("New");
//JTabbedPane
final JTabbedPane tabs = new JTabbedPane();
tabs.setBackground(Color.gray);
//JMenu items
JMenuItem classfile = new JMenuItem("Class");
JMenuItem packagefolder = new JMenuItem("Package");
JMenuItem other = new JMenuItem("Other");
JMenuItem open = new JMenuItem("Open");
open.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
try {
JFileChooser chooseFile = new JFileChooser();
chooseFile.setAcceptAllFileFilterUsed(false);
FileFilter filter1 = new ExtensionFileFilter("Java Class", new String[] {"JAVA"});
FileFilter filter2 = new ExtensionFileFilter("Text File", new String[] {"TXT"});
chooseFile.setFileFilter(filter2);
chooseFile.setFileFilter(filter1);
chooseFile.showOpenDialog(chooseFile);
String filePath = chooseFile.getSelectedFile().getAbsolutePath();
FileReader readFile = new FileReader(filePath);
String fileName = chooseFile.getSelectedFile().getName();
tabs.addTab(fileName, scroll);
#SuppressWarnings("resource")
Scanner fileReaderScan = new Scanner(readFile);
String storeAllString = "";
while(fileReaderScan.hasNextLine())
{
String temp = fileReaderScan.nextLine() + "\n";
storeAllString = storeAllString + temp;
}
code.setText(storeAllString);
code.setLineWrap(true);
code.setWrapStyleWord(true);
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println(e);
}
}
});
JMenuItem save = new JMenuItem("Save");
JMenuItem saveas = new JMenuItem("Save As...");
//Compile menu bar
file.add(newfile);
file.add(open);
file.add(save);
file.add(saveas);
newfile.add(classfile);
newfile.add(packagefolder);
newfile.add(other);
menu.add(file);
window.add(tabs);
window.setJMenuBar(menu);
window.setVisible(true);
}
}
You're adding the JScrollPane "scroll" to the JTabbedPane. How many times do you construct this component? Answer -- once only. So you're only adding and re-adding the same component every time.
final JScrollPane scroll = new JScrollPane(code); // here you create scroll
// .....
open.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
try {
JFileChooser chooseFile = new JFileChooser();
// ....
// you add the same component here
tabs.addTab(fileName, scroll);
// ....
}
Since you can't add a component to a container more than once and see it in both containers, the solution is to create any components needed for the new tab inside of the ActionListener's actionPerformed(...) method each time you need to add something to the JTabbedPane.
Related
How can I retrieve the currently selected menu or menu item when clicked on it and the subsequent path will be printed on console. In this code I have done the menus and sub menus up to 4 levels. And want to print the path of selected menus and submenus when clicked on. I am using swing concept for this program. Please help. Thanks in advance.
import java.awt.Component;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Menu {
public static void main(final String args[]) {
JFrame frame = new JFrame("MenuSample Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
JMenu worldMenu = new JMenu("world");
menuBar.add(worldMenu);
JMenu indMenu = new JMenu("India");
worldMenu.add(indMenu);
/* creates menu */
JMenu odMenu = new JMenu("Odisha");
indMenu.add(odMenu);
JMenu delhiMenu = new JMenu("Delhi");
indMenu.add(delhiMenu);
JMenu upMenu = new JMenu("Uttar Pradesh");
indMenu.add(upMenu);
JMenu mpMenu = new JMenu("Madhya Pradesh");
indMenu.add(mpMenu);
JMenu ausMenu = new JMenu("Australia");
worldMenu.add(ausMenu);
JMenu AmericaMenu = new JMenu("America");
worldMenu.add(AmericaMenu);
/* creates submenu */
JMenu bbMenu = new JMenu("Bhubaneswar");
odMenu.add(bbMenu);
JMenu bmMenu = new JMenu("Berhampur");
odMenu.add(bmMenu);
/*creates sub sub menu */
JMenuItem rjMenuItem = new JMenuItem("Raj Mahal");
bbMenu.add(rjMenuItem);
JMenuItem abMenuItem = new JMenuItem("Acharya Bihar");
bbMenu.add(abMenuItem);
JMenuItem bnMenuItem = new JMenuItem("Bani Bihar");
bbMenu.add(bnMenuItem);
/* retrieving path */
MenuSelectionManager.defaultManager().addChangeListener(
new ChangeListener() {
public void stateChanged(ChangeEvent evt) {
MenuElement[] path = MenuSelectionManager.defaultManager()
.getSelectedPath();
//
int s=0;
for (int i = 0; i < path.length; i++) {
Component c = path[i].getComponent();
if (c instanceof JMenuItem) {
JMenuItem mi = (JMenuItem) c;
String label = mi.getText();
System.out.println("LEVEL----" + s);
System.out.println("you hv selected:"+label);
s++;
}
}
}
});
//
frame.setJMenuBar(menuBar);
frame.setSize(350, 250);
frame.setVisible(true);
}
}
How to get the currently selected
Menu - A parent JMenu cannot be selected. Why would you want to know
if the mouse is over it?
MenuItem - Embrace the Action interface
It is an all too common oversight to not use the Action interface. When developing with Swing make Action your friend, it will treat you well. You went down the wrong path with MenuSelectionManager.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class MenuExample {
private JFrame frame;
private JLabel choiceIndicator;
MenuExample create() {
frame = createFrame();
choiceIndicator = new JLabel();
frame.setJMenuBar(createMenuBar());
frame.getContentPane().add(createContent());
return this;
}
private Component createContent() {
JPanel panel = new JPanel();
panel.add(new JLabel("Last menu item choice:"));
panel.add(choiceIndicator);
return panel;
}
private JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
menuBar.add(createWorld());
return menuBar;
}
private JMenu createWorld() {
JMenu worldMenu = new JMenu("World");
worldMenu.add(createIndia());
worldMenu.add(new JMenu("Australia"));
worldMenu.add(new JMenu("America"));
return worldMenu;
}
private JMenu createIndia() {
JMenu india = new JMenu("India");
india.add(createOdisha());
india.add(new JMenu("Delhi"));
india.add(new JMenu("Uttar Pradesh"));
india.add(new JMenu("Madhya Pradesh"));
return india;
}
private JMenuItem createOdisha() {
JMenu menu = new JMenu("Odisha");
menu.add(createBhubaneswar());
menu.add(new JMenu("Berhampur"));
return menu;
}
private JMenuItem createBhubaneswar() {
JMenu menu = new JMenu("Bhubaneswar");
menu.add(choiceItem("Raj Mahal"));
menu.add(choiceItem("Acharya Bihar"));
menu.add(choiceItem("Bani Bihar"));
return menu;
}
private JMenuItem choiceItem(String text) {
return new JMenuItem(new Choice(text, choiceIndicator));
}
private JFrame createFrame() {
JFrame frame = new JFrame(getClass().getSimpleName());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
return frame;
}
void show() {
frame.setSize(350, 250);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MenuExample().create().show();
}
});
}
class Choice extends AbstractAction {
private final JLabel choiceIndicator;
public Choice(String text, JLabel choiceIndicator) {
this(text, null, null, null, choiceIndicator);
}
public Choice(String text, ImageIcon icon, String desc, Integer mnemonic, JLabel choiceIndicator) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
this.choiceIndicator = choiceIndicator;
}
public void actionPerformed(ActionEvent e) {
choiceIndicator.setText(e.getActionCommand());
}
}
}
I am new for Java. I need to have MDI in my project. When the user clicks ‘Open’ in menu bar, the internal frame is added and should be full screen on top.
I still cannot make it full screen on top when it is open. Also in my code, if I remove the following line from “AddNote” method, I cannot see the internal frame. In logic the JDesktop should add when the form is open.
JDesktopPane desktop = new JDesktopPane();
There is my code:
package MyPackage;
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.*;
import java.io.*;
import java.awt.Dimension;
import java.awt.FlowLayout;
public class MainForm extends JFrame implements ActionListener {
private JMenuItem cascade = new JMenuItem("Cascade");
private int numInterFrame=0;
private JDesktopPane desktop=null;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run()
{
new MainForm();
}
});
}
public MainForm(){
super("Example");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// Name the JMenu & Add Items
JMenu menu = new JMenu("File");
menu.add(makeMenuItem("Open"));
menu.add(makeMenuItem("Save"));
menu.add(makeMenuItem("Quit"));
// Add JMenu bar
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
//menuBar.add(menuWindow);
setJMenuBar(menuBar);
this.setMinimumSize(new Dimension(400, 500));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
JDesktopPane desktop = new JDesktopPane();
this.add(desktop, BorderLayout.CENTER);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
// Menu item actions
String command = e.getActionCommand();
if (command.equals("Quit")) {
System.exit(0);
} else if (command.equals("Open")) {
// Open menu item action
JFileChooser fileChooser = new JFileChooser();
int returnVal = fileChooser.showOpenDialog(MainForm.this);
if (returnVal == fileChooser.APPROVE_OPTION) {
numInterFrame=numInterFrame+1;
File file = fileChooser.getSelectedFile();
AddNote(numInterFrame);
// Load file
} else if (returnVal == JFileChooser.CANCEL_OPTION ) {
// Do something else
}
}
else if (command.equals("Save")) {
// Save menu item action
System.out.println("Save menu item clicked");
}
}
private JMenuItem makeMenuItem(String name) {
JMenuItem m = new JMenuItem(name);
m.addActionListener(this);
return m;
}
private void AddNote(int index){
JDesktopPane desktop = new JDesktopPane();
JInternalFrame internalFrame = new JInternalFrame("PDFAnnotation" + index, true, true, true, true);
internalFrame.setBounds(0, 0, 600, 100);
desktop.add(internalFrame);
PDFPanel p=new PDFPanel();
JPanel e =p.getJPanel();
internalFrame.add(e, BorderLayout.CENTER);
internalFrame.setVisible(true);
this.add(desktop, BorderLayout.CENTER);
/* Dimension size = desktop.getSize();
int w = size.width ;
int h = size.height ;
int x=0;
int y=0;
desktop.getDesktopManager().resizeFrame(internalFrame, x, y, w, h);*/
}
}
There are a number problems, which are compounded based on the fact that you are shadowing the main desktop variable...
You declare an instance field....
private JDesktopPane desktop = null;
But in your constructor, you declare it again...
JDesktopPane desktop = new JDesktopPane();
This means that the instance field remains null. Instead, in you constructor, you should be using the instance field, for example...
desktop = new JDesktopPane();
This means that in your AddNote method, you can get rid of the creation of yet another JDesktopPane...
//JDesktopPane desktop = new JDesktopPane();
JInternalFrame internalFrame = new JInternalFrame("PDFAnnotation" + index, true, true, true, true);
internalFrame.setBounds(0, 0, 600, 100);
desktop.add(internalFrame);
PDFPanel p = new PDFPanel();
JPanel e = p.getJPanel();
internalFrame.add(e, BorderLayout.CENTER);
internalFrame.setVisible(true);
//this.add(desktop, BorderLayout.CENTER);
Also, because you're using...
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
You won't need
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
You should also have a read of Code Conventions for the Java Programming Language
I have been working on an html text editing program for a while and i wondered if anyone could help me with this small problem. I have two jmenus but one of them are misbehaving. i have two problems. 1 the menu item in the menu has a submenu arrow although it is not a sub menu
is that i have added an action listener to the menu but when i click the action doesent happen. here is the code.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
public class Window {
static boolean saved = false;
static boolean opened = false;
static File saveDirectory = null;
static File openDirectory = null;
static final JTextArea editor = new JTextArea(10,50);
public static void openWindowEditor(){
JFrame f = new JFrame("Easy HTML Text editor");
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
JMenu viewMenu = new JMenu("View");
JMenuItem fileMenuSave = new JMenuItem("Save");
JMenuItem fileMenuOpen = new JMenuItem("Open");
JMenuItem fileMenuSaveAs = new JMenuItem("Save as...");
JMenuItem viewMenuEasyInsert = new JMenu("Easy insert");
fileMenu.setMnemonic(KeyEvent.VK_A);
viewMenu.setMnemonic(KeyEvent.VK_A);
menuBar.add(fileMenu);
menuBar.add(viewMenu);
fileMenu.add(fileMenuSave);
fileMenu.add(fileMenuOpen);
fileMenu.add(fileMenuSaveAs);
viewMenu.add(viewMenuEasyInsert);
fileMenuSave.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
save(editor.getText());
}
});
fileMenuOpen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
open();
}
});
fileMenuSaveAs.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveAs();
}
});
viewMenuEasyInsert.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
openEasyInsertWindow();
}
});
f.setJMenuBar(menuBar);
f.add(editor);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLayout(new GridLayout(1,1));
f.pack();
f.setVisible(true);
}
public static void open(){
JFileChooser chooser = new JFileChooser();
int returnVal = chooser.showDialog(null, "open");
if(returnVal == JFileChooser.APPROVE_OPTION){
File file = chooser.getSelectedFile();
try{
editor.read(new FileReader(file), null);
}catch(IOException e){
JOptionPane.showMessageDialog(null, e);
}
}
}
public static void save(String text){
JFileChooser chooser = new JFileChooser();
File file = null;
int returnVal = chooser.showDialog(null, "Save");
if(returnVal == JFileChooser.APPROVE_OPTION){
file = (chooser.getSelectedFile());
String result = text.replace("\n", System.getProperty("line.separator"));
saveDirectory = chooser.getSelectedFile();
try{
FileWriter fw = new FileWriter(file);
fw.write(result);
fw.close();
saved = true;
}catch(IOException e){
JOptionPane.showMessageDialog(null, e);
}
}
}
public static void saveAs(){
JFileChooser chooser = new JFileChooser();
File dir;
int returnVal = chooser.showDialog(null, "Save as...");
if(returnVal == JFileChooser.APPROVE_OPTION){
dir = chooser.getSelectedFile();
try{
FileWriter fw = new FileWriter(dir);
fw.write(editor.getText());
fw.close();
}catch(IOException e){
JOptionPane.showMessageDialog(null, e);
}
}
}
public static void openEasyInsertWindow(){
JFrame f = new JFrame("easy insert");
JButton insertDivButton = new JButton("Insert <div> element");
JButton openInsertSettings = new JButton("Open the insert settings");
f.setLayout(new GridLayout(2,1));
f.add(insertDivButton);
f.add(openInsertSettings);
f.pack();
f.setVisible(true);
JOptionPane.showMessageDialog(editor, "Easy insert");
}
}
Because you've defined it as a JMenu and not a JMenuItem
JMenuItem viewMenuEasyInsert = new JMenu("Easy insert");
should be
JMenuItem viewMenuEasyInsert = new JMenuItem("Easy insert");
i don't know how to change frame's title when an drag and drop event takes place. I 've read Java Docs about DnD and Transferable but i can't find a solution, i've come to an conclusion that i have to play games with DropTargetListener, but i am to a deadlock.Any answer would be a relief!(also in drag n drop i would like to hold the attributes of the text)
The SSCCE is:
package sscceeditor;
import java.io.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.text.BadLocationException;
import rtf.AdvancedRTFDocument;
import rtf.AdvancedRTFEditorKit;
class ExampleFrame extends JFrame{
private JMenuBar bar = new JMenuBar();
private JMenu fileMenu = new JMenu("File");
private JMenuItem saveItem = new JMenuItem("Save");
private JMenuItem loadItem = new JMenuItem("Load");
private JTextPane txtPane = new JTextPane(new AdvancedRTFDocument());
private JScrollPane scroller = new JScrollPane(txtPane);
private JFileChooser chooser = new JFileChooser();
private AdvancedRTFEditorKit rtfKit = new AdvancedRTFEditorKit();
//ctor begins...
public ExampleFrame(){
super("Example Editor");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 400);
this.setLocationRelativeTo(null);
saveItem.addActionListener(new SaveHandler());
loadItem.addActionListener(new LoadHandler());
this.addDragAndDropSupportToJTextPane(txtPane);
//set the kit...
txtPane.setEditorKit(rtfKit);
//create the menu...
fileMenu.add(saveItem);
fileMenu.add(loadItem);
bar.add(fileMenu);
this.setJMenuBar(bar);
//create the main panel...
JPanel mainPane = new JPanel();
mainPane.setLayout(new BorderLayout());
mainPane.add(BorderLayout.CENTER , scroller);
this.setContentPane(mainPane);
}//end of ctor.
//inner event handler classes...
class SaveHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
int response = chooser.showSaveDialog(ExampleFrame.this);
if(response == JFileChooser.APPROVE_OPTION){
try(BufferedWriter bw = new BufferedWriter(
new FileWriter(chooser.getSelectedFile().getPath())))
{
rtfKit.write(bw, txtPane.getDocument(), 0, txtPane.getDocument().getLength());
bw.close();
JOptionPane.showMessageDialog( ExampleFrame.this,"Saved");
txtPane.setText("");
}catch(IOException | BadLocationException ex){
System.err.println(ex);
}
}
}//end of method.
}
class LoadHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
int response = chooser.showOpenDialog(ExampleFrame.this);
if(response == JFileChooser.APPROVE_OPTION){
StringBuilder sb = new StringBuilder();
try(BufferedReader bw = new BufferedReader(
new FileReader(chooser.getSelectedFile().getPath())))
{
txtPane.setText("");
rtfKit.read(bw, txtPane.getDocument(), 0);
bw.close();
}catch(IOException | BadLocationException ex){
System.err.println(ex);
}
}
}//end of method.
}
private void addDragAndDropSupportToJTextPane(JTextPane thePane){
thePane.setDragEnabled(true);
thePane.setDropMode(DropMode.INSERT);
}//end of method.
}//end of class ExampleFrame.
public class SSCCEeditor {
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
new ExampleFrame().setVisible(true);
}
});
}
}
Thanks a lot for your time!
Im trying to add a checkboxgroup to my menu but keep getting a "Cannot find symbol" error.
MenuBar mb = new MenuBar();
Menu file = new Menu("File");
Menu colorM = new Menu("Color");
MenuItem quitM = new MenuItem("Quit", new MenuShortcut(KeyEvent.VK_Q));
CheckboxGroup cbg = new CheckboxGroup();
Checkbox cb1 = new Checkbox("Black",cbg,true);
Checkbox cb2 = new Checkbox("Red",cbg,false);
Checkbox cb3 = new Checkbox("Blue",cbg,false);
Checkbox cb4 = new Checkbox("Green",cbg,false);
Then in my initialization i have
chatF.setMenuBar(mb);
mb.add(file);
mb.add(colorM);
file.add(quitM);
colorM.add(cbg);
I tried adding a MenuItem and putting the cbg in there but same problem
CheckboxGroup is not a Component (or, more specifically, a MenuItem), so you can't add it to the menu. Instead, you can create a CheckboxMenuItem, but I think CheckboxGroup only works with instances of Checkbox so you'll have to write your own code to enforce single-selection.
If Swing is an option, you can instead use JRadioButtonMenuItem and ButtonGroup:
package com.example.checkboxmenu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
public class CheckboxMenu extends JFrame {
public CheckboxMenu() {
JMenuBar mb = new JMenuBar();
JMenu file = new JMenu("File"); //$NON-NLS-1$
JMenu colorM = new JMenu("Color");
JMenuItem quitM = new JMenuItem("Quit", KeyEvent.VK_Q);
JRadioButtonMenuItem cb1 = new JRadioButtonMenuItem("Black", true);
JRadioButtonMenuItem cb2 = new JRadioButtonMenuItem("Red", true);
JRadioButtonMenuItem cb3 = new JRadioButtonMenuItem("Blue", true);
JRadioButtonMenuItem cb4 = new JRadioButtonMenuItem("Green", true);
ButtonGroup group = new ButtonGroup();
group.add(cb1);
group.add(cb2);
group.add(cb3);
group.add(cb4);
setJMenuBar(mb);
mb.add(file);
mb.add(colorM);
file.add(quitM);
colorM.add(cb1);
colorM.add(cb2);
colorM.add(cb3);
colorM.add(cb4);
quitM.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400,300);
setVisible(true);
}
/**
* #param args
*/
public static void main(String[] args) {
new CheckboxMenu();
}
}
You can't add a CheckboxGroup to a Menu... you can only add MenuItem instances. You can add a CheckboxMenuItem, but this doesn't understand CheckboxGroup either.
So you need to change the CheckBoxs to CheckboxMenuItems, add them individually to the menu, roll your own CheckboxMenuItemGroup class and use it to bind the CheckboxMenuItems together.
Something like the following should work:
public class CheckboxMenuItemGroup implements ItemListener {
private Set<CheckboxMenuItem> items = new HashSet<CheckboxMenuItem>();
public void add(CheckboxMenuItem cbmi) {
cbmi.addItemListener(this);
cbmi.setState(false);
items.add(cbmi);
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
String itemAffected = (String) e.getItem();
for (CheckboxMenuItem item : items) {
// Use this line to allow user to toggle the selected item off
if (!item.getLabel().equals(itemAffected)) item.setState(false);
// Use this line to force one of the items to always be selected
// item.setState(item.getLabel().equals(itemAffected));
}
}
}
public void selectItem(CheckboxMenuItem itemToSelect) {
for (CheckboxMenuItem item : items) {
item.setState(item == itemToSelect);
}
}
public CheckboxMenuItem getSelectedItem() {
for (CheckboxMenuItem item : items) {
if (item.getState()) return item;
}
return null;
}
}
This should work because ItemListeners don't get called when code calls item.setState(), only when the user clicks on the item in the menu. Just make sure you only set the state of the items with the CheckboxMenuItemGroup.selectItem() call, otherwise you could end up with more than one item selected.
Then you just need to build your menu like this:
public static void main(String[] args) {
final Frame f = new Frame("Test CheckboxMenuItemGroup");
MenuBar mb = new MenuBar();
Menu menu = new Menu("Menu");
CheckboxMenuItem cb1 = new CheckboxMenuItem("Black");
CheckboxMenuItem cb2 = new CheckboxMenuItem("Red");
CheckboxMenuItem cb3 = new CheckboxMenuItem("Blue");
CheckboxMenuItem cb4 = new CheckboxMenuItem("Green");
CheckboxMenuItemGroup mig = new CheckboxMenuItemGroup();
mig.add(cb1);
mig.add(cb2);
mig.add(cb3);
mig.add(cb4);
mig.selectItem(cb1);
menu.add(cb1);
menu.add(cb2);
menu.add(cb3);
menu.add(cb4);
f.setMenuBar(mb);
f.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setSize(300, 200);
f.setVisible(true);
}
Using swing instead of awt.
JMenuBar menuBar = new JMenuBar();
JMenu color = new JMenu("Color");
JCheckBoxMenuItem cb1 = new JCheckBoxMenuItem("Black");
JCheckBoxMenuItem cb2 = new JCheckBoxMenuItem("Red");
JCheckBoxMenuItem cb3 = new JCheckBoxMenuItem("Blue");
JCheckBoxMenuItem cb4 = new JCheckBoxMenuItem("Green");
ButtonGroup group = new ButtonGroup();
group.add(cb1);
group.add(cb2);
group.add(cb3);
group.add(cb4);
menuBar.add(cb1);
menuBar.add(cb2);
menuBar.add(cb3);
menuBar.add(cb4);
setJMenuBar(menuBar); // Set the JMenuBar of the JFrame
You can add any AbstractButton to a ButtonGroup.
On OSX Java 7 (1.7.0_40) Julians answer doesnt quite work because the object returned by ItemEvent is actually a String rather than a CheckBoxItem, soiunds like a bug in OSX but got it working by modifying the itemStateChanged method
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashSet;
import java.util.Set;
public class CheckboxMenuItemGroup implements ItemListener
{
private Set<CheckboxMenuItem> items = new HashSet<CheckboxMenuItem>();
public void add(CheckboxMenuItem cbmi) {
cbmi.addItemListener(this);
cbmi.setState(false);
items.add(cbmi);
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
String itemAffected = (String)e.getItem();
for (CheckboxMenuItem item : items) {
if (item.getLabel() != itemAffected) item.setState(false);
}
}
}
public void selectItem(CheckboxMenuItem itemToSelect) {
for (CheckboxMenuItem item : items) {
item.setState(item == itemToSelect);
}
}
public CheckboxMenuItem getSelectedItem() {
for (CheckboxMenuItem item : items) {
if (item.getState()) return item;
}
return null;
}
}