I am trying to work out how to navigate across multiple panels in swing. I would like to do this by using the CardLayout as opposed to using glass panels as from what I have read it seems that this is the correct tool for this job (however, feel free to correct me if you know otherwise). I have written a test case which almost achieves this but falls short on 2 fronts. It uses the depreciated "show()" method and furthermore after it switches to the second card the buttons from card1 begin to mysteriously float through to the surface again!
public class test extends JPanel implements ActionListener{
final static int extraWindowWidth = 100;
JButton jbtnOne = new JButton("Button 1");
JPanel cardPanel = new JPanel(new CardLayout());
JPanel card1 = new JPanel();
JPanel card2 = new JPanel();
public void addComponentToPane(Container pane) {
//Create the "cards".
JPanel card1 = new JPanel() {
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
size.width += extraWindowWidth;
return size;
}
};
card1.add(jbtnOne);
card1.add(new JButton("Button 2"));
card1.add(new JButton("Button 3"));
card2.add(new JTextField("TextField", 20));
cardPanel.add(card1, "card1");
cardPanel.add(card2, "card2");
pane.add(cardPanel, BorderLayout.CENTER);
jbtnOne.addActionListener(this);
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TabDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
test demo = new test();
demo.addComponentToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == jbtnOne){
System.out.println("HERE");
card2.show();
}
}
}
The CardLayout is managing the components so you will need to call show on the CardLayout instead of JPanel#show:
CardLayout cardLayout = (CardLayout) cardPanel.getLayout();
cardLayout.show(cardPanel, "card2");
Alternatively, when switching card components, you could also use
cardLayout.next(cardPanel);
Related
I am learning Java and I have to develop an application using a GUI. I have the application working in command line already, but the GUI is driving me insane and costing me in lost hours of head banging and research which is leading nowhere. Can you please help me get the basics working so that i can develop further from there. I want to have a single frame application that can switch between frames on a button click. I created a frame and added three panels P1-P3. These are set as Card Layout (from what i read from forums). Then I added additional panels to these to which i have set colour and buttons.
'''
public class MyMainForm extends JFrame{
private JPanel P1;
private JPanel P2;
private JPanel P3;
private JButton btnFrame1;
private JButton btnFrame2;
private JButton button1;
private JTextField thisIsPanel3TextField;
private JButton btn2Frame1;
private final JFrame frame = new JFrame("MyMain Frame");
public MyMainForm() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(P1);
pack();
setSize(1000,800);
//setLocation(null);
btnFrame1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
P1.setVisible(false);
setContentPane(new MyMainForm().P2);
}
});
btnFrame2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
P2.setVisible(false);
setContentPane(new MyMainForm().P3);
}
});
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
P3.setVisible(false);
setContentPane(new MyMainForm().P2);
}
});
btn2Frame1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
P1.setVisible(false);
setContentPane(new MyMainForm().P3);
}
});
}
public static void main(String[] args) {
MyMainForm MyMainForm = new MyMainForm();
MyMainForm.setVisible(true);
}
}
'''
I can display P2 or P3 with this new code example above. When i try to go from P2 or P3 back to P1 the content pane doesn't show? Do i need to revalidate the content pane for this to work? I really need to be able to go from P1 to P2
The easiest way to do this is to use a CardLayout. Just follow this example:
JFrame frame = new JFrame();
JPanel p1 = new JPanel();
p1.setBackground(Color.RED);
JPanel p2 = new JPanel();
p2.setBackground(Color.WHITE);
JPanel p3 = new JPanel();
p3.setBackground(Color.BLUE);
//Create the panel that contains the "cards".
JPanel cards = new JPanel(new CardLayout());
cards.add(p1, "Panel 1");
cards.add(p2, "Panel 2");
cards.add(p3, "Panel 3");
// Add your card container to the frame
Container pane = frame.getContentPane();
pane.add(cards, BorderLayout.CENTER);
JButton btn = new JButton("Click me!");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed (ActionEvent e) {
CardLayout cl = (CardLayout)(cards.getLayout());
cl.next(cards);
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(btn);
pane.add(btnPanel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
Alternatively, you can switch to a specific panel by calling cl.show(cards, "Panel X") where X is the number of the panel. This is because the swing argument is the name I assigned to each "card" and the show method recalls panels added to CardLayout by name. For your example, each button should have a listener that uses this method to "show" its assigned panel.
Hey everyone, I want to combine my classes and get it in
only one frame. Now I have 2 classes and I don't know how to group them.
The JSlider.
public class JSliderExample extends JFrame {
JSlider jsHorizontal;
JTextField jtf1;
public JSliderExample() {
jsHorizontal = new JSlider(JSlider.HORIZONTAL, 0, 100, 50);
jtf1 = new JTextField(15);
jtf1.setEditable(false);
jtf1.setText("Horizontal value is " + jsHorizontal.getValue());
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
panel.add(jsHorizontal);
panel.setBackground(Color.WHITE);
panel.add(jtf1);
panel.setBackground(Color.WHITE);
getContentPane().add(panel, BorderLayout.CENTER);
getContentPane().add(panel, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(300, 400, 400, 300);
setVisible(true);
setBackground(Color.WHITE);
}
class JSliderHandler implements ChangeListener {
public void stateChanged(ChangeEvent ce) {
jtf1.setText("value is " + jsHorizontal.getValue());
}
}
And there are my buttons
.
public void createGUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
JButton button2 = new JButton("PLAY");
button2.setActionCommand("Button PLAY was pressed!");
panel.add(button2);
textField = new JTextField();
textField.setColumns(23);
panel.add(textField);
ActionListener actionListener = new TestActionListener();
button1.addActionListener(actionListener);
button2.addActionListener(actionListener);
button3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textField.setText(e.getActionCommand());
}
});
getContentPane().add(panel);
setPreferredSize(new Dimension(320, 100));
}
public class TestActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
textField.setText(e.getActionCommand());
}
}
In the end of programm I see 2 frames that consist of 2 classes.
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
TestFrame frame = new TestFrame();
frame.pack();
JSliderExample frame1 = new JSliderExample();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
If you don't want to see 2 JFrames, then don't create 2 JFrames. Why not make JPanels with all your classes above and not JFrames, and then in your main method, add your JPanels to the JFrame created within main. Simple.
So for example, instead of having JSliderExample extend JFrame, change it's name to SliderPanel and have it extend JPanel, and likewise with your JButton program. Then your main method could look something like:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// your JSlider example class **that extends JPanel**
SliderPanel sliderPanel = new SliderPanel();
// your JButton example class **that extends JPanel**
ButtonPanel buttonPanel = new ButtonPanel():
JFrame frame = new JFrame("My GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(sliderPanel, BorderLayout.PAGE_START);
frame.add(buttonPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null); // center GUI if you want
frame.setVisible(true);
}
});
}
I create two jbuttons in one panel(can be Box).i create same panel dynamically several times in same frame.so if two panels created dynamically those button make with same variable name.But i want to identify buttons one by one for put actions.how to identify dynamically created buttons one by one?
button creating code
public class Jscrollpanetest extends JFrame {
JScrollPane scrollPane;
Box box;
private static int panelCount = 0;
public Jscrollpanetest() {
setPreferredSize(new Dimension(200, 400));
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.getVerticalScrollBar().setUnitIncrement(15);
box = Box.createVerticalBox();
scrollPane.getViewport().add(box);
this.add(scrollPane);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
Timer t = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
box.add(new TestPanel(), box.size());
scrollPane.validate();
}
});
t.setRepeats(true);
t.start();
}
public class TestPanel extends JPanel {
int myId = panelCount++;
public TestPanel() {
this.setLayout(new GridBagLayout());
this.setBorder(BorderFactory.createBevelBorder(1));
JButton up = new JButton("^");
JLabel rate = new JLabel("1");
JButton down = new JButton("^");
JLabel label = new JLabel("" + myId);
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
this.setMaximumSize(new Dimension(1000, 200));
this.setPreferredSize(new Dimension(1000, 100));
this.add(label);
this.add(up);
this.add(rate);
this.add(down);
}
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Jscrollpanetest testScrollPane = new Jscrollpanetest();
}
});
}
}
If use and dynamic created ActionListener there will be no problem. So each button will have its own ActionListener.
If using a common ActionListener must add tags to each button as extend JButton.
im trying to to use cards layout, and i have 2 buttons at the the top that supoose to change the card but for some reason it wont work, the next method works but the show or first\last doesnt, ofcourse i cant use next, cause i want a specific card for every button, here is my code:
cards = new CardLayout();
cardPanel = new JPanel();
cardPanel.setLayout(cards);
cards.show(cardPanel, "gapas");
JPanel firstCard = new JPanel();
firstCard.setBackground(Color.WHITE);;
JPanel secondCard = new JPanel();
secondCard.setBackground(Color.blue);
cardPanel.add(firstCard, "kalam");
cardPanel.add(secondCard, "gapan");
guiFrame.add(tabsPanel,BorderLayout.NORTH);
guiFrame.add(cardPanel,BorderLayout.CENTER);
guiFrame.setVisible(true);
}
ActionListener action = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().matches("kalam")){
cards.show(cardPanel,"kalam");
System.out.println("kalam");
}
else{
cards.show(cardPanel, "gapas");
System.out.println("gapas");
}
}
};
I think you want something like this.
public class TestCard extends JFrame implements ActionListener {
CardLayout cards;
JPanel cardPanel, tabsPanel;
JButton b1, b2;
public TestCard() {
b1= new JButton("kalam");
b2= new JButton("gapas");
tabsPanel = new JPanel();
cards = new CardLayout();
cardPanel = new JPanel();
cardPanel.setLayout(cards);
JPanel firstCard = new JPanel();
firstCard.setBackground(Color.WHITE);
JPanel secondCard = new JPanel();
secondCard.setBackground(Color.blue);
cardPanel.add(firstCard, "kalam");
cardPanel.add(secondCard, "gapas");
tabsPanel.add(b1);
tabsPanel.add(b2);
add(tabsPanel, BorderLayout.NORTH);
add(cardPanel, BorderLayout.CENTER);
b1.addActionListener(this);
b2.addActionListener(this);
setSize(800, 600);
cards.show(cardPanel, "gapas");
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().matches("kalam")) {
cards.show(cardPanel, "kalam");
System.out.println("kalam");
} else {
cards.show(cardPanel, "gapas");
System.out.println("gapas");
}
}
public static void main(String[] args) {
new TestCard();
}
}
Documentation states:
show (Container parent, String name) Flips to the component that was added to this layout with the specified name, using the addLayoutComponent method.
You add two items:
kalam
gapan
but you try to show: gapas.
Additionally I would add first and then try 2 show.
I would like to know what code to insert and where to add a simple label that can just say the word "Label" and a input text box that I can enter a number.
public CalculateDimensions() {
JTabbedPane Tab = new JTabbedPane();
JPanel jplInnerPanel1 = createInnerPanel("First Tab");
Tab.addTab("One", jplInnerPanel1);
Tab.setSelectedIndex(0);
JPanel jplInnerPanel2 = createInnerPanel("Second Tab");
Tab.addTab("Two", jplInnerPanel2);
JPanel jplInnerPanel3 = createInnerPanel("Third Tab");
Tab.addTab("Three", jplInnerPanel3);
JPanel jplInnerPanel4 = createInnerPanel("Fourth Tab");
Tab.addTab("Four", jplInnerPanel4);
JPanel jplInnerPanel5 = createInnerPanel("Fifth Tab");
Tab.addTab("Five", jplInnerPanel5);
setLayout(new GridLayout(1, 1));
add(Tab);
}
protected JPanel createInnerPanel(String text) {
JPanel jplPanel = new JPanel();
JLabel jlbDisplay = new JLabel(text);
jlbDisplay.setHorizontalAlignment(JLabel.CENTER);
jplPanel.setLayout(new GridLayout(1, 1));
jplPanel.add(jlbDisplay);
return jplPanel;
}
public static void main(String[] args) {
JFrame frame = new JFrame("Calculations");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.getContentPane().add(new CalculateDimensions(),
BorderLayout.CENTER);
frame.setSize(400, 400);
frame.setVisible(true);
}
}
The Swing tutorial is an excellent resource for building GUIs.
Take a look at the visual guide and click on the components you want for detailed how to guides for creating text boxes, and other items.
http://download.oracle.com/javase/tutorial/ui/features/components.html
in your public static void main() method you should not instantiate JFrame frame = new JFrame("Calculations");
This is where you are going wrong!
That line should read:
CalculateDimensions frame = new CalculateDimensions("Calculations");
You will also need to change the line says
public class CalculateDimensions {
(it's near the top) says
public class CalculateDimensions extends JFrame {
then inside the method called public class CalculateDimensions { you need to add a line after JPanel jplInnerPanel1 = createInnerPanel("First Tab"); which says
jplInnerPanel1.add(new JLabel("Label");