I'm trying to update a JFrame, and all of the components in the frame, including JPanel, JLabel components, etc. I tried using revalidate(), but that didn't seem to be working. I have a JLabel in the frame displaying an int, and I have the int iterating by 1 when I click a JButton. I can see that the value of the int changes, but the actual text on the label doesn't change. I know I can use JLabel.setText(), but is there a method to use for all components, that would update the displayed text/image upon pressing a button?
Here is my code below:
package repainttest;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Window extends JFrame {
int test = 1;
JLabel label;
public Window() {
setLayout(new FlowLayout());
label = new JLabel(Integer.toString(test));
add(label);
JButton button = new JButton("Add");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
test +=1;
System.out.println(test);
refresh();
}
});
add(button);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void refresh() {
SwingUtilities.updateComponentTreeUI(this);
revalidate();
repaint();
}
}
If you do not set the new text (test) on the JLabel, it is never going to know that the value of test is changing. So, please insert following statement:
label.setText(String.valueOf(test));
in public void actionPerformed(ActionEvent e) after following statement:
test +=1;
and see the results.
Related
I am working on a GUI project with Swing in Java and the program is generally working fine. However, under each screen, I have a back button that calls the method of the screen before it and goes through the ArrayList containing all of the elements on the current screen and calls setVisible(false) on them. Upon running the program, the back button works correctly if you click it once but if you go back on the screen, and click it again, it takes two clicks for it to correctly work and then four clicks and then eight clicks and so on. I have no idea what is going on or why it is behaving this way as nothing in my code seems to do it. Also, sometimes, the button correctly returns to the previous screen but then keeps the components on the current screen active as if setVisible(false) was never called. The following code represents the general structure of my project. Is there anything that it is doing that is generating this problem?
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class MAIN {
static JFrame frame;
static JPanel panel;
public static void main(String [] args) {
mainScreen();
}
public static void mainScreen() {
JButton newScreen = new JButton("Next Screen");
frame = new JFrame();
panel = new JPanel();
panel.setBounds(0,0,1920,1080);
panel.setBackground(Color.cyan);
newScreen.setBounds(50, 500, 100, 500);
newScreen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
newScreen.setVisible(false);
JButton returnButton = new JButton("return");
returnButton.setBounds(50, 50, 100, 100);
panel.add(returnButton);
returnButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
returnButton.setVisible(false);
mainScreen();
}
});
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.add(newScreen);
frame.add(panel);
frame.setSize(1920,1080);
frame.setLayout(null);
frame.setVisible(true);
}
}
import java.awt.*;
import java.sql.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
public class nava extends JFrame implements ActionListener
{
Button b1=new Button("clear");
TextField t1=new TextField();
public nava()
{
this.setLayout(new GridLayout(2,2));
b1.addActionListener(this);
this.setSize(200,200);
add(t1);
add(b1);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==b1)
{
t1.setText(""); //without space
}
}
public static void main(String r[])
{
new nava().show();
}
}
On clicking the button b1 the TextField should get empty but it is not
getting empty.The textfield just remain the same .But when I put space in the actionPerformed function it add a space in textfield. Please tell me what is the problem with the code.
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==b1)
{
t1.setText(" "); //with space
}
}
Use Swing components, not AWT components and the code should work. For example use JButton and JTextField not Button and TextField. Also don't call deprecated methods such as show(). Please consider checking the Swing tutorials as they'll teach you much you'll find useful. For example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class Nava extends JFrame implements ActionListener {
JButton b1 = new JButton("Clear");
JTextField t1 = new JTextField("Fubar", 10);
public Nava() {
this.setLayout(new GridLayout(2, 2));
b1.addActionListener(this);
// this.setSize(200, 200);
add(t1);
add(b1);
b1.setMnemonic(KeyEvent.VK_C); // alt-c to activate button
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
t1.setText("");
}
}
public static void main(String r[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Nava nava = new Nava();
nava.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
nava.pack(); // let components and layout managers size themselves
nava.setLocationByPlatform(true);
nava.setVisible(true);
}
});
}
}
As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
As for why your code doesn't work -- I honestly don't know as I don't work directly with AWT library components; very few people do. Edit: note this similar question. The authors of that question don't know why setText("") but offer a work-around:
// first this:
tf.setText(" ");
// followed by this:
tf.setText("");
I have a frame, on this frame I have a Menu with About MenuItem. When we select it the program opens a new JPanel with texts and with OK button and the enabled status of parent panel is set to false.
And now comes a problem. When we click on OK, then I want to close this About panel, and I want to turn to parent panel, and I want to enable it!
Please tell me, how?
Consider using a WindowListener that reacts to the closing event of the about-dialog. You can add this in your frame or in the constructor of your dialog, just set the variables accordingly.
myDialog.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
parentFrame.setEnabled(true);
}
});
If you really only have a switching JPanel, use a ButtonListener.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//Execute when button is pressed
frame.setEnabled(true);
}
});
As mentioned in the comments, using a modal JDialog would be a more elegant way of solving the problem of disabling a parent frame while a dialog is active. Here is a tutorial.
Why don't you use simply a JOptionPane (particularly the showMessageDialog method)? You can specify there an Object (for example a JPanel) which will be presented in a modal dialog. Take a look at this sample code I've written for you (I've used a JButton, but it will be the same for JMenuItem):
import java.awt.BorderLayout;
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.JOptionPane;
import javax.swing.JPanel;
public class AboutDialogDemo extends JFrame {
private final JButton btnAbout = new JButton("About...");
public AboutDialogDemo() {
final JFrame thisFrame = this;
btnAbout.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(thisFrame, new AboutPanel());
}
});
getContentPane().setLayout(new BorderLayout());
getContentPane().add(btnAbout, BorderLayout.PAGE_END);
pack();
}
public static void main(String[] args) {
AboutDialogDemo frame = new AboutDialogDemo();
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class AboutPanel extends JPanel {
private final JLabel lblAbout = new JLabel("Sample about text");
public AboutPanel() {
setLayout(new BorderLayout());
add(lblAbout, BorderLayout.PAGE_START);
}
}
I hope you'll find it useful
I am trying to toggle visibility of a JTextField with a checkbox. If the checkbox is selected I want the JTextField to be displayed and vice-versa. My program works fine until I add the line that initializes the JTextField to be invisible at the start. If I remove this the segment works fine! Can you help me?
final JCheckBox chckbxNewCheckBox_1 = new JCheckBox("New Folder");
panel_3.add(chckbxNewCheckBox_1);
final JTextField textField_3 = new JTextField();
panel_3.add(textField_3);
textField_3.setColumns(20);
//textField_3.setVisible(false); if a comment it in.. it never becomes visible
chckbxNewCheckBox_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
if(chckbxNewCheckBox_1.isSelected()){
textField_3.setVisible(true);
}
else
textField_3.setVisible(false);
}
});
Try with ActionListener instead of MouseListener
checkBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
textField_3.setVisible(checkBox.isSelected());
}
});
--EDIT--
call panel_3.revalidate(); after changing its visibility.
When an element is invisible during container initialization, it never gets its dimensions initialized. You can check it by calling getWidth() and getHeight() on the text area after you set it to visible. They're both zero. So follow #Braj edit and call panel.revalidate() after you change element visibility to let layout manager know that it's time to reposition/recalculate some elements and give them proper size.
You will do better with ItemListener
chckbxNewCheckBox_1.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.DESELECTED))
textField_3.setVisible(false);
else if (e.getStateChange() == ItemEvent.SELECTED))
textField_3.setVisible(true);
textField_3.revalidate();
}
});
Note: pelase follow naming conventions and use underscores only for constants.
Consider calling pack() method
Below is the complete code I experimented with:
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Test {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setLayout(new FlowLayout());
final JCheckBox chckbxNewCheckBox_1 = new JCheckBox("New Folder");
final JPanel panel_3 = new JPanel();
frame.add(panel_3);
panel_3.add(chckbxNewCheckBox_1);
final JTextField textField_3 = new JTextField();
panel_3.add(textField_3);
textField_3.setColumns(20);
textField_3.setVisible(false); //if a comment it in.. it never becomes visible
chckbxNewCheckBox_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
if (chckbxNewCheckBox_1.isSelected()) {
textField_3.setVisible(true);
} else
textField_3.setVisible(false);
frame.pack();
}
});
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
I want to display a TextField only when user has entered a value in Input field
Here is my code:
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class PlayingAround {
JFrame frame;
JTextField display;
JTextField input;
public static void main(String[] args) {
PlayingAround obj = new PlayingAround();
obj.create();
}
private void create() {
frame = new JFrame();
display = new JTextField();
input = new JTextField();
display.setEditable(false);
display.setVisible(false);
input.addKeyListener(new Listener());
frame.add(BorderLayout.NORTH, display);
frame.add(BorderLayout.SOUTH, input);
frame.setSize(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class Listener implements KeyListener {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
display.setVisible(true);
display.setText(input.getText());
}
}
}
But my problem is that the Display JTextField doesn't becomes visible until there are some events like Resizing the Window, Minimizing and maximizing the Window.
I tried calling frame.repaint() in the keyReleased Method but even it has not helped.
You should call revalidate() and repaint() on the container that holds the JTextField after placing the text field component in the container. The revalidate() call sends a request to the container's layout managers to re-layout its components. The repaint() then requests that the JVM request of the paint manager to redraw the newly laid out container and its child components. The repaint() is not always needed but is usually a good idea.
Also, don't use a KeyListener for this, but rather a DocumentListener on the first text component's Document. This way, if the user empties the first text component, you can make the second text component disappear if desired. Also, text can be entered without key presses, and you want to allow for that.