Strange Behaviour when using JTextArea with JScrollPane in JFrames [duplicate] - java

I have been experimenting with making GUIs in java as opposed to just using "static" all the time and come across the "SwingUtilities.invokeLater()" method. I manage to get everything setup but when it comes to run the application, nothing appears on the JPanel until I resize the window. Is there a fix for this or am I doing it wrong?
Heres my code:
public class main extends JPanel implements ActionListener{
public JLabel userLabel;
public JLabel passLabel;
public JTextField userField;
public JTextField passField;
public JButton login;
public JButton closeLogin;
public JButton help;
public main(){
userLabel = new JLabel("Username: ");
passLabel = new JLabel("Password: ");
userField = new JTextField(16);
passField = new JTextField(16);
login = new JButton("Login");
login.setActionCommand("login");
login.setMnemonic(KeyEvent.VK_L);
closeLogin = new JButton("Close");
closeLogin.setActionCommand("closeLogin");
closeLogin.setMnemonic(KeyEvent.VK_E);
help = new JButton("Help");
help.setActionCommand("helpLogin");
help.setMnemonic(KeyEvent.VK_H);
login.addActionListener(this);
closeLogin.addActionListener(this);
help.addActionListener(this);
add(userLabel);
add(userField);
add(passLabel);
add(passField);
add(login);
add(help);
add(closeLogin);
}
public void actionPerformed(ActionEvent e){
}
public static void initComponents(){
JFrame loginFrame = new JFrame("Encrypted Chat - Login");
loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main loginPanel = new main();
loginPanel.setLayout(new FlowLayout());
loginFrame.setSize(300, 125);
loginFrame.setResizable(false);
loginFrame.setVisible(true);
}
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
initComponents();
}
});
}
}
EDIT: I know the password JTextField is meant to be a JPasswordField.. so ignore it :P

Two basic advices:
1.) When you use swing, and stuff doesnt show up/update, you should call JPanel.revalidate() and JPanel.repaint() These two functions will update your panel.
If you are using a JFrame and you didn't add any extra panels to it, then you can get the content panel by JFrame.getContentPane()
2.) When you finished adding Components to a panel/frame you should also call pack() on the frame, this will ensure, that all your Components have the prefered size.

You never add your content to the JFrame. The minimal set of changes you need:
public static void main(String args[]){
final main main = new main();
SwingUtilities.invokeLater(new Runnable(){
public void run(){
initComponents(main);
}
});
}
And then modify initComponents to take a main object:
public static void initComponents(main main){
JFrame loginFrame = new JFrame("Encrypted Chat - Login");
loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main loginPanel = new main();
loginPanel.setLayout(new FlowLayout());
loginFrame.setSize(300, 125);
loginFrame.setResizable(false);
loginFrame.setVisible(true);
loginFrame.add(main); // <----- this line is added
}

for built_in FlowLayout (for JPanel) I don't suggest to use pack() for JFrame, sure correct way could be to use proper and better LayoutManager for this job, GridBagLayout or SpringLayout
output by using JFrame#setSize() and without pack()
for example
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class MainLogin implements ActionListener {
private JFrame loginFrame = new JFrame("Encrypted Chat - Login");
private JPanel pnl = new JPanel();
private JLabel userLabel;
private JLabel passLabel;
private JTextField userField;
private JTextField passField;
private JButton login;
private JButton closeLogin;
private JButton help;
public MainLogin() {
userLabel = new JLabel("Username: ");
passLabel = new JLabel("Password: ");
userField = new JTextField(16);
passField = new JTextField(16);
login = new JButton("Login");
login.setActionCommand("login");
login.setMnemonic(KeyEvent.VK_L);
closeLogin = new JButton("Close");
closeLogin.setActionCommand("closeLogin");
closeLogin.setMnemonic(KeyEvent.VK_E);
help = new JButton("Help");
help.setActionCommand("helpLogin");
help.setMnemonic(KeyEvent.VK_H);
login.addActionListener(this);
closeLogin.addActionListener(this);
help.addActionListener(this);
pnl.add(userLabel);
pnl.add(userField);
pnl.add(passLabel);
pnl.add(passField);
pnl.add(login);
pnl.add(help);
pnl.add(closeLogin);
loginFrame.add(pnl);
loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loginFrame.setSize(300, 125);
loginFrame.setResizable(false);
loginFrame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainLogin mainLogin = new MainLogin();
}
});
}
}

Put
JFrame.setVisible(true); on the last line after adding all components to it.

Related

How to use an ActionListener to make a JPanel Visible

I tried to make the first JPanel disappear and the second JPanel visible with the click of a JButton.
So far i only get the first JPanel to show and after clicking the JButton the Frame gets empty.
I also tried to do it with composition so i dont have to extend classes. So my bad understanding of how
composition works might be the problem. I looked into it alot but couldnt find a proper solution for my problem.
First JPanel class:
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Panel1 {
JPanel firstscreenpanel = new JPanel();
JButton jButton1 = new JButton();
Panel1() {
jButton1.setBounds(300,300,400,200);
jButton1.setBackground(Color.BLACK);
jButton1.setVisible(true);
jButton1.addActionListener(new ActionListener() {
Panel2 test = new Panel2();
public void actionPerformed(ActionEvent e) {
firstscreenpanel.setVisible(false);
test.secondscreenpanel.setVisible(true);
}
});
}
public Component panelone() {
firstscreenpanel.setSize(1280, 1024);
firstscreenpanel.setLayout(null);
firstscreenpanel.setBackground(Color.BLUE);
firstscreenpanel.add(jButton1);
firstscreenpanel.setVisible(true);
return firstscreenpanel;
}
}
Second JPanel class:
import java.awt.Color;
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Panel2 {
public JPanel secondscreenpanel = new JPanel();
public JButton jButton2 = new JButton();
Panel2() {
jButton2.setBounds(100,100,400,200);
jButton2.setBackground(Color.BLACK);
jButton2.setVisible(true);
}
public Component paneltwo() {
secondscreenpanel.setSize(1280, 1024);
secondscreenpanel.setLayout(null);
secondscreenpanel.add(jButton2);
secondscreenpanel.setBackground(Color.RED);
secondscreenpanel.setVisible(false);
return secondscreenpanel;
}
}
JFrame Class:
import javax.swing.JFrame;
public class Frame1 {
public JFrame frame1 = new JFrame();
Panel1 panel1 = new Panel1();
Panel2 panel2 = new Panel2();
Frame1() {
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setState(JFrame.MAXIMIZED_BOTH);
frame1.setSize(1280, 1024);
frame1.setLayout(null);
frame1.add(panel1.panelone());
frame1.add(panel2.paneltwo());
frame1.setVisible(true);
}
}
Main Class:
public class MainClass {
private void showGUI() {
Frame1 jframe = new Frame1();
}
public static void main(String[] args) {
final MainClass main = new MainClass();
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run() {
main.showGUI();
}
});
}
}
I did not check the whole code (too bug, too many empty lines) but stopped at Panel2 test = new Panel2();
is this instance being added to some visible component? if not it will never be displayed.
Note: using a null layout manager is often not recommended, use a CardLayout or even a JTabbedPane to switch components - see tutorial A Visual Guide to Layout Managers
This is not the best implementation, but it is simple enough for you to follow. I modified your code to create a frame containing your original two panels (although those panel classes are not necessary - as I explained in a comment on your posted solution), and a button to toggle visibility on the panels. I am using a regular JButton and not a JToggleButton also not the best use of the class, but simply for you to understand.
The Action Listener is added to the button on the frame. Notice that my action listener does not create new instances of anything. That was part of the original problem. Since the button is a member of the frame class like the panels 1 and 2, it has access to them directly. SO, in the listener, all I need to do is "toggle" the visibility of each of the panels.
public class Frame1 extends JFrame {
private Panel1 panel1 = new Panel1();
private Panel2 panel2 = new Panel2();
private JPanel btnPanel = new JPanel();
private JButton button = new JButton("Toggle");
public Frame1() {
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
boolean visible = panel1.isVisible();
panel1.setVisible(!visible);
panel2.setVisible(visible);
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setState(JFrame.MAXIMIZED_BOTH);
setSize(1280, 1024);
btnPanel.setSize(400, 100);
btnPanel.add(button);
setLayout(null);
add(panel1);
add(panel2);
add(btnPanel);
}
}
public class Panel1 extends JPanel {
public Panel1() {
setBounds(100,100,400,200);
setBackground(Color.RED);
setVisible(true);
}
}
public class Panel2 extends JPanel {
public Panel2() {
setBounds(100,100,400,200);
setBackground(Color.BLACK);
setVisible(false);
}
}
public class MainClass {
private void showGUI() {
Frame1 jframe = new Frame1();
jframe.setVisible(true);
}
public static void main(String[] args) {
final MainClass main = new MainClass();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
main.showGUI();
}
});
}
}
You can fix your program by passing a reference of your frame to your panel1. See my example below.
Frame class
import javax.swing.*;
public class Frame1 {
private JFrame frame = new JFrame();
private Panel1 panel1;
private Panel2 panel2;
Frame1() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setState(JFrame.MAXIMIZED_BOTH);
frame.setSize(1280, 1024);
frame.setLayout(null);
panel1 = new Panel1(this);
frame.add(panel1.getPanel());
panel2 = new Panel2();
frame.add(panel2.getPanel());
frame.setVisible(true);
}
public Panel2 getPanel2() {
return panel2;
}
}
Panel1 class
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Panel1 {
private JPanel panel = new JPanel();
private Frame1 frame1;
private JButton jButton1 = new JButton();
public Panel1(Frame1 frame1) {
this.frame1 = frame1;
panel.setSize(1280, 1024);
panel.setLayout(null);
panel.setBackground(Color.BLUE);
panel.add(jButton1);
panel.setVisible(true);
jButton1.setBounds(300,300,400,200);
jButton1.setBackground(Color.BLACK);
jButton1.setVisible(true);
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.setVisible(false);
frame1.getPanel2().getPanel().setVisible(true);
}
});
}
public JPanel getPanel() {
return panel;
}
}
Panel2 class
import javax.swing.*;
import java.awt.*;
public class Panel2 {
private JButton jButton2 = new JButton();
private JPanel panel = new JPanel();
public Panel2() {
panel.setSize(1280, 1024);
panel.setLayout(null);
panel.add(jButton2);
panel.setBackground(Color.RED);
panel.setVisible(false);
jButton2.setBounds(100,100,400,200);
jButton2.setBackground(Color.BLACK);
jButton2.setVisible(true);
}
public JPanel getPanel() {
return panel;
}
}
I solved my problem by adding "public static" to "Panel2 panel2 = new Panel2();"
And then i just used:
"Frame1.panel2.secondscreenpanel.setVisible(true);"
inside the JButton ActionListener.
Its now working but i guess thats a bad way of doing it. Because i heard that using to much static isnt that good. But i dont now why yet.

formatting JTextfields using another class

this is the code of the Gui Design class and below is the Class that provides functionality to the program. Im trying to get user input from the textfields so i can remove the text using the clearAll method and also save user input using the saveit method.I tried using nameEntry.setText(""); in the clearAll method but it wont work can someone help me please!
//Import Statements
import javax.swing.*;
import java.awt.*;
import javax.swing.JOptionPane;
import java.awt.event.*;
//Class Name
public class Customer extends JFrame {
Function fun = new Function();
public static void main(String[]args){
Customer.setLookAndFeel();
Customer cust = new Customer();
}
public Customer(){
super("Resident Details");
setSize(500,500);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
FlowLayout two = new FlowLayout(FlowLayout.LEFT);
setLayout(two);
JPanel row1 = new JPanel();
JLabel name = new JLabel("First Name",JLabel.LEFT);
JTextField nameEntry = new JTextField("",20);
row1.add(name);
row1.add(nameEntry);
add(row1);
JPanel row2 = new JPanel();
JLabel surname = new JLabel("Surname ",JLabel.LEFT);
JTextField surnameEntry = new JTextField("",20);
row2.add(surname);
row2.add(surnameEntry);
add(row2);
JPanel row3 = new JPanel();
JLabel contact1 = new JLabel("Contact Details : Email ",JLabel.LEFT);
JTextField contact1Entry = new JTextField("",10);
FlowLayout newflow = new FlowLayout(FlowLayout.LEFT,10,30);
setLayout(newflow);
row3.add(contact1);
row3.add(contact1Entry);
add(row3);
JPanel row4 = new JPanel();
JLabel contact2 = new JLabel("Contact Details : Phone Number",JLabel.LEFT);
JTextField contact2Entry = new JTextField("",10);
row4.add(contact2);
row4.add(contact2Entry);
add(row4);
JPanel row5 = new JPanel();
JLabel time = new JLabel("Duration Of Stay ",JLabel.LEFT);
JTextField timeEntry = new JTextField("",10);
row5.add(time);
row5.add(timeEntry);
add(row5);
JPanel row6 = new JPanel();
JComboBox<String> type = new JComboBox<String>();
type.addItem("Type Of Room");
type.addItem("Single Room");
type.addItem("Double Room");
type.addItem("VIP Room");
row6.add(type);
add(row6);
JPanel row7 = new JPanel();
FlowLayout amt = new FlowLayout(FlowLayout.LEFT,100,10);
setLayout(amt);
JLabel amount = new JLabel("Amount Per Day ");
JTextField AmountField = new JTextField("\u20ac ",10);
row7.add(amount);
row7.add(AmountField);
add(row7);
JPanel row8 = new JPanel();
FlowLayout prc = new FlowLayout(FlowLayout.LEFT,100,10);
setLayout(prc);
JLabel price = new JLabel("Total Price ");
JTextField priceField = new JTextField("\u20ac ",10);
row8.add(price);
row8.add(priceField);
add(row8);
JPanel row9 = new JPanel();
JButton clear = new JButton("Clear");
row9.add(clear);
add(row9);
JPanel row10 = new JPanel();
JButton save = new JButton("Save");
save.addActionListener(fun);
row10.add(save);
add(row10);
//Adding ActionListners
nameEntry.addActionListener(fun);
clear.addActionListener(fun);
save.addActionListener(fun);
setVisible(true);
}
private static void setLookAndFeel() {
try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
);
} catch (Exception exc) {
// ignore error
}
}
}
//Import Statements
import javax.swing.*;
import java.awt.*;
import java.awt.Color;
import javax.swing.JOptionPane;
import java.awt.event.*;
//Class Name
public class Function implements ActionListener {
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if(command.equals("Add Customer")) {
Login();
}
else if(command.equals("Register")){
Registration();
}
else if(command.equals("Exit")){
System.exit(0);
}
else if(command.equals("Clear")){
ClearAllFields();
}
else if(command.equals("Save")){
SaveIt();
}
}
public static void Login(){
Customer cust = new Customer();
}
public static void Registration(){
//Do Nothing
}
//This clears all the text from the JTextFields
public static void ClearAllFields(){
}
//This will save Info on to another Class
public static void SaveIt(){
}
}
Alternatively, you can make nameEntry known to the Function class by defining it before calling the constructor for Function and then passing it into the constructor, like:
JTextField nameEntry = new JTextField("",20);
Function fun = new Function(nameEntry);
Then, in Function, add nameEntry as a member variable of Function and make a constructor for Function which accepts nameEntry, (right after the "public class Function..." line), like:
JTextField nameEntry;
public Function(JTextField nameEntry) {
this.nameEntry = nameEntry;
}
Now, the following will compile:
public void ClearAllFields(){
nameEntry.setText("");
}
And, the Clear button will clear the name field.
Again as per comments, one simple way to solve this is to give the gui public methods that the controller (the listener) can call, and then pass the current displayed instance of the GUI into the listener, allowing it to call any public methods that the GUI might have. The code below is simpler than yours, having just one JTextField, but it serves to illustrate the point:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class GUI extends JPanel {
private JTextField textField = new JTextField(10);
private JButton clearButton = new JButton("Clear");
public GUI() {
// pass **this** into the listener class
MyListener myListener = new MyListener(this);
clearButton.addActionListener(myListener);
clearButton.setMnemonic(KeyEvent.VK_C);
add(textField);
add(clearButton);
}
// public method in GUI that will do the dirty work
public void clearAll() {
textField.setText("");
}
// other public methods here to get text from the JTextFields
// to set text, and do whatever else needs to be done
private static void createAndShowGui() {
GUI mainPanel = new GUI();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MyListener implements ActionListener {
private GUI gui;
// use constructor parameter to set a field
public MyListener(GUI gui) {
this.gui = gui;
}
#Override
public void actionPerformed(ActionEvent e) {
gui.clearAll(); // call public method in field
}
}
A better and more robust solution is to structure your program in a Model-View-Controller fashion (look this up), but this would probably be overkill for this simple academic exercise that you're doing.

Java take input string in one Jframe and display in another

I have to get a String input in one JFrame and display in another.
My second task is to flash the given string in a larger font in the second frame, at an interval of 1sec.
How to proceed?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Input{
String hinput;
private JFrame mainFrame;
private JLabel headerLabel;
private JLabel statusLabel;
private JPanel controlPanel;
private void prepareGUI(){
mainFrame = new JFrame("STRING");
mainFrame.setSize(500,100);
headerLabel = new JLabel("", JLabel.CENTER);
controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
mainFrame.add(headerLabel);
mainFrame.add(controlPanel);
mainFrame.setVisible(true);
}
private void showTextField(){
JLabel stringlabel= new JLabel("String ", JLabel.RIGHT);
final JTextField userText = new JTextField(20);
JButton submitButton = new JButton("Submit");
submitButton.addActionListener(new mylistener());
submitButton.setActionCommand("open");
controlPanel.add(stringlabel);
controlPanel.add(userText);
controlPanel.add(submitButton);
mainFrame.setVisible(true);
}
private class mylistener implements ActionListener{
public void actionPerformed(ActionEvent e){
String cmd = e.getActionCommand();
if(cmd.equals("open")){
mainFrame.dispose();
NewJFrame nj= new NewJFrame(hinput);
}
}
}
public static void main(String args[]){
Input Inp = new Input();
Inp.prepareGUI();
Inp.showTextField();
}
}
class NewJFrame{
JFrame mainFrame;
String text;
JLabel l1;
JTextField tb1;
public NewJFrame(String t){
text=t;
mainFrame=new JFrame("STRING");
mainFrame.setSize(800,800);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
l1=new JLabel("Entered string");
tb1.setText(text);
mainFrame.add(l1);
mainFrame.add(tb1);
mainFrame.setVisible(true);
}
}
I am getting traceback after i click 'submit' button.
Please point out the errors.
You can get rid of the error by instatiating tb1 in your NewJFrame class like so:
class NewJFrame{
JFrame mainFrame;
String text;
JLabel l1;
JTextField tb1;
public NewJFrame(String t){
text=t;
mainFrame=new JFrame("STRING");
mainFrame.setSize(800,800);
// *** must init tb1!!! ***///
JTextField tb1 = new JTextField();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
l1=new JLabel("Entered string");
tb1.setText(text);
mainFrame.add(l1);
mainFrame.add(tb1);
mainFrame.setVisible(true);
}
}
As for getting text typed in one JFrame to open in another, I have a slightly modified solution. Maybe have text entered in a JTextField on one JPanel display in another JPanel. To do that, you could use the following code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JLabel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;
public class SimpleGUI extends JFrame {
private final JPanel firstPanel;
private final JPanel secondPanel;
private final JButton submitButton;
private final JTextField textField;
private final JLabel secondPanelLabel;
public SimpleGUI() {
// sets the title of the JFrame
super("SimpleGUI");
setLayout(new FlowLayout());
// inits both JPanels
firstPanel = new JPanel();
secondPanel = new JPanel();
// inits empty second JLabel and adds to the secondPanel
secondPanelLabel = new JLabel();
secondPanel.add(secondPanelLabel);
// makes the secondPanel invisible for the time being
secondPanel.setVisible(false);
// inits the submit button
submitButton = new JButton("Submit");
// event-handler for submit button, will set the text in the
// secondPanelLabel to the text in the JTextField the user types
// into. It then makes the firstPanel (with the text field and button),
// invisible, and then makes the second panel visible.
submitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
secondPanelLabel.setText(textField.getText());
firstPanel.setVisible(false);
secondPanel.setVisible(true);
}
});
// inits the textField
textField = new JTextField(10);
// adds the button and the text field to the firstPanel
firstPanel.add(submitButton);
firstPanel.add(textField);
// adds both panels to this JFrame
this.add(firstPanel);
this.add(secondPanel);
}
}
And here is a class with a main method that constructs the SimpleGUI so you can test it out for yourself:
import javax.swing.JFrame;
public class SimpleGUITest {
public static void main(String[] args) {
SimpleGUI frame = new SimpleGUI();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setVisible(true);
}
}

Simple Java GUI Program

My JPanel and JTextField are for some reason not appearing. The programs only task is to add a number to the counter every time the button is clicked. No compiling errors nor console issues. Simply not showing up??
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Swing
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
final JFrame mainFrame = new JFrame ("Counter (Program 1/2)");
mainFrame.setVisible(true);
mainFrame.setSize(400, 200);
mainFrame.setLayout(new BorderLayout());
mainFrame.setLocationRelativeTo(null);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton countButton = new JButton("Count up");
mainFrame.add(countButton, BorderLayout.SOUTH);
countButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
JTextField clicks = new JTextField(BorderLayout.CENTER);
JPanel firstPanel = new JPanel();
mainFrame.add(firstPanel);
mainFrame.add(clicks, BorderLayout.NORTH);
int counter = 1;
counter++;
String textField = String.valueOf(counter);
clicks.setText(textField);
}
});
}
});
}
}
Don't add the JTextField and JPanel inside the ActionListener. This makes no sense since you'll be re-adding new components each time the button is pressed. Instead add them on GUI creation, before calling setVisible(true) on the GUI. Then update the text field's text in the ActionListener.
As a side recommendation: try to make your class more object oriented by giving it fields, a constructor, and getting most all of that code out of the static main method.
Your mistakes:
Add clicks and firstpanel to the frame in run method, not in the actionPerformed
BorderLayout.CENTER should be pass as a parameter to add method, not to the text field constructor.
Define count as static. This is not the best way but in your situation it is the easiest way.
Call mainFrame.setVisible(true); after you added all your components.
Here is the working code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Swing {
public static int counter = 1;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final JFrame mainFrame = new JFrame("Counter (Program 1/2)");
mainFrame.setSize(400, 200);
mainFrame.setLayout(new BorderLayout());
mainFrame.setLocationRelativeTo(null);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton countButton = new JButton("Count up");
mainFrame.add(countButton, BorderLayout.SOUTH);
final JTextField clicks = new JTextField(String.valueOf(counter));
JPanel firstPanel = new JPanel();
mainFrame.add(firstPanel, BorderLayout.CENTER);
mainFrame.add(clicks, BorderLayout.NORTH);
countButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
counter++;
String textField = String.valueOf(counter);
clicks.setText(textField);
}
});
mainFrame.setVisible(true);
}
});
}
}

GUI elements not showing until resize of window

I have been experimenting with making GUIs in java as opposed to just using "static" all the time and come across the "SwingUtilities.invokeLater()" method. I manage to get everything setup but when it comes to run the application, nothing appears on the JPanel until I resize the window. Is there a fix for this or am I doing it wrong?
Heres my code:
public class main extends JPanel implements ActionListener{
public JLabel userLabel;
public JLabel passLabel;
public JTextField userField;
public JTextField passField;
public JButton login;
public JButton closeLogin;
public JButton help;
public main(){
userLabel = new JLabel("Username: ");
passLabel = new JLabel("Password: ");
userField = new JTextField(16);
passField = new JTextField(16);
login = new JButton("Login");
login.setActionCommand("login");
login.setMnemonic(KeyEvent.VK_L);
closeLogin = new JButton("Close");
closeLogin.setActionCommand("closeLogin");
closeLogin.setMnemonic(KeyEvent.VK_E);
help = new JButton("Help");
help.setActionCommand("helpLogin");
help.setMnemonic(KeyEvent.VK_H);
login.addActionListener(this);
closeLogin.addActionListener(this);
help.addActionListener(this);
add(userLabel);
add(userField);
add(passLabel);
add(passField);
add(login);
add(help);
add(closeLogin);
}
public void actionPerformed(ActionEvent e){
}
public static void initComponents(){
JFrame loginFrame = new JFrame("Encrypted Chat - Login");
loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main loginPanel = new main();
loginPanel.setLayout(new FlowLayout());
loginFrame.setSize(300, 125);
loginFrame.setResizable(false);
loginFrame.setVisible(true);
}
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
initComponents();
}
});
}
}
EDIT: I know the password JTextField is meant to be a JPasswordField.. so ignore it :P
Two basic advices:
1.) When you use swing, and stuff doesnt show up/update, you should call JPanel.revalidate() and JPanel.repaint() These two functions will update your panel.
If you are using a JFrame and you didn't add any extra panels to it, then you can get the content panel by JFrame.getContentPane()
2.) When you finished adding Components to a panel/frame you should also call pack() on the frame, this will ensure, that all your Components have the prefered size.
You never add your content to the JFrame. The minimal set of changes you need:
public static void main(String args[]){
final main main = new main();
SwingUtilities.invokeLater(new Runnable(){
public void run(){
initComponents(main);
}
});
}
And then modify initComponents to take a main object:
public static void initComponents(main main){
JFrame loginFrame = new JFrame("Encrypted Chat - Login");
loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main loginPanel = new main();
loginPanel.setLayout(new FlowLayout());
loginFrame.setSize(300, 125);
loginFrame.setResizable(false);
loginFrame.setVisible(true);
loginFrame.add(main); // <----- this line is added
}
for built_in FlowLayout (for JPanel) I don't suggest to use pack() for JFrame, sure correct way could be to use proper and better LayoutManager for this job, GridBagLayout or SpringLayout
output by using JFrame#setSize() and without pack()
for example
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class MainLogin implements ActionListener {
private JFrame loginFrame = new JFrame("Encrypted Chat - Login");
private JPanel pnl = new JPanel();
private JLabel userLabel;
private JLabel passLabel;
private JTextField userField;
private JTextField passField;
private JButton login;
private JButton closeLogin;
private JButton help;
public MainLogin() {
userLabel = new JLabel("Username: ");
passLabel = new JLabel("Password: ");
userField = new JTextField(16);
passField = new JTextField(16);
login = new JButton("Login");
login.setActionCommand("login");
login.setMnemonic(KeyEvent.VK_L);
closeLogin = new JButton("Close");
closeLogin.setActionCommand("closeLogin");
closeLogin.setMnemonic(KeyEvent.VK_E);
help = new JButton("Help");
help.setActionCommand("helpLogin");
help.setMnemonic(KeyEvent.VK_H);
login.addActionListener(this);
closeLogin.addActionListener(this);
help.addActionListener(this);
pnl.add(userLabel);
pnl.add(userField);
pnl.add(passLabel);
pnl.add(passField);
pnl.add(login);
pnl.add(help);
pnl.add(closeLogin);
loginFrame.add(pnl);
loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loginFrame.setSize(300, 125);
loginFrame.setResizable(false);
loginFrame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainLogin mainLogin = new MainLogin();
}
});
}
}
Put
JFrame.setVisible(true); on the last line after adding all components to it.

Categories

Resources