I've hit a problem in getting a JPanel to update.
My simple program uses a custom JPanel which displays a label and a textfield. A Jbutton on the main panel is used to replace the JPanel with a new JPanel. The initial panel shows up fine but when the button is pressed the panel is not updated with a new MyPanel. I can tell that a new object is being created as count is being incremented.
public class SwingTest extends JFrame{
private JPanel mp;
private JPanel vp;
private JButton button;
public static void main(String[] args) {
SwingTest st = new SwingTest();
}
public SwingTest() {
vp = new MyPanel();
mp = new JPanel(new BorderLayout());
mp.add(vp, BorderLayout.CENTER);
button = new JButton("Change");
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
vp = new MyPanel();
vp.revalidate();
}
});
mp.add(button, BorderLayout.SOUTH);
this.add(mp);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
setSize(250, 150);
pack();
setVisible(true);
}
}
and my custom panel....
public class MyPanel extends JPanel{
private JLabel label;
private JTextField tf;
static int count = 0;
public MyPanel(){
count++;
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
setPreferredSize(new Dimension(400, 200));
c.gridx = 0;
c.gridy = 0;
label = new JLabel(String.valueOf(count));
tf = new JTextField(10);
add(label,c);
c.gridx = 1;
add(tf, c);
}
}
You state:
A Jbutton on the main panel is used to replace the JPanel with a new JPanel.
And yet this code:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
vp = new MyPanel();
vp.revalidate();
}
});
and yet this code does not do this at all. All it does is change the JPanel referenced by the vp variable, but has absolutely no effect on the JPanel that is being displayed by the GUI, which suggests that you're confusing reference variable with reference or object. To change the JPanel that is displayed, you must do exactly this: add the new JPanel into the container JPanel into the BorderLayout.CENTER (default) position, then call revalidate() and repaint() on the container.
e.g.,
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
// vp = new MyPanel();
// vp.revalidate();
mp.remove(vp); // remove the original MyPanel from the GUI
vp = new MyPanel(); // create a new one
mp.add(vp, BorderLayout.CENTER); // add it to the container
// ask the container to layout and display the new component
mp.revalidate();
mp.repaint();
}
});
Or better still -- use a CardLayout to swap views.
Or better still -- simply clear the value held by the JTextField.
For more on the distinction between reference variable and object, please check out Jon Skeet's answer to this question: What is the difference between a variable, object, and reference?
Related
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.
In previos my questions I asked similar questions to this. But in my previous projects I used GUI builder, so now I would like to add JTextField to the Panel dynamically without Builder. I don't why but for some reason I cannot execute this code:
public class Reference {
JFrame frame = new JFrame();
JPanel MainPanel = new JPanel();
MainPanel main = new MainPanel();
JPanel SubPanel = new JPanel();
JButton addButton = new JButton();
JButton saveButton = new JButton();
private List<JTextField> listTf = new ArrayList<JTextField>();
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new Reference();
}
public Reference() {
frame.add(main);
frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(addButton, BorderLayout.EAST);
frame.add(saveButton, BorderLayout.WEST);
frame.pack();
frame.setSize(500, 300);
frame.setVisible(true);
main.setLayout(new BorderLayout());
main.setBackground(Color.green);
main.add(SubPanel);
SubPanel.setBackground(Color.yellow);
addButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt) {
main.add(new SubPanel());
main.revalidate();
}
});
saveButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt) {
for (int i = 0; i < main.getComponentCount();) {
SubPanel panel = (SubPanel)main.getComponent(i);
JTextField firstName = panel.getFirstName();
String text = firstName.getText();
System.out.println( text );
}}
});
}
private class SubPanel extends JPanel {
JTextField firstName = new JTextField(15);
public SubPanel() {
this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
this.add(firstName);
listTf.add(firstName);
}
public JTextField getFirstName()
{
return firstName;
}
}
public class MainPanel extends JPanel
{
List<SubPanel> subPanels = new ArrayList<SubPanel>();
public MainPanel()
{
}
public void addSubPanel()
{
SubPanel panel = new SubPanel();
add(panel);
subPanels.add(panel);
}
public SubPanel getSubPanel(int index)
{
return subPanels.get(index);
}
}
}
And by saveButton trying to get value of JTextField, but without success. In output I can see just JFrame with 2 Buttons, but ActionListener of addButton and saveButton is not active. I cannot understand where is wrong.
Any help would be much appreciated.
In Swing, the order you do some things is very important, for example...
frame.add(main);
frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(addButton, BorderLayout.EAST);
frame.add(saveButton, BorderLayout.WEST);
frame.pack();
frame.setSize(500, 300);
frame.setVisible(true);
You add main to your frame
You set the frames layout (!?)
You add your buttons
You pack the frame
You set it's size (!?)
You make it visible
The problem here is step #2. If, instead, we simply remove step #2 (step #4 and #5 aren't great either), you will find that your window now contains main...
frame.add(main);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(addButton, BorderLayout.EAST);
frame.add(saveButton, BorderLayout.WEST);
frame.pack();
frame.setVisible(true);
This...
for (int i = 0; i < main.getComponentCount();) {
SubPanel panel = (SubPanel) main.getComponent(i);
a bad idea of three reasons;
Your loop will never advance (i will always be 0)
You are blindly casting the contents of main without actually knowing what's on it
MainPanel already has a List of SubPanels...
You need to make sure that you are adding SubPanels via the addSubPanel method (and this should probably return an instance of the SubPanel) and provide a means by which you can access this List, maybe via a getter of some sort. Although, I'd be more interested in their values (ie the text field text) rather then the SubPanel itself ;)
My software layout is kinda wizard-base. So the base panel is divided into two JPanels. One left panel which never changes. And one right panel that works with CardLayout. It has many sub-panels and show each one of them by a method.
I can easily go from one inner panel to another one. But I want to have a button in left panel and change panels of the right side.
Here is a sample code which you can run it:
BASE:
public class Base {
JFrame frame = new JFrame("Panel");
BorderLayout bl = new BorderLayout();
public Base(){
frame.setLayout(bl);
frame.setSize(800, 600);
frame.add(new LeftBar(), BorderLayout.WEST);
frame.add(new MainPanel(), BorderLayout.CENTER);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
// TODO code application logic here
new Base();
}
}
Left side
public class LeftBar extends JPanel{
JButton button;
MainPanel mainPanel = new MainPanel();
public LeftBar(){
setPreferredSize(new Dimension(200, 40));
setLayout(new BorderLayout());
setBackground(Color.black);
button = new JButton("Show Second Page");
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
mainPanel.showPanel("secondPage");
}
});
add(button, BorderLayout.NORTH);
}
}
Right Side
public class MainPanel extends JPanel {
private CardLayout cl = new CardLayout();
private JPanel panelHolder = new JPanel(cl);
public MainPanel(){
FirstPage firstPage = new FirstPage(this);
SecondPage secondPage = new SecondPage(this);
setLayout(new GridLayout(0,1));
panelHolder.add(firstPage, "firstPage");
panelHolder.add(secondPage, "secondPage");
cl.show(panelHolder, "firstPage");
add(panelHolder);
}
public void showPanel(String panelIdentifier){
cl.show(panelHolder, panelIdentifier);
}
}
Inner panels for right side:
public class FirstPage extends JPanel {
MainPanel mainPanel;
JButton button;
public FirstPage(MainPanel mainPanel) {
this.mainPanel = mainPanel;
setBackground(Color.GRAY);
button = new JButton("Show page");
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
mainPanel.showPanel("secondPage");
}
});
add(button);
}
}
public class SecondPage extends JPanel{
MainPanel mainPanel;
JButton button;
public SecondPage(MainPanel mainPanel){
this.mainPanel = mainPanel;
setBackground(Color.white);
add(new JLabel("This is second page"));
}
}
And this is a picture to give you the idea:
As I explained, I can travel "from first" page to "second page" by using this method: mainPanel.showPanel("secondPage"); or mainPanel.showPanel("firstPage");.
But I also have a JButton in the left bar, which I call the same method to show the second panel of the CardLayout. But it does not work. It doesnt give any error though.
Any idea how to change these CardLayout panels from outside of panels?
The problem is that LeftBar has mainPanel member that is initialized to a new instance of MainPanel. So you have two instances of MainPanel, one allocated in Base and added to the frame, the other one allocated in LeftBar.
So LeftBar executes mainPanel.showPanel("secondPage"); on a second instance of MainPanel which is not even a part of a visual hierarchy. To fix this just pass an existing instance of MainPanel to the constructor of LeftBar. You already do this in FirstPage and SecondPage.
For some reason I can't get the BorderLayout to set the way it's supposed to. Just would like to know where I'm going wrong.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ColorFactory extends JFrame
{
final int width = 500;
final int height = 300;
private JPanel buttonPanel;
private JPanel radioButtonPanel;
private JLabel msgChangeColor;
public ColorFactory()
{
setTitle("Color Factory");
setSize(width, height);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
createTopPanel();
add(buttonPanel, BorderLayout.NORTH);
createBottomPanel();
add(radioButtonPanel, BorderLayout.SOUTH);
msgChangeColor = new JLabel("Top buttons change the panel color and bottom radio buttons change the text color.");
add(msgChangeColor, BorderLayout.CENTER);
pack();
}
private void createTopPanel()
{
buttonPanel = new JPanel();
setLayout(new FlowLayout());
JButton redButton = new JButton("Red");
redButton.setBackground(Color.RED);
redButton.addActionListener(new ButtonListener());
redButton.setActionCommand("R");
JButton orangeButton = new JButton("Orange");
orangeButton.setBackground(Color.ORANGE);
orangeButton.addActionListener(new ButtonListener());
orangeButton.setActionCommand("O");
JButton yellowButton = new JButton("Yellow");
yellowButton.setBackground(Color.YELLOW);
yellowButton.addActionListener(new ButtonListener());
yellowButton.setActionCommand("Y");
buttonPanel.add(redButton);
buttonPanel.add(orangeButton);
buttonPanel.add(yellowButton);
}
private void createBottomPanel()
{
radioButtonPanel = new JPanel();
setLayout(new FlowLayout());
JRadioButton greenRadioButton = new JRadioButton("Green");
greenRadioButton.setBackground(Color.GREEN);
greenRadioButton.addActionListener(new RadioButtonListener());
greenRadioButton.setActionCommand("G");
JButton blueRadioButton = new JButton("Blue");
blueRadioButton.setBackground(Color.BLUE);
blueRadioButton.addActionListener(new RadioButtonListener());
blueRadioButton.setActionCommand("B");
JButton cyanRadioButton = new JButton("Cyan");
cyanRadioButton.setBackground(Color.CYAN);
cyanRadioButton.addActionListener(new RadioButtonListener());
cyanRadioButton.setActionCommand("C");
radioButtonPanel.add(greenRadioButton);
radioButtonPanel.add(blueRadioButton);
radioButtonPanel.add(cyanRadioButton);
}
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String actionColor = e.getActionCommand();
if(actionColor.equals("R"))
{
buttonPanel.setBackground(Color.RED);
radioButtonPanel.setBackground(Color.RED);
}
if(actionColor.equals("O"))
{
buttonPanel.setBackground(Color.ORANGE);
radioButtonPanel.setBackground(Color.ORANGE);
}
if(actionColor.equals("Y"))
{
buttonPanel.setBackground(Color.YELLOW);
radioButtonPanel.setBackground(Color.YELLOW);
}
}
}
private class RadioButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String actionTextColor = e.getActionCommand();
if(actionTextColor.equals("G"))
{
msgChangeColor.setForeground(Color.GREEN);
}
if(actionTextColor.equals("B"))
{
msgChangeColor.setForeground(Color.BLUE);
}
if(actionTextColor.equals("C"))
{
msgChangeColor.setForeground(Color.CYAN);
}
}
}
public static void main(String[] args)
{
ColorFactory run = new ColorFactory();
run.setVisible(true);
}
}
The problem is you are changing the layout manager for the frame when you create your top and bottom panels...
private void createTopPanel() {
buttonPanel = new JPanel();
setLayout(new FlowLayout()); // <--- This is call setLayout on the frame
This is why it's dangerous to...
Extend from something like JFrame directly...
Dynamically build components
It's all to easy to lose context and start effecting components you didn't actually want to...
Another problem (besides the one posted by MadProgrammer) is that you add your components to the JFrame itself.
You should add content to the content pane of the frame which you can get by calling JFrame.getContentPane().
Example:
JFrame f = new JFrame("Test");
Container c = f.getContentPane();
c.add(new JButton("In Center"), BorderLayout.CENTER);
c.add(new JButton("At the Bottom"), BorderLayout.SOUTH);
c.add(new JButton("At the Top"), BorderLayout.NORTH);
c.add(new JButton("On the Left"), BorderLayout.WEST);
c.add(new JButton("On the Right"), BorderLayout.EAST);
You can set/change the content panel by calling JFrame.setContentPane(). The default content panel already has BorderLayout so you don't even need to change it nor to set a new panel.
I am trying to get a JLabel to appear when a JButton is clicked. I have added an action listener and added the component to the layout. I am using the label1.setVisible(true) when the JButton is clicked in actionPerformed. I still can't get it work. Can some look at my code?
public class LearnAppMain extends JFrame implements ActionListener {
// Define variables
public JButton button1;
public JLabel label1;
public JTextField field1;
private Image image1;
private String apple = "apple.jpg";
public LearnAppMain() {
ImageIcon image1 = new ImageIcon(this.getClass().getResource(apple));
JLabel label1 = new JLabel(image1);
button1 = new JButton("A");
button1.addActionListener(this);
field1 = new JTextField(10);
// Create layout
setLayout(new FlowLayout());
// create Container
final Container cn = getContentPane();
cn.add(button1);
cn.add(field1);
cn.add(label1);
// setLayout(new FlowLayout());
setSize(250, 250);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (e.getSource() == button1) {
label1.setVisible(true);
field1.setText("Apple");
}
}
}
I have my main method in another class file. The error I get leads me to the label1.setVisible(true);
Every question I've seen they say to do this, but I'm wondering if there is something else that needs to be added.
There were a couple of issues here:
Your label1 was hidden by doing JLabel label in the constructor. You basically declared another variable called label1 in your constructor that hid the one in the class itself.
Your label was visible on the startup - I used label.setVisible(false) for the test, but you might want otherwise
I also put the creation of Image aside as I did not have an image, so uncomment that and change as appropriate.
Here's a complete working version:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class LearnAppMain extends JFrame implements ActionListener {
// Define variables
public JButton button1;
public JLabel label1;
public JTextField field1;
private Image image1;
private String apple = "apple.jpg";
public LearnAppMain() {
//ImageIcon image1 = new ImageIcon(this.getClass().getResource(apple));
//JLabel label1 = new JLabel(image1);
label1 = new JLabel("hello");
label1.setVisible(false);
button1 = new JButton("A");
button1.addActionListener(this);
field1 = new JTextField(10);
// Create layout
setLayout(new FlowLayout());
// create Container
final Container cn = getContentPane();
cn.add(button1);
cn.add(field1);
cn.add(label1);
// setLayout(new FlowLayout());
setSize(250, 250);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (e.getSource() == button1) {
label1.setVisible(true);
field1.setText("Apple");
}
}
public static void main(String[] args) {
new LearnAppMain();
}
}
I'd suggest using separate (usually inner-class) ActionListener instances instead of overriding actionPerformed. See e.g. this for a similar example if you are interested:
http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/events/BeeperProject/src/events/Beeper.java
Also, if you are using this in a bigger application (i.e. not just experimenting or for prototyping), make sure all Swing code is run on EDT.
You typically use SwingUtilities.invokeLater for that purpose.
Hope this helps.
first you don't add the image first itself to JLabel.
just create the object and leave it like..
ImageIcon image1 = new ImageIcon(this.getClass().getResource(apple));
JLabel label1 = new JLabel("");
label1.setVisible(true);
then do the modification in the action performed
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button1)
{
field1.seticon(image1);
field1.revalidate();
}
it will definitely works
clientDetail.addActionListener(new ActionListener(){
public void actionPerformed (ActionEvent e){
d.getContentPane().removeAll();
g = new GridBagLayout();
gc = new GridBagConstraints();
d.setLayout(g);
JLabel message= new JLabel(" Message");
addComponent(message,5,1,1,2);
JTextArea Message = new JTextArea();
addComponent(Message,5,1,1,2);
d.setVisible(true);
d.setVisible(true);
d.pack();
}
private void addComponent(Component component, int i, int i0, int i1, int i2) {
gc.gridx=i;
gc.gridy=i0;
gc.gridheight=i1;
gc.gridwidth=i2;
g.setConstraints(component, gc);
add(component);
}
});
Recep.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
}
});