I'm having a problem trying to change JPanels by using buttons. I have a JFrame with 2 panels, 1 of them is for the buttons, which i want them to always be showed. The other one is the one that i will be switching everytime i press one ot the buttons of the other panel. The problem is that everytime i press them nothing really ever displays, i keep my buttons but the other panel that i call does not appear.
Code for one of the buttons is as follows
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
ReparacaoPanel r = new ReparacaoPanel(this, this.jPanel1);
this.getContentPane().remove(this.jPanel1);
this.getContentPane().add(r);
//this.setContentPane(r);
this.visiblePanel.setVisible(false);
this.visiblePanel = r;
this.pack();
this.setVisible(true);
r.setLocation(200, 200);
this.getContentPane().revalidate();
this.repaint();
}
If i try to use "this.setContentPane(r);" (it sets the frame to only show the panel) the panel shows. But when i try to call it as i'm trying to do in the code above nothing is showed apart from the panel that has the buttons.
I have no idea what i'm doing wrong, it does not seem to be a problem with the JPanel that i'm trying to call as it shows if used alone.
Anyone can help me out?
Consider this working example for switching manually between panels. Which produces this output.
.........
Some tiny NumberPanel
Every new instance shows another number in the center.
import javax.swing.JPanel;
public class NumberPanel extends JPanel {
private static int counter = 0;
public NumberPanel() {
setLayout(new BorderLayout(0, 0));
JLabel lblNewLabel = new JLabel("" + counter++);
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
add(lblNewLabel);
}
}
Setting up a frame
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.SOUTH);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.getContentPane().remove(numberPanel);
numberPanel = new NumberPanel();
frame.getContentPane().add(numberPanel, BorderLayout.CENTER);
frame.pack();
}
});
panel.add(btnNewButton);
numberPanel = new NumberPanel();
frame.getContentPane().add(numberPanel, BorderLayout.CENTER);
frame.pack();
}
Testprogram
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestPanelSwitch {
private JFrame frame;
private NumberPanel numberPanel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestPanelSwitch window = new TestPanelSwitch();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public TestPanelSwitch() {
initialize();
}
private void initialize() {
// see above
}
}
Back to the Question
I think you only need to pack your frame, like in the anonymous ActionListener.
frame.getContentPane().remove(numberPanel);
numberPanel = new NumberPanel();
frame.getContentPane().add(numberPanel, BorderLayout.CENTER);
frame.pack();
EDIT
As leonidas mentioned it is also possible to revalidate the frame. This requires only to replace the upper call to pack by theese.
frame.invalidate();
frame.validate();
Related
I'm having some trouble with a simple application I'm creating to count the number of clicks per second. The code is as follows:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.Border;
public class CPSFrame implements ActionListener {
JFrame frame;
JPanel borderPanel, settings;
JButton click;
String[] timesList = {"5","10","15","20","25","30"};
JComboBox times;
JTextField showCps;
public CPSFrame() {
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
CPSFrame c = new CPSFrame();
c.drawGui();
}
});
}
public void drawGui() {
frame = new JFrame();
borderPanel = new JPanel();
settings = new JPanel();
click = new JButton("Click me!");
times = new JComboBox(timesList);
showCps = new JTextField();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("CPS Calculator");
{
borderPanel.setLayout(new BorderLayout(0, 0));
frame.add(borderPanel);
{
borderPanel.add(click);
settings.setLayout(new GridLayout(1, 0, 0, 0));
borderPanel.add(settings, BorderLayout.SOUTH);
{
settings.add(times);
settings.add(showCps);
}
}
}
frame.pack();
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent evt) {
}
}
For some reason, if I resize the JFrame and press click, both times and showCPS disappear. I have a feeling it has something to do with the way I have the BorderLayout set up, but I'm not sure.
Here is a video of what is happening.
edit: updated the code and added a video of what is happening.
Works fine for me (Java 1.6, Win) and nothing disappears after resize and click. Try to specify the location of c.click explicitly c.borderPanel.add(c.click,BorderLayout.CENTER);
Maybe there are Java implementations (platforms, versions) where BorderLayout don't like unspecified location.
I need help with this code, I'm trying to make a simple cookie clicker type game, I have most the code done, but for some reason, when I try to add the JLabel to the frame, it creates an error, I was hoping one of you guys could help me out, I'm fairly new to Java, thanks for the help!
//Variables
static int clicked = 0;
private FlowLayout layout;
private Container container;
public static void main(String [] args) {
//Declaring the buttons, panels, etc...
JButton button = new JButton("Click");
JPanel panel = new JPanel();
panel.add(button);
final JFrame frame = new JFrame("Button Pressed");
frame.setSize(400, 200);
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.add(panel);
//Action Listener Code
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Execute when button is pressed
clicked++;
System.out.println("Button pressed " + clicked + " times!");
}
}
}
You can add an JLabel then update its text when button is clicked.
Note: call JFrame.setVisible(true) in the end when all the component is added.
sample code:
// Declaring the buttons, panels, etc...
JButton button = new JButton("Click");
final JLabel label = new JLabel();
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
clicked++;
label.setText("Button pressed " + clicked + " times!");
}
});
JPanel panel = new JPanel();
panel.add(button);
panel.add(label);
final JFrame frame = new JFrame("Button Pressed");
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
Find more examples here and here
The basic principle is relatively easy. In order to add something to something else, you first need to have access (or a reference to) the thing you want to add to.
While there are a number of ways you might achieve this, the simplest might be to use an instance/class field. This field would then be accessible from anywhere within the class, for example
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ClickTest {
public static void main(String[] args) {
new ClickTest();
}
private JPanel panel;
public ClickTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
//Declaring the buttons, panels, etc...
JButton button = new JButton("Click");
panel = new JPanel();
panel.add(button);
final JFrame frame = new JFrame("Button Pressed");
frame.setSize(400, 200);
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.add(panel);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
panel.add(new JLabel("You clicked me"));
panel.revalidate();
}
});
}
});
}
}
Take a look at Creating a GUI With JFC/Swing and Understanding Class Members for more details
I am using a JDialog with 2 JTextfields and JButtons in it. When Jdialog opens for the first time I have a cursor on my first textfield. Now if I click somewhere outside Jdialog and then try clicking back the JDialog, I dont see the cursor on any of the textfields and I am unable to write or edit anything on the textfields.
I have set the modal to be true. So even If I click anywhere else my dialog still appears on the screen but gets deactivated.
This issue is only with linux server and not on windows. Windows works perfectly.
Adding a sample code here to get some picture of the issue.
Here TestClass is extending JFrame.
public TestClass(){
setSize(new Dimension(600,500));
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
myPanel = new JPanel();
JButton openDialog = new JButton("Click here");
openDialog.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
dialog = new JDialog(myFrame,true);
dialog.setSize(new Dimension(400,400));
JTextField myField = new JTextField(10);
JPanel innerPanel = new JPanel();
innerPanel.add(myField);
dialog.add(innerPanel);
dialog.setVisible(true);
//add(dialog);
}
});
myPanel.add(openDialog);
add(myPanel);
}
Your incomplete example could not be tested. The example below exhibits the expected behavior under Java 6 on both Mac OS X and Ubuntu 12. In particular, the text field remains functional after switching back from another program.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* #see http://stackoverflow.com/a/15576897/230513
*/
public class TestClass extends JFrame {
private static JFrame myFrame;
public TestClass() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
JButton openDialog = new JButton("Click here");
JPanel myPanel = new JPanel();
myPanel.add(new JButton(new AbstractAction("Click here") {
#Override
public void actionPerformed(ActionEvent e) {
JDialog dialog = new JDialog(myFrame, true);
JTextField myField = new JTextField(10);
JPanel innerPanel = new JPanel();
innerPanel.add(myField);
dialog.add(innerPanel);
dialog.pack();
dialog.setSize(new Dimension(160, 120));
dialog.setLocationRelativeTo(myFrame);
dialog.setVisible(true);
}
}));
add(myPanel);
pack();
setSize(new Dimension(320, 240));
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myFrame = new TestClass();
}
});
}
}
I'm trying to create a small GUI, it has 2 JButtons, and 2 JPanels with some drawing animation on each of them. By default it must show first JPanel, and by clicking on second JButton I want to see my second JPanel. So : I create JFrame, Panel1 and Panel2, where I have drawn my animations, create Button1 and Button2 and adding to them ActionListeners. I have also MainPanel which has in a fields variable i. By changing this "i" my constructor adds to MainPanel either Panel1 (default) or Panel2 (by clicking on JButton2 I change i). Than I add this MainPanel to my frame. So my question : in the class MainPanel I have refreshMe method, what should I write there to make my GUI working properly? Thanks. Here is my code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GuiTest {
public static void main(String[] args) {
JFrame f = new JFrame();
MainPanel myPanel = new MainPanel();
f.add(myPanel);
Button1 button1 = new Button1();
Button2 button2 = new Button2();
myPanel.add(button1);
myPanel.add(button2);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
class MainPanel extends JPanel {
Panel1 p1 = new Panel1();
Panel2 p2 = new Panel2();
public int i = 1; //this is being changed later by clicking JButton
// I use this setter later in actionPerformed in order to change i
public void setI(int i) {
this.i = i;
}
MainPanel() {
if (i == 1) {
this.add(p1);
}
if (i == 2) {
this.add(p2);
}
}
public void refreshMe() {
// Need some help here:
// I don't know what should I write, how to make a repaint of myPanel?
System.out.println("just test, if the method refreshMe working by clicking some button");
}
}
class Panel1 extends JPanel {
public Panel1() {
this.setBackground(Color.BLUE);
// a lot of drawing stuff going on here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
class Panel2 extends JPanel {
public Panel2() {
this.setBackground(Color.GREEN);
// a lot of drawing stuff going on here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
class Button1 extends JButton {
MainPanel someObj1 = new MainPanel();
Button1() {
setText("Show Annimation A");
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
someObj1.setI(1);
System.out.println("The variable i is now: " + someObj1.i);
someObj1.refreshMe();
}
});
}
}
class Button2 extends JButton {
MainPanel someObj2 = new MainPanel();
Button2() {
setText("Show Annimation B");
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
someObj2.setI(2);
System.out.println("The variable i is now: " + someObj2.i);
someObj2.refreshMe();
}
});
}
}
In order to reflect changes after adding/removing or resizing a component that is on a visible container call revalidate() and repaint() on the containers instance after adding/removing or resizing the component.
Though this will not work in your code the main reason being inside JButton classes you recreate a new instance of MainPanel when in fact the 2 JButtons should share the single instance which is being used (you could pass MainPanel instance to the JButtons constructors, but you shouldn't really be extending a JButton unless adding custom functionality):
class Button2 extends JButton {
MainPanel someObj2 = new MainPanel();//you create an instance of MainPanel which isnt even showing and than do changes on that, this way you will never see any of the changes
Button2() {
}
}
A few other suggestions on your code:
Dont extend JButton class unnecessarily, simply create an instance of JButton like you did with JFrame and call methods on JButton instance.
Dont forget to create/manipulate Swing components on Event Dispatch Thread, via SwingUtilities.invokeLater(..) block, read here for more.
Here is your code fixed (above suggestions ect implemented):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
final MainPanel myPanel = new MainPanel();
f.add(myPanel);
JButton button1 = new JButton("Show Animation A");
JButton button2 = new JButton("Show Animation B");
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myPanel.setI(1);
System.out.println("The variable i is now: " + myPanel.i);
myPanel.refreshMe();
}
});
button2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myPanel.setI(2);
System.out.println("The variable i is now: " + myPanel.i);
myPanel.refreshMe();
}
});
myPanel.add(button1);
myPanel.add(button2);
myPanel.checkPanel();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
});
}
}
class MainPanel extends JPanel {
Panel1 p1 = new Panel1();
Panel2 p2 = new Panel2();
public int i = 1; //this is being changed later by clicking JButton
// I use this setter later in actionPerformed in order to change i
public void setI(int i) {
this.i = i;
}
public void refreshMe() {
checkPanel();
revalidate();
repaint();
// Need some help here:
// I don't know what should I write, how to make a repaint of myPanel?
System.out.println("just test, if the method refreshMe working by clicking some button");
}
public void checkPanel() {
if (i == 1) {
this.add(p1);
this.remove(p2);//or it will remain there as this is default flowlayout
} else if (i == 2) {
this.add(p2);
this.remove(p1);
}
}
}
class Panel1 extends JPanel {
public Panel1() {
this.setBackground(Color.BLUE);
// a lot of drawing stuff going on here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
class Panel2 extends JPanel {
public Panel2() {
this.setBackground(Color.GREEN);
// a lot of drawing stuff going on here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
However Id suggest something simpler, fortunately you have 2 choices:
1) Use CardLayout which will allow you to flip between multiple components on a single JFrame/container.
Here is an example I made:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
private final static String PANEL1 = "panel 1";
private final static String PANEL2 = "panel 2";
public Test() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void initComponents() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel1 = new JPanel();
panel1.add(new JLabel("Panel 1"));
JPanel panel2 = new JPanel();
panel2.add(new JLabel("Panel 2"));
//Create the panel that contains the "cards".
final JPanel cards = new JPanel(new CardLayout());
cards.add(panel1, PANEL1);
cards.add(panel2, PANEL2);
//create button to allow chnage to next card
JButton buttonNext = new JButton(">");
buttonNext.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
CardLayout cl = (CardLayout) (cards.getLayout());//get cards
cl.next(cards);
}
});
//create button to allow chnage to previous card
JButton buttonPrev = new JButton("<");
buttonPrev.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
CardLayout cl = (CardLayout) (cards.getLayout());//get cards
cl.previous(cards);
}
});
//create panel to hold buttons which will allow switching between cards
JPanel buttonPanel = new JPanel();
buttonPanel.add(buttonPrev);
buttonPanel.add(buttonNext);
frame.add(cards);
frame.add(buttonPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
}
2) Use removeAll() technique i.e call frame.getContentPane().removeAll() which will remove all components currently on JFrame and than add the new content and call revalidate() and repaint() (also might want to add pack() in there) on JFrame instance to reflect changes. Though Id recommend CardLayout.
I think you can just use CardLayout to implement your function. Please refer to here
What I am looking to do is a similar principle to adding attachments to emails, you can click a button and a new browse box would open increasing the number of separate attachments you can have.
I'm fairly new so if someone could point me towards an example?
Sample code to add Buttons on the fly dynamically.
panel.add(new JButton("Button"));
validate();
Full code:
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;
import java.awt.BorderLayout;
public class AddComponentOnJFrameAtRuntime extends JFrame implements ActionListener {
JPanel panel;
public AddComponentOnJFrameAtRuntime() {
super("Add component on JFrame at runtime");
setLayout(new BorderLayout());
this.panel = new JPanel();
this.panel.setLayout(new FlowLayout());
add(panel, BorderLayout.CENTER);
JButton button = new JButton("CLICK HERE");
add(button, BorderLayout.SOUTH);
button.addActionListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
setVisible(true);
}
public void actionPerformed(ActionEvent evt) {
this.panel.add(new JButton("Button"));
this.panel.revalidate();
validate();
}
public static void main(String[] args) {
AddComponentOnJFrameAtRuntime acojfar = new AddComponentOnJFrameAtRuntime();
}
}
Resource
public static void main(String[] args) {
final JFrame frame = new JFrame("Test");
frame.setLayout(new GridLayout(0, 1));
frame.add(new JButton(new AbstractAction("Click to add") {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.add(new JLabel("Bla"));
frame.validate();
frame.repaint();
}
});
}
}));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setVisible(true);
}
Component was not visible until setSize() was called:
component.setSize(100,200);
jPanel.add(component);
jPanel.revalidate();
jPanel.repaint();
panel.add(button);
panel.revalidate();
panel.repaint();
Java : Dynamically add swing components
for Example : count=3
//Java Swing: Add Component above method
public void dya_addcomp(int count)
{
//Dynamicaly Delete Image_icon
BufferedImage Drop_Tablefield = null;
try {
Drop_Tablefield = ImageIO.read(this.getClass().getResource("/images/drop.png"));
} catch (IOException ex) {
msg(" Error: drop and edit icon on Table, "+ex);
}
//count Items: 3 times for loop executed..
for(int i=0;i<count;i++)
{
//cnt++;
//lblcount.setText("Count : "+cnt);
JTextField txtcolnm=new JTextField("",20);
JComboBox cmbtype=new JComboBox();
JTextField txtcolsize=new JTextField("",20);
JButton Drop_Table_Field = new JButton(new ImageIcon(Drop_Tablefield));
cmbtype.addItem("INTEGER"); cmbtype.addItem("FLOAT");
cmbtype.addItem("STRING"); cmbtype.addItem("BOOLEAN");
colnamepanel.add(txtcolnm); colnamepanel.add(cmbtype);
colnamepanel.add(txtcolsize); colnamepanel.add(Drop_Table_Field);
colnamepanel.setAutoscrolls(true);
//refresh panel
colnamepanel.revalidate();
colnamepanel.repaint();
//set the layout on Jpanel
colnamepanel.setLayout(new FlowLayout(FlowLayout.LEFT,5,0));
}//end for loop
}//end method