I'm working on a Java desktop Application that uses multiple Jpanels as cards in a CardLayout, the problem is that when I switch between the cards the JmenuBar disappears totally or just parts of it.I have a mainFramewhich holds all the Jpanels and the JmenuBar, the other Jpanels have some texts and JButtons and JLabels Here's how I'm implementing this :
This is the Frame that holds everything mainFrame.java
public class mainFrame extends JFrame {
JPanel cards ;
menubar menu= new menubar();
mainPanel card1 = new mainPanel();
Ajout card2= new Ajout();
//ViewAjoutEnf card3= new ViewAjoutEnf();
public mainFrame(){
setResizable(true);
setExtendedState(JFrame.MAXIMIZED_BOTH);
this.add(menu);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cards = new JPanel(new CardLayout());
cards.add(card1, "Card 1");
cards.add(card2, "Card 2");
// cards.add(card3, "Card 3");
getContentPane().add(cards);
}
This is the JmenuBar class menubar.Java:
public class menubar extends JMenuBar{
JMenu menuouvrir = new JMenu("ملف");
JMenuItem ajoutbase = new JMenuItem("فتح");
JMenuItem quiter = new JMenuItem("خروج ");
JMenuItem motpass = new JMenuItem("تبديل كلمة السر");
JMenu menuajout = new JMenu("ادخال ");
JMenuItem ajoutprodui = new JMenuItem("ادخال منتوج");
JMenuItem listproduit = new JMenuItem("لائحة المنتوجات");
JMenu menusortie = new JMenu("اخراج");
JMenuItem sortiproduit = new JMenuItem("اخراج منتوج");
JMenu retour = new JMenu("عودة ");
JMenu menuapropos = new JMenu("?");
public menubar (){
this.setBounds(0, 0, 1370, 30);
this.add(Box.createHorizontalGlue());
this.setFont(new Font("sans-serif", Font.PLAIN, 12));
menuouvrir.add(ajoutbase);
menuouvrir.add(motpass);
menuouvrir.addSeparator();
menuouvrir.add(quiter);
menuajout.add(ajoutprodui);
menuajout.add(listproduit);
menusortie.add(sortiproduit);
this.add(menuapropos);
this.add(retour);
this.add(menusortie);
this.add(menuajout);
this.add(menuouvrir);
this.setVisible(true);
}
and these are the Two Jpanels i have:
mainPanel.Java
public class mainPanel extends JPanel {
JButton but = new JButton("dsdffd");
public mainPanel(){
this.setLayout(null);
this.add(but);
but.setBounds(70,500,70,70);
this.setBackground(Color.white);
this.setVisible(true);
}
}
and Ajou.Java:
public class Ajout extends JPanel{
JButton but = new JButton("dsdffd");
public Ajout(){
this.setLayout(null);
this.add(but);
but.setBounds(70,500,70,70);
this.setBackground(Color.white);
this.setVisible(true);
}
}
Don't extend JMenuBar. There is no reason to do this. You create an instance of JMenuBar and and add JMenu instances to the menu bar.
Don't use a null layout. A JMenuBar has its own layout manager.
I don't see where you add the menu bar to the frame using the setJMenBar(...) method.
Read the section from the Swing tutorial on How to Use Menus for more information and working examples. The examples will also show you how to better structure your code.
Also, don't keep extending panels just to add a single component to the panel. You can add multiple components to any panel. And make sure your panels use a layout manager.
Related
I want to make an app where I have a JPanel with no default layout. I want to be able to change the layout using options from the menu. For instance, if I have a control to add three image icons to the JPanel , the size and position of these icons should be determined by the frame's current layout manager.
So if I add 3 image icons to a Border Layout (adding them in the South, East and Center positions), switching the layout to a flow layout should make them appear in right to left order with no resizing.
I am confused as to how to go about that. Is there a way to switch layouts within the same JPanel like this?
To dynamically change layouts after each menu action, set the new layout with its constraints and call the revalidate() method. Check the actionPerformed() method of below code.
public class LayoutController extends JFrame implements ActionListener {
JMenuItem flowLayout;
JMenuItem borderLayout;
JMenuItem gridLayout;
JPanel panel;
JButton button1;
JButton button2;
JButton button3;
public LayoutController() {
setSize(600, 600);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(null); // no default layout
panel.setSize(600, 600);
flowLayout = new JMenuItem("Flow Layout");
flowLayout.addActionListener(this);
borderLayout = new JMenuItem("Border Layout");
borderLayout.addActionListener(this);
gridLayout = new JMenuItem("Grid Layout");
gridLayout.addActionListener(this);
// menu to change layout dynamically
JMenu fileMenu = new JMenu("Layout");
fileMenu.add(flowLayout);
fileMenu.add(borderLayout);
fileMenu.add(gridLayout);
JMenuBar menuBar = new JMenuBar();
menuBar.add(fileMenu);
setJMenuBar(menuBar);
// Customize your components
button1 = new JButton("IMAGE1");
button2 = new JButton("IMAGE2");
button3 = new JButton("IMAGE3");
panel.add(button1);
panel.add(button2);
panel.add(button3);
add(panel, BorderLayout.CENTER);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new LayoutController().setVisible(true);
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
//Customize your code here
if (e.getSource() == flowLayout) {
//flow layout with right alignment
panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
} else if (e.getSource() == borderLayout) {
// border layout with constraints
BorderLayout layout = new BorderLayout();
layout.addLayoutComponent(button1, BorderLayout.SOUTH);
layout.addLayoutComponent(button2, BorderLayout.EAST);
layout.addLayoutComponent(button3, BorderLayout.CENTER);
panel.setLayout(layout);
} else if (e.getSource() == gridLayout) {
// grid layout with 2 rows and 2 columns
panel.setLayout(new GridLayout(2, 2));
}
panel.revalidate();
}
}
I have a problem with my application GUI. I would like to create one global JMenuBar and share it to other JPanels, but if i want to assign to multi JPanels i have error:
#
"The menuBar component is added to a parent component more than once.
•panelAll.add(menuBar);
•panelTask.add(menuBar);"
#
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
JPanel panelAll = new JPanel();
frame.getContentPane().add(panelAll, "name_218556506364138");
panelAll.setLayout(null);
JMenuBar menuBar = new JMenuBar();
menuBar.setBounds(0, 0, 795, 21);
panelAll.add(menuBar);
JPanel panelTask = new JPanel();
frame.getContentPane().add(panelTask, "name_218567310779840");
panelTask.setLayout(null);
panelTask.add(menuBar);
JPanel panelMyTask = new JPanel();
frame.getContentPane().add(panelMyTask, "name_218578712986622");
panelMyTask.add(menuBar);
JPanel panelMySoftware = new JPanel();
frame.getContentPane().add(panelMySoftware, "name_218590026900741");
panelMySoftware.add(menuBar);
JPanel panelMyDevices = new JPanel();
frame.getContentPane().add(panelMyDevices, "name_218598029981563");
panelMyDevices.add(menuBar);
}
}
Image
i don't think its a good idea to add a JMenuBar into a JPanel, but if you insist...
a JMenuBar can be added only to one container, so you need to create more instances of the JMenuBar. That should work without problems if you use the command pattern.
//first instance
JMenuBar taskMenuBar = new MyJMenuBarImplementation();
JPanel panelMyTask = new JPanel();
frame.getContentPane().add(panelMySoftware, "name_xxx");
panelMyTask.add(taskMenuBar);
//second instance
JMenuBar softwareMenuBar = new MyJMenuBarImplementation();
JPanel panelMySoftware = new JPanel();
frame.getContentPane().add(panelMySoftware, "name_yyy");
panelMySoftware.add(softwareMenuBar);
//and so on...
I need to create a JMenuBar that will be shown under of JTabbedPane named as shapes. When I changed tab, menu bar will not be shown in the other tab. You can see what I mean from images.
I created a menu bar and add it to JFrame but that is not I mean. If you did not understand a point let me explain.
public class Gui extends JPanel {
JFrame frame;
JTabbedPane tabbedPane;
JMenuBar menuBar;
JMenu createShapes, display, help;
JMenuItem RandomShapes, Rectangle, Circle, Square;
public void createFrame() {
frame = new JFrame();
frame.setSize(1000, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.setVisible(true);
frame.setFocusable(false);
setVisible(true);
setSize(1000, 600);
}
public void createMenus() {
menuBar = new JMenuBar();
//frame.setJMenuBar(menuBar);
createShapes = new JMenu("CreateShapes");
menuBar.add(createShapes);
display = new JMenu("Display");
menuBar.add(display);
help = new JMenu("Help");
menuBar.add(help);
RandomShapes = new JMenuItem("Random Shapes");
createShapes.add(RandomShapes);
Rectangle = new JMenuItem("Rectangle");
createShapes.add(Rectangle);
Circle = new JMenuItem("Circle");
createShapes.add(Circle);
Square = new JMenuItem("Square");
createShapes.add(Square);
}
public Gui() {
createFrame();
createMenus();
frame.add(this);
//===frames part
tabbedPane = new JTabbedPane();
frame.getContentPane().add(tabbedPane);
JPanel gui2 = new JPanel();
tabbedPane.addTab("Shapes", this);
tabbedPane.addTab("Images", gui2);
//===endframespart
}
}
The other tab image
Shapes tab image
Actually, you cannot set menu bar to JTabbedPane.
You need to add JInternalFrame inside one of the tabs of JTabbedPane, then
you can call setJMenuBar of JInternalFrame.
Here is a simple example:
JInternalFrame jInternalFrame = new JInternalFrame();
jMenuBar = new javax.swing.JMenuBar();
jMenu1 = new JMenu("Save");
jMenu2 = new JMenu("Open");
jMenuBar.add(jMenu1);
jMenuBar.add(jMenu2);
jInternalFrame.setJMenuBar(jMenuBar);
tabbedPane.addTab("tab3", jInternalFrame);
I'm working on a GUI and I'm not having some trouble with panes.
My GUI is divided into two parts (topPane and bottomPane).
I have buttons and labels on both panes, but one of the button functions I wanted to change the background color, but it's not doing the job.
What I did is that I used a Container (called thisContentPane) to change the background color of my entire GUI.
Here is my current code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class TempConverter extends JFrame
{
//Creating a contentPane down inside the inner class
Container thisContentPane;
//class scope variables : DO NOT CREATE THIS OBJECTS HERE.
JButton calculateButton, clearButton;
JTextField celsiusField, fahrenheitField, kelvinField;
//menu
JMenuBar menuBar = new JMenuBar();
JMenu backgroundColor = new JMenu("Background Color");
JMenu help = new JMenu("Help");
JMenuItem lightGray, white, black, blue, howToUse, about;
//constructor
TempConverter()
{
super("Temperature Converter App");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
this.setSize(400,200);;
this.setLocationRelativeTo(null);
//menuBar
this.setJMenuBar(menuBar);
menuBar.add(backgroundColor);
//adding JMenu to JMenuBar
menuBar.add(backgroundColor);
menuBar.add(help);
//adding JMenuItems
lightGray = backgroundColor.add("LIGHTGRAY");
white = backgroundColor.add("WHITE");
black = backgroundColor.add("BLACK");
blue = backgroundColor.add("BLUE");
howToUse = help.add("How To Use");
about = help.add("Help");
//babysitter
MaryPoppins babysitter = new MaryPoppins();
//adding action listener to the menu item
lightGray.addActionListener(babysitter);
white.addActionListener(babysitter);
black.addActionListener(babysitter);
blue.addActionListener(babysitter);
howToUse.addActionListener(babysitter);
about.addActionListener(babysitter);
//building JPanels
JPanel topPanel = new JPanel();
topPanel.setLayout(new GridLayout(3,2,0,20));
//add this to JFrame in centerzone
this.add(topPanel, BorderLayout.CENTER);
//bottom panel
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new FlowLayout());
//add this to JFrame in bottom
this.add(bottomPanel, BorderLayout.SOUTH);
//add components to the panels
//add the buttons
calculateButton = new JButton("Calculate");
clearButton = new JButton("Clear");
//add buttons
bottomPanel.add(calculateButton);
bottomPanel.add(clearButton);
//register listeners
calculateButton.addActionListener(babysitter);
clearButton.addActionListener(babysitter);
//add components to the top panel
JLabel labelOne = new JLabel("Celsius:");
JLabel secondOne = new JLabel("Fahrenheit:");
JLabel thirdOne = new JLabel("Kelvin:");
celsiusField = new JTextField("");
fahrenheitField = new JTextField("");
kelvinField = new JTextField("");
//add the label and text fields
topPanel.add(labelOne);
topPanel.add(celsiusField);
topPanel.add(secondOne);
topPanel.add(fahrenheitField);
topPanel.add(thirdOne);
topPanel.add(kelvinField);
this.setVisible(true);
} // end constructor
public static void main (String[] args) {
new TempConverter();
}
private class MaryPoppins implements ActionListener
{
//implement the abstract method from the interface
public void actionPerformed(ActionEvent ev)
{
thisContentPane = getContentPane();
if(ev.getActionCommand().equals("LIGHTGRAY"))
{
thisContentPane.setBackground(Color.lightGray);
}
else if (ev.getActionCommand().equals("BLUE"))
{
thisContentPane.setBackground(Color.BLUE);
}
else if(ev.getActionCommand().equals("WHITE") )
{
thisContentPane.setBackground(Color.WHITE);
}
else if (ev.getActionCommand().equals("BLACK"))
{
thisContentPane.setBackground(Color.BLACK);
}else if (ev.getActionCommand().equals("Clear"))
{
thisContentPane.setBackground(Color.BLACK);
}
else if (ev.getActionCommand().equals("BLACK"))
{
thisContentPane.setBackground(Color.BLACK);
}
}//end ActionPerformed()
}//end inner class
} // end class
When I click the buttons or menu items it doesn't do anything.
Your problem is that your contentPanel's background color is not "visible": your topPanel and your bottomPanel are on top of it :)
You should either do:
if (ev.getActionCommand().equals("LIGHTGRAY")) {
thisTopPanel.setBackground(Color.lightGray);
thisBottemPanel.setBackground(Color.lightGray);
}
... and do it for each of your if conditions (you know what I mean).
But that's not really the best way to go. An alternative that, in my opinion, makes perfect sense 'cause it reflects the exact behaviour you're looking for, would be:
topPanel.setOpaque(false);
bottomPanel.setOpaque(false);
I would obviously recommend the second option ;)
Also, since I'm at it, I prefer to use Color.LIGHTGRAY (and Color.BLACK, Color.WHITE, etc.) instead of Color.lightGrey, because these aliases respect the convention that states that constants must be upper-case.
I just started to learn swing by myself, I'm little bit confused why my event does not work here:
1.I'm trying to delete everything from my panel if the user click menu bar -> load but it force me to change the panel to final because i'm using it inside the event!
2.I have defined new panel in my event and defined two more container to add to that panel and then add it to the main frame but it seems nothing happening!
Please help me if you can find out what is wrong.
Sorry in advance for messy code.
I appreciate any hints.
public class SimpleBorder {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable()
{
public void run()
{
myFrame frame = new myFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
class MyFrame extends JFrame {
public MyFrame()
{
setSize(500,500);
JPanel panel = new JPanel();
panel.setLayout(null);
JLabel label = new JLabel("my name is bernard...");
Color myColor = new Color(10, 150, 80);
panel.setBackground(myColor);
label.setFont(new Font("Serif", Font.PLAIN, 25));
Dimension size = label.getPreferredSize();
Insets insets = label.getInsets();
label.setBounds(85+insets.left, 120+insets.top , size.width, size.height);
panel.add(label);
JMenuBar menu = new JMenuBar();
setJMenuBar(menu);
JMenu col = new JMenu("Collection");
menu.add(col);
JMenu help = new JMenu("Help");
menu.add(help);
Action loadAction = new AbstractAction("Load")//menu item exit goes here
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent event)
{
JTextArea text = new JTextArea(10, 40);
JScrollPane scrol1 = new JScrollPane(text);
String[] items = {"A", "B", "C", "D"};
JList list = new JList(items);
JScrollPane scrol2 = new JScrollPane(list);
JPanel panel2 = new JPanel(new BorderLayout());
panel2 = new JPanel(new GridLayout(1, 2 ));
panel2.add(scrol1,BorderLayout.WEST);
panel2.add(scrol2,BorderLayout.EAST);
add(panel2);
}
};
JMenuItem load = new JMenuItem(loadAction);
col.add(load);
add(panel);
}
}
Call revalidate()/repaint() on your JFrame instance after adding the new panel:
JPanel panel2 = new JPanel(new BorderLayout());
// panel2 = new JPanel(new GridLayout(1, 2 ));//why this it will overwrite the above layout
panel2.add(scrol1,BorderLayout.WEST);
panel2.add(scrol2,BorderLayout.EAST);
add(panel2);
revalidate();
repaint();
Also call pack() on you JFrame instance so all components are spaced by the layoutmanager. As said in a comment dont extend the JFrame class, create a variable of the frame and initiate all that you need on the frames instance, and dont set a layout to null, unless you love hard work :P
Alternatively as mentioned by mKorbel, a CardLayout may be more what you want, it will allow you to use a single JPanel and switch between others/new ones:
JPanel cards;
final static String BUTTONPANEL = "Card with JButtons";
final static String TEXTPANEL = "Card with JTextField";
//Where the components controlled by the CardLayout are initialized:
//Create the "cards".
JPanel card1 = new JPanel();
...
JPanel card2 = new JPanel();
...
//Create the panel that contains the "cards".
cards = new JPanel(new CardLayout());
cards.add(card1, BUTTONPANEL);
cards.add(card2, TEXTPANEL);
//add card panel to frame
frame.add(cards);
//swap cards
CardLayout cl = (CardLayout)(cards.getLayout());//get layout of cards from card panel
cl.show(cards, TEXTPANEL);//show another card