i was following a tutorial on youtube to learn java guis ands i was making a login screen.
i was testing the login button by making it print works in console w but i presses. i followed the whole tutoral properly and tried every way. the code is spamming widows shown in the video.
link to video : https://hriday.tk/2022-01-09%2019-56-32.mkv
the code :
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Login implements ActionListener{
public Login() {
JPanel panel = new JPanel();
JFrame frame = new JFrame();
JLabel Ulabel = new JLabel("UserName");
JLabel Plabel = new JLabel("PassWord");
JTextField Utext = new JTextField(20);
JPasswordField Ptext = new JPasswordField(20);
JButton login = new JButton("Login");
JLabel success = new JLabel("");
panel.setLayout(null);
panel.add(Ulabel);
panel.add(Utext);
panel.add(Plabel);
panel.add(Ptext);
panel.add(login);
panel.add(success);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(350, 150);
frame.setTitle("Login");
frame.add(panel);
Ulabel.setBounds(10, 10, 80, 25);
Utext.setBounds(100, 10, 165, 25);
Plabel.setBounds(10, 40, 80, 25);
Ptext.setBounds(100, 40, 165, 25);
login.setBounds(50, 70, 100, 25);
success.setBounds(200, 70, 100, 25);
login.addActionListener(new Login());
}
public static void main(String[] args){ new Login(); }
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("works");
}
} ```
This is causing your problems:
// imports
public class Login implements ActionListener {
public Login() {
// .... code removed
login.addActionListener(new Login()); // **** here ****
}
// .....
}
You're calling this in the Login constructor and so are creating new Login objects recursively, meaning, each time the Login constructor is called, it creates a new Login object, which calls the constructor, which creates a new Login object, which.... well, you should get the point.
Instead, change it to this:
login.addActionListener(this);
Here you add the already created Login object, the this object, and add it to the ActionListener.
Caveat:
Having said this, I would be remiss if I didn't mention that using null layouts and setBounds(...) is not healthy as this makes for very inflexible GUI's that while they might look good on one platform look terrible on most other platforms or screen resolutions and that are very difficult to update and maintain. Instead, you will want to study and learn the layout managers and then nest JPanels, each using its own layout manager to create pleasing and complex GUI's that look good on all OS's.
For that reason you're far better off learning about and using the layout managers. You can find the layout manager tutorial here: Layout Manager Tutorial, and you can find links to the Swing tutorials and to other Swing resources here: Swing Info.
... and if this is from a tutorial and it recommends use of null layouts, then ditch the tutorial!
For example (using GridBagLayout):
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import javax.swing.*;
public class Login2 {
private static final int GAP = 5;
private JPanel mainPanel = new JPanel();
private JTextField userNameField = new JTextField(20);
private JPasswordField passwordField = new JPasswordField(20);
private JButton loginButton = new JButton("Login");
private JLabel successLabel = new JLabel(" ");
public Login2() {
mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
mainPanel.setLayout(new GridBagLayout());
mainPanel.add(new JLabel("UserName:"), createGBC(0, 0));
mainPanel.add(userNameField, createGBC(1, 0));
mainPanel.add(new JLabel("Password:"), createGBC(0, 1));
mainPanel.add(passwordField, createGBC(1, 1));
mainPanel.add(loginButton, createGBC(0, 2));
mainPanel.add(successLabel, createGBC(1, 2));
loginButton.addActionListener(e -> {
successLabel.setText("Success");
Window window = SwingUtilities.getWindowAncestor(mainPanel);
window.dispose();
});
}
public String getUserName() {
return userNameField.getText();
}
public char[] getPassword() {
return passwordField.getPassword();
}
// create constraints that help position components in the GridBagLayout-using container
private GridBagConstraints createGBC(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.insets = new Insets(GAP, GAP, GAP, GAP);
return gbc;
}
public JPanel getMainPanel() {
return mainPanel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Login2 login2 = new Login2();
JDialog dialog = new JDialog(null, "Login", ModalityType.APPLICATION_MODAL);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.add(login2.getMainPanel());
dialog.pack();
dialog.setLocationByPlatform(true);
dialog.setVisible(true);
System.out.println("User Name: " + login2.getUserName());
System.out.println("Password: " + new String(login2.getPassword()));
});
}
}
Related
Recently I've been trying to make a program that takes in a double in the form of a string. It then parses that to a double which goes to another class to be divided to a quarter or a half and then returns that output to a label.
I've been having an issue where when I click a button to actually submit what is inside the text field, the label doesn't change.
I've tried a lot of trial and error and I know I can change the text after doing new JLabel("test") for example. However, there seems to be an issue with my action listener for when the button is pushed. I can't tell if it's not seeing the button as being pushed.
NOTE: I am new to awt event things and swing as a whole, I usually operate just using the output terminal of visual studio code where it's just text and no graphics.
import javax.swing.*;
import java.awt.event.*;
import java.awt.Font;
import java.awt.Dimension;
public class MoneySorterRunner {
private MoneySorter sorter = new MoneySorter();
private String input = "0";
private double money = Double.parseDouble(input);
private static JTextField typeHere = new JTextField();
///labels num1-3 are the labels being changed
private static JLabel num1 = new JLabel(new MoneySorterRunner().sorter.divQuarter(new MoneySorterRunner().money));
private static JLabel num2 = new JLabel(new MoneySorterRunner().sorter.divQuarter(new MoneySorterRunner().money));
private static JLabel num3 = new JLabel(new MoneySorterRunner().sorter.divHalf(new MoneySorterRunner().money));
public static void main(String args[]) {
JFrame frame = new JFrame("Money Calculator - v0.1a");
JPanel panel = new JPanel();
JButton doThing = new JButton("Do a Thing");
doThing.setActionCommand("Do a Thing");
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 250);
frame.setLocation(200, 200);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
panel.setLayout(null);
frame.setVisible(true);
JLabel item1 = new JLabel("test");
JLabel item2 = new JLabel("test");
JLabel item3 = new JLabel("test");
item1.setFont(new Font("Arial", Font.PLAIN, 30));
item2.setFont(new Font("Arial", Font.PLAIN, 30));
item3.setFont(new Font("Arial", Font.PLAIN, 30));
num1.setFont(new Font("Arial", Font.PLAIN, 25));
num2.setFont(new Font("Arial", Font.PLAIN, 25));
num3.setFont(new Font("Arial", Font.PLAIN, 25));
Dimension size1 = item1.getPreferredSize();
Dimension size2 = item2.getPreferredSize();
Dimension size3 = item3.getPreferredSize();
panel.add(item1);
panel.add(item2);
panel.add(item3);
panel.add(num1);
panel.add(num2);
panel.add(num3);
panel.add(doThing);
panel.add(typeHere);
item1.setBounds(10, 10, size1.width + 3, size1.height);
item2.setBounds(190, 10, size2.width + 3, size2.height);
item3.setBounds(325, 10, size3.width + 3, size3.height);
num1.setBounds(50, 50, 50, 25);
num2.setBounds(200, 50, 50, 25);
num3.setBounds(350, 50, 50, 25);
doThing.setBounds(250, 150, 100, 25);
typeHere.setBounds(100, 150, 150, 25);
}
public void actionPerformed(ActionEvent event){
String check = event.getActionCommand();
if(check.equals("Do a Thing")){
input = typeHere.getText();
}
if(input != "0"){
num1.setText(sorter.divQuarter(money));
num2.setText(sorter.divQuarter(money));
num3.setText(sorter.divHalf(money));
}
}
}
For those who wanted the MoneySorter.java:
public MoneySorter(){
}
public String divQuarter(double moneyIn){
String answer = Double.toString(moneyIn);
return answer;
}
public String divHalf(double moneyIn){
String answer = Double.toString(moneyIn);
return answer;
}
}
I understand that your program is supposed to do the following.
User enters an amount of money in a JTextField and when she clicks on a JButton the JLabels show the entered amount in dollars, half-dollars and quarters (as per U.S. currency). My answer, below, is based on this understanding.
I don't know if making all the variables static is good or bad but I never use static class member variables in my Swing programs.
Here is my analysis of your code.
private double money = Double.parseDouble(input);
This line of code will be executed precisely once, when you launch class MoneySorterRunner. You want to do this every time the JButton is clicked, hence parsing the text entered into the JTextField should be performed in the actionPerformed method.
JPanel panel = new JPanel();
panel.setLayout(null);
It is almost never needed to set the layout manager to null. You can almost always find an appropriate layout manager or you can place one JPanel within another and use different layout managers for each JPanel in order to get the desired placement of components within the Swing application window.
JButton doThing = new JButton("Do a Thing");
doThing.setActionCommand("Do a Thing");
By default, the text of a JButton is also its action command so no need to explicitly set it.
frame.setLocation(200, 200);
frame.setLocationRelativeTo(null);
These are two different ways to set the location of the JFrame and they do not complement each other. Use one or the other, but not both.
frame.setVisible(true);
Only after you have created all the [GUI] components and added them to the JFrame should you make the JFrame visible. So this should be the last line of the code that creates your GUI.
doThing.setBounds(250, 150, 100, 25);
If you use a layout manager, you never need to call method setBounds.
if(input != "0"){
This is not the way to compare strings. Use method equals as you have done here
if(check.equals("Do a Thing")){
Here is my rewrite of your application. Note that since I could not find the code for class MoneySorter, in your question, I just created my own version of that class. The point is to show how to change the text of the JLabel after clicking on the JButton and not how to create the actual text to display.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class MoneySorterRunner implements ActionListener {
private MoneySorter sorter = new MoneySorter();
private JTextField typeHere = new JTextField();
private JLabel num1;
private JLabel num2;
private JLabel num3;
private void createAndShowGui() {
JFrame frame = new JFrame("Money Calculator - v0.1a");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(createLabels(), BorderLayout.PAGE_START);
frame.add(createForm(), BorderLayout.CENTER);
frame.setSize(550, 250);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createForm() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0));
panel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
typeHere = new JTextField(10);
panel.add(typeHere);
JButton doThing = new JButton("Do a Thing");
doThing.addActionListener(this);
panel.add(doThing);
return panel;
}
private static JLabel createLabel(String text) {
JLabel label = new JLabel(text);
label.setFont(new Font("Arial", Font.PLAIN, 25));
return label;
}
private JPanel createLabels() {
JPanel panel = new JPanel(new GridLayout());
num1 = createLabel("num1");
panel.add(num1);
num2 = createLabel("num2");
panel.add(num2);
num3 = createLabel("num3");
panel.add(num3);
return panel;
}
public static void main(String args[]) {
new MoneySorterRunner().createAndShowGui();
}
public void actionPerformed(ActionEvent event){
String check = event.getActionCommand();
if(check.equals("Do a Thing")){
String text = typeHere.getText();
if (!text.isEmpty()) {
double money = Double.parseDouble(text);
num1.setText(sorter.divQuarter(money));
num2.setText(sorter.divQuarter(money));
num3.setText(sorter.divHalf(money));
}
}
}
}
class MoneySorter {
public String divQuarter(double money) {
return "divQuarter(" + money + ")";
}
public String divHalf(double money) {
return "divHalf(" + money + ")";
}
}
This is how your GUI looked when I ran your original code (as posted in your question).
This is how the GUI looks when running the code in this answer.
After launching
After entering a value and clicking the JButton
It looks like you forgot to set the ActionListener. You should also change your method to another name, because your method has the same name as the actionPerformed of the ActionListener.
doThing.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new MoneySorterRunner().actionPerformedMethod(e);
}
});
You forgot to add the ActionListener.
In order to fix this, you need to do two things:
Add this statement to your code, preferably near where you create the button (so that it is easier to keep track). -
doThing.addActionListener(this);
When you write "public class", you also need this keyword: implements ActionListener - meaning your class (basically the first line) should look like:
public class MoneySorterRunner implements ActionListener
And that should make it work.
Recently I'm writing a mail system client using Java (I chose swing to write the GUI and use IDEA to hardcode my GUI). In the Compose module, I want to show or hide the textfield for CC and Bcc when I click the corresponding buttons.
So I googled and browsed the following questions and doc on the web:
How to make JPanel scrollable in Java?
How to make JPanel scrollable?
Scrolling a JPanel
Doc: JScrollPane
Finally, I chose the JScrollPane to implement it.
My simplified sample code is as follows (the original code is tedious):
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Demo extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JLabel lbl1;
private JTextField txf1;
private JLabel lbl2;
private JTextField txf2;
// container for lbl2 and txf2, which should be able to be shown or hidden
private JPanel pnlContainer2;
private JLabel lbl3;
private JTextField txf3;
// container for lbl3 and txf3
private JPanel pnlContainer3;
private JButton btnShow;
// the container I want to move when I click btnShow
private JPanel pnlBody;
// the panel to hold my "cards"
// In this example, I include it just to show what controls are on my interface.
private JPanel pnlContent;
private JPanel pnlContainer;
// here, I want to use JScrollPane to make my pnlContainer scrollable
// to adapt to my interface
private JScrollPane scrollPane;
public Demo() {
init();
}
private void init() {
pnlContainer = new JPanel(new CardLayout(), true);
pnlContainer.setBounds(0, 0, 200, 180);
pnlContent = new JPanel(null, true);
pnlContent.setBounds(0, 0, 200, 180 + 50);
scrollPane = new JScrollPane(pnlContent, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBounds(0, 0, 200, 180);
pnlContainer.add(scrollPane);
pnlBody = new JPanel(null, true);
lbl1 = new JLabel("lbl1");
lbl1.setBounds(10, 20, 40, 30);
txf1 = new JTextField();
txf1.setBounds(60, 20, 120, 30);
pnlContent.add(lbl1);
pnlContent.add(txf1);
pnlContainer2 = new JPanel(null, true);
pnlContainer2.setBounds(0, 70, 180, 30);
lbl2 = new JLabel("lbl2");
lbl2.setBounds(10, 0, 40, 30);
txf2 = new JTextField();
txf2.setBounds(60, 0, 120, 30);
pnlContainer2.add(lbl2);
pnlContainer2.add(txf2);
pnlContainer2.setVisible(false);
pnlContent.add(pnlContainer2);
pnlBody = new JPanel(null, true);
pnlBody.setBounds(0, 70, 180, 90);
pnlContainer3 = new JPanel(null, true);
pnlContainer3.setBounds(0, 0, 180, 30);
pnlBody.add(pnlContainer3);
lbl3 = new JLabel("lbl3");
lbl3.setBounds(10, 0, 40, 30);
txf3 = new JTextField();
txf3.setBounds(60, 0, 120, 30);
pnlContainer3.add(lbl3);
pnlContainer3.add(txf3);
btnShow = new JButton("show");
btnShow.setBounds(60, 50, 80, 30);
btnShow.addActionListener(this);
pnlBody.add(btnShow);
pnlContent.add(pnlBody);
this.add(pnlContainer);
this.setLayout(null);
this.setTitle("Demo");
this.setSize(200, 200);
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setResizable(false);
// ImageIcon icon = new ImageIcon("E:\\Javarepo\\Hmail\\src\\main\\resources\\assets\\hmail.png");
// this.setIconImage(icon.getImage());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
Object src = e.getSource();
if (src instanceof JButton) {
JButton btn = (JButton) src;
boolean showSelected = false;
String altText;
if (btn == btnShow) {
showSelected = btnShow.getText() == "show";
altText = showSelected ? "hide" : "show";
btnShow.setText(altText);
}
relayout(showSelected);
}
}
private void relayout(boolean showSelected) {
int x = pnlBody.getX();
int y = pnlBody.getY();
if (showSelected) {
pnlContainer2.setVisible(true);
pnlBody.setBounds(x, y + 50, 180, 90);
} else {
pnlContainer2.setVisible(false);
pnlBody.setBounds(x, y - 50, 180, 90);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Demo());
}
}
However, no matter which JPanel I apply JScrollPane to, I cannot make my interface adaptive to the hide and show of my JContainer2.
How can I modify it, or what control to use to replace JScrollPane? Any suggestions will be welcome.
And here is my platform information:
java -version
java version "1.8.0_212"
Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)
OS: win10 1909
arch: amd64
I rewrote your code. Explanations appear after it.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
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.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;
public class Demo2 implements ActionListener, Runnable {
private static final String HIDE = "HIDE";
private static final String SHOW = "SHOW";
private JButton button;
private JLabel lbl2;
private JFrame frame;
private JTextField txf2;
#Override
public void run() {
showGui();
}
#Override
public void actionPerformed(ActionEvent event) {
boolean visible;
String text;
String actionCommand = event.getActionCommand();
switch (actionCommand) {
case HIDE:
text = SHOW;
visible = false;
break;
case SHOW:
text = HIDE;
visible = true;
break;
default:
text = "???";
visible = false;
}
button.setText(text);
lbl2.setVisible(visible);
txf2.setVisible(visible);
}
private JPanel createButtonsPanel() {
JPanel buttonsPanel = new JPanel();
button = new JButton(SHOW);
button.addActionListener(this);
buttonsPanel.add(button);
return buttonsPanel;
}
private JScrollPane createForm() {
JPanel form = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
JLabel lbl1 = new JLabel("lbl1");
form.add(lbl1, gbc);
gbc.gridx = 1;
JTextField txf1 = new JTextField(6);
form.add(txf1, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
lbl2 = new JLabel("lbl2");
lbl2.setVisible(false);
form.add(lbl2, gbc);
gbc.gridx = 1;
txf2 = new JTextField(6);
txf2.setVisible(false);
form.add(txf2, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
JLabel lbl3 = new JLabel("lbl3");
form.add(lbl3, gbc);
gbc.gridx = 1;
JTextField txf3 = new JTextField(6);
form.add(txf3, gbc);
return new JScrollPane(form,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
private void showGui() {
frame = new JFrame("Demo");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(createForm(), BorderLayout.CENTER);
frame.add(createButtonsPanel(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
/**
* Start here.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Demo2());
}
}
You should always try to use a layout manager. The code above uses GridBagLayout but there are several other layout managers that are good at handling forms, including GroupLayout and SpringLayout as well as third party layout managers like MiG Layout and FormLayout.
In order to "show" and "hide" the middle row in your form, simply set the visible property to true or false. If the text of the button is SHOW, then when the user clicks on it, I change the button text to HIDE and make lbl2 and txf2 both visible. If the button text is HIDE, then when the user clicks the button I change the text to SHOW and make lbl2 and txf2 not visible.
Because I use a layout manager, it handles resizing the JPanel whenever the contents of the JPanel are changed. When you don't use a layout manager, then you have to write code that handles the resizing and of-course your code does not, hence your problem.
I want to create an input JFrame where the program reads three fields (model, week and plan), and after inserting one line the user can choose to input new values on a different row, this is done pressing a JLabel with a image add icon.
My expectation is to be able to add a new JPanel (called body in the subclass) right under the last one (JPanel lastContent global variable), and to be able to remove or add new ones as the user needs.
Below is my code so far:
package marquesina;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.jdesktop.swingx.HorizontalLayout;
import org.jdesktop.swingx.VerticalLayout;
public class JModificaciones extends Container {
private JPanel lastContent;
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("DEMO");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
JModificaciones mods = new JModificaciones();
frame.setContentPane(mods);
//Display the window.
frame.pack();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(
dim.width / 2 - frame.getSize().width / 2,
dim.height / 2 - frame.getSize().height / 2);
frame.setVisible(true);
});
}
public JModificaciones() {
initComponents();
System.out.println("New Panel Created");
}
private void initComponents() {
JPanel jHeader = new JPanel();
JLabel jLMod = new JLabel();
JLabel jLSem = new JLabel();
JLabel jLPlan = new JLabel();
JPanel jFooter = new JPanel();
JButton jGuardar = new JButton();
JButton jCancelar = new JButton();
setLayout(new VerticalLayout(10));
//HEADER
jHeader.setLayout(new HorizontalLayout());
jLMod.setText("Model");
jHeader.add(jLMod);
jLWeek.setText("Week");
jHeader.add(jLWeek);
jLPlan.setText("Plan");
jHeader.add(jLPlan);
add(jHeader);
//CONTENT
add(new jContent());
//FOOTER
jGuardar.setText("Save");
jFooter.add(jGuardar);
jCancelar.setText("Cancel");
jFooter.add(jCancel);
add(jFooter);
}
public class jContent extends JPanel {
JLabel jAdd = new javax.swing.JLabel();
JLabel jDelete = new javax.swing.JLabel();
public jContent() {
JPanel body = new JPanel(new HorizontalLayout());
JTextField jModel = new JTextField();
JTextField jWeek = new JTextField();
JTextField jPlan = new JTextField();
body.setLayout(new org.jdesktop.swingx.HorizontalLayout());
jModel.setPreferredSize(new java.awt.Dimension(100, 28));
body.add(jModel);
jWeek.setPreferredSize(new java.awt.Dimension(100, 28));
body.add(jWeek);
jPlan.setPreferredSize(new java.awt.Dimension(100, 28));
body.add(jPlan);
jAdd.setIcon(
new javax.swing.ImageIcon(
getClass().getResource("add.png")));
jAdd.addMouseListener(new java.awt.event.MouseAdapter() {
#Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
}
});
body.add(jAdd);
jDelete.setIcon(
new javax.swing.ImageIcon(
getClass().getResource("delete.png")));
jDelete.addMouseListener(new java.awt.event.MouseAdapter() {
#Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
remove(lastContent);
}
});
body.add(jDelete);
add(body);
}
}
}
However I'm not able to add a new JPanel (which I want to create when the user clicks on the jAdd JLabel), I can't come up with a way to reference the JPanel where I want to put my new Components and using just add() or remove() as I do in the above code just reference the MouseListener, not the JPanel created in the sublcass...
when I compile and run my code everything seems to work fine except the JButton does not appear. I'm adding it to a JPanel that is on the frame. I'm new so I might not know what to lookout for here. Thanks!
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
public class TemperatureConverter extends JFrame{
//declarations
private JLabel celJLabel, farJLabel;
private JTextField celJTextField, farJTextField;
private JSlider sliderJSlider;
private JButton closeButton;
private TitledBorder border;
private JPanel topPanel, bottomPanel;
double celsiusDegrees, farenheitDegrees, sliderValue;
DecimalFormat decimalFormat = new DecimalFormat("#.0");
public TemperatureConverter()
{
createUserInterface();
}
public void createUserInterface()
{
//create the JFrame
Container frame = getContentPane();
frame.setBackground(Color.white);
frame.setLayout(null);
border = new TitledBorder("Convert between C & F");
border.setTitleColor(Color.black);
border.setTitleFont(new Font("Default", Font.ITALIC, 12));
border.setTitleJustification(TitledBorder.LEFT);
border.setTitlePosition(TitledBorder.TOP);
topPanel = new JPanel();
topPanel.setBounds(20,10,360,300);
topPanel.setForeground(Color.black);
topPanel.setBackground(Color.white);
topPanel.setLayout(null);
topPanel.setBorder(border);
frame.add(topPanel);
bottomPanel = new JPanel();
bottomPanel.setBounds(20,310,360,50);
bottomPanel.setForeground(Color.black);
bottomPanel.setBackground(Color.white);
bottomPanel.setLayout(null);
frame.add(bottomPanel);
celJLabel = new JLabel();
celJLabel.setBounds(120, 200, 60, 20);
celJLabel.setBackground(Color.white);
celJLabel.setFont(new Font("Default", Font.PLAIN, 12));
celJLabel.setText("Celcius");
celJLabel.setHorizontalAlignment(JLabel.LEFT);
topPanel.add(celJLabel);
farJLabel = new JLabel();
farJLabel.setBounds(120, 220, 60, 20);
farJLabel.setBackground(Color.white);
farJLabel.setFont(new Font("Default", Font.PLAIN, 12));
farJLabel.setText("Faranheit");
farJLabel.setHorizontalAlignment(JLabel.LEFT);
topPanel.add(farJLabel);
celJTextField = new JTextField();
celJTextField.setBounds(195,200, 50, 15);
celJTextField.setFont(new Font("Default", Font.PLAIN, 12));
celJTextField.setHorizontalAlignment(JTextField.CENTER);
celJTextField.setForeground(Color.black);
celJTextField.setBackground(Color.white);
topPanel.add(celJTextField);
farJTextField = new JTextField();
farJTextField.setBounds(195,225, 50, 15);
farJTextField.setFont(new Font("Default", Font.PLAIN, 12));
farJTextField.setHorizontalAlignment(JTextField.CENTER);
farJTextField.setForeground(Color.black);
farJTextField.setBackground(Color.white);
topPanel.add(farJTextField);
sliderJSlider = new JSlider(JSlider.HORIZONTAL, 0,100,0);
sliderJSlider.setBounds(20, 20, 310, 120);
sliderJSlider.setMajorTickSpacing(10);
sliderJSlider.setMinorTickSpacing(5);
sliderJSlider.setPaintTicks(true);
sliderJSlider.setPaintLabels(true);
sliderJSlider.setForeground(Color.black);
sliderJSlider.setBackground(Color.white);
topPanel.add(sliderJSlider);
sliderJSlider.addChangeListener(
new ChangeListener()
{
public void stateChanged(ChangeEvent event)
{
sliderStateChanged(event);
}
}
);
closeButton = new JButton();
closeButton.setBounds(140, 250, 75, 20);
closeButton.setFont(new Font("Default", Font.PLAIN,12));
closeButton.setText("Close");
closeButton.setForeground(Color.black);
closeButton.setBackground(Color.white);
bottomPanel.add(closeButton);
closeButton.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
closeActionPerformed(event);
}
}
);
setTitle("Temperature Converter");
setSize(400,400);
setVisible(true);
}
public static void main(String[] args)
{
TemperatureConverter application = new TemperatureConverter();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void sliderStateChanged(ChangeEvent event)
{
farenheitDegrees = sliderJSlider.getValue();
calculateCelsiusTemperature();
}
public void calculateCelsiusTemperature()
{
celsiusDegrees = (farenheitDegrees - 32)*5.0/9.0;
outputTemps();
}
public void outputTemps()
{
celJTextField.setText(decimalFormat.format(celsiusDegrees));
farJTextField.setText(decimalFormat.format(farenheitDegrees));
}
public void closeActionPerformed(ActionEvent event)
{
TemperatureConverter.this.dispose();
}
}
I'd follow the advice from the comments, use a proper layout manager.
The actual fault, is the placement of the close button within the bottom panel.
closeButton.setBounds(140, 250, 75, 20);
This might be a typo or a misunderstanding of the coordinate system, each new panel has its own private system where (0,0) is the top left of at component. The button is at (140, 250), however bottomPanel is only 360 x 50, so it is outside the visible bounds..
Try changing to
closeButton.setBounds(0, 0, 75, 20);
Your first and major mistake is this: topPanel.setLayout(null);. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
The solution is simple: learn about and how to use the layout managers, and then use them. You can find links to the Swing tutorials including those for the layout managers and other Swing resources here: Swing Info
e.g.,
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;
public class TempConverter extends JPanel {
private static final int PREF_W = 400;
private static final int GAP = 5;
private JTextField celJTextField = new JTextField(10);
private JTextField farJTextField = new JTextField(10);
private JSlider sliderJSlider = new JSlider(0, 100, 0);
private JButton closeButton = new JButton("Close");
public TempConverter() {
sliderJSlider.setMajorTickSpacing(10);
sliderJSlider.setMinorTickSpacing(5);
sliderJSlider.setPaintTicks(true);
sliderJSlider.setPaintLabels(true);
JPanel textFieldPanel = new JPanel(new GridBagLayout());
textFieldPanel.add(new JLabel("Celcius:"), createGbc(0, 0));
textFieldPanel.add(celJTextField, createGbc(1, 0));
textFieldPanel.add(new JLabel("Faranheit:"), createGbc(0, 1));
textFieldPanel.add(farJTextField, createGbc(1, 1));
JPanel textFieldWrapperPanel = new JPanel(new GridBagLayout());
textFieldWrapperPanel.add(textFieldPanel);
JPanel conversionPanel = new JPanel(new BorderLayout());
conversionPanel.setBorder(BorderFactory.createTitledBorder("Foo"));
conversionPanel.setLayout(new BorderLayout());
conversionPanel.add(sliderJSlider, BorderLayout.PAGE_START);
conversionPanel.add(textFieldWrapperPanel, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
bottomPanel.add(closeButton);
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout());
add(conversionPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(GAP, GAP, GAP, GAP);
return gbc;
}
#Override
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
;
if (isPreferredSizeSet()) {
super.getPreferredSize();
}
int prefW = Math.max(PREF_W, superSize.width);
return new Dimension(prefW, superSize.height);
}
private static void createAndShowGui() {
TempConverter mainPanel = new TempConverter();
JFrame frame = new JFrame("TempConverter");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Now you might say that this looks more complicated, and perhaps it is, but what happens when you want to add another JTextField and JLabel to represent the Kelvin temperature scale? For your GUI, you'll need to resize the GUI and recalculate the position of any component that may be effected by adding the new components. For my GUI, you just need to add a few new lines, and the chance of the changes causing a bug in my code is much smaller than that of your changes. e.g. please note the changes below just require 3 lines of code. Everything else remains the same:
public class TempConverter extends JPanel {
private static final int PREF_W = 400;
private static final int GAP = 5;
private JTextField celJTextField = new JTextField(10);
private JTextField farJTextField = new JTextField(10);
private JTextField KelvinJTextField = new JTextField(10); // !!! Added
private JSlider sliderJSlider = new JSlider(0, 100, 0);
private JButton closeButton = new JButton("Close");
public TempConverter() {
sliderJSlider.setMajorTickSpacing(10);
sliderJSlider.setMinorTickSpacing(5);
sliderJSlider.setPaintTicks(true);
sliderJSlider.setPaintLabels(true);
JPanel textFieldPanel = new JPanel(new GridBagLayout());
textFieldPanel.add(new JLabel("Celcius:"), createGbc(0, 0));
textFieldPanel.add(celJTextField, createGbc(1, 0));
textFieldPanel.add(new JLabel("Faranheit:"), createGbc(0, 1));
textFieldPanel.add(farJTextField, createGbc(1, 1));
// !!! added
textFieldPanel.add(new JLabel("Kelvin:"), createGbc(0, 2));
textFieldPanel.add(KelvinJTextField, createGbc(1, 2));
I am currently trying to make a little app using a jframe that has multiple jpanels. I have a couple questions about this.
There has to be a cleaner way of making an app with 16 different panels than having it all inside one class. What are some other options.
Currently I only have 3 panels. I haven't gone any further because 2 of the panels aren't reflecting my changes. They are the two panels I call using
removeAll();
add();
revalidate();
repaint();
What would be causing the other panels I am calling to be blank?
Here is a look at what I have, any advice would be great. Thanks
public class Jframetest extends JFrame {
private JPanel Home;
private JPanel masslog;
private JPanel DEH;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Jframetest frame = new Jframetest();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Jframetest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setBounds(100, 100, 618, 373);
Home = new JPanel();
masslog = new JPanel();
DEH = new JPanel();
Home.setBackground(new Color(255, 250, 250));
Home.setBorder(new LineBorder(Color.DARK_GRAY, 1, true));
DEH.setBackground(new Color(255, 250, 250));
DEH.setBorder(new LineBorder(Color.DARK_GRAY, 1, true));
masslog.setBackground(new Color(255, 250, 250));
masslog.setBorder(new LineBorder(Color.DARK_GRAY, 1, true));
setContentPane(Home);
Home.setLayout(null);
JButton dehbutton = new JButton("Sign in");
dehbutton.setFont(new Font("Tahoma", Font.PLAIN, 14));
dehbutton.setForeground(new Color(0, 0, 0));
dehbutton.setBackground(UIManager.getColor("Menu.selectionBackground"));
DEH.add(dehbutton);
JButton btnNewButton = new JButton("Data Entry login");
btnNewButton.setFont(new Font("Tahoma", Font.PLAIN, 14));
btnNewButton.setForeground(new Color(0, 0, 0));
btnNewButton.setBackground(UIManager.getColor("Menu.selectionBackground"));
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Home.removeAll();
Home.add(DEH);
Home.revalidate();
Home.repaint();
// JOptionPane.showMessageDialog(null, "Username/Password incorrect");
}
});
btnNewButton.setBounds(44, 214, 204, 61);
Home.add(btnNewButton);
final JButton button = new JButton("Manager and Associate login");
button.setFont(new Font("Tahoma", Font.PLAIN, 14));
button.setBackground(UIManager.getColor("EditorPane.selectionBackground"));
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Home.removeAll();
Home.add(masslog);
Home.revalidate();
Home.repaint();
}
});
button.setBounds(340, 214, 204, 61);
Home.add(button);
JTextPane txtpnEmployeeLogin = new JTextPane();
txtpnEmployeeLogin.setForeground(Color.DARK_GRAY);
txtpnEmployeeLogin.setBackground(Color.WHITE);
txtpnEmployeeLogin.setFont(new Font("Tahoma", Font.PLAIN, 34));
txtpnEmployeeLogin.setText("Employee Login");
txtpnEmployeeLogin.setBounds(181, 123, 260, 52);
Home.add(txtpnEmployeeLogin);
JLabel lblNewLabel = new JLabel("New label");
lblNewLabel.setIcon(new ImageIcon("C:\\Users\\Will and April\\Downloads\\your-logo-here.jpg"));
lblNewLabel.setBounds(427, 11, 165, 67);
Home.add(lblNewLabel);
}
}
Your mistake is using a null layout, revalidate, invalidate and validate will no longer have any significant meaning, because they are related to supporting the layout management API.
Because you've removed the layout manager, you panels no longer have anything to tell them what size or location that they should appear at, meaning when you add a new component, it has a size of 0x0 and position of 0x0
Update with example
There are many reasons why you should take advantage of the layout manager API, including automatic handling of differences between how fonts are rendered on different systems, dynamic and resizable layouts, differences in screen resolution and DPI to name a few.
It will also encourage you to separate your UI into areas of responsibility instead of trying to dump your entire UI code into a single class (yes, I've seen this done, yes, I've spent most of my career cleaning up after people who do this...)
This example makes use of CardLayout and GridBagLayout, but you should take the time to become farmiluar with the some of the others avaiable in the default JDK
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
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.JTextField;
import javax.swing.border.EmptyBorder;
public class FrameTest extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
FrameTest frame = new FrameTest();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public FrameTest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final CardLayout layout = new CardLayout();
setLayout(layout);
LoginPane loginPane = new LoginPane();
add(loginPane, "login");
add(new NewLoginPane(), "newLogin");
add(new ManagerLoginPane(), "managerLogin");
loginPane.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
System.out.println(command);
if ("new".equals(command)) {
layout.show(getContentPane(), "newLogin");
} else if ("manager".equals(command)) {
layout.show(getContentPane(), "managerLogin");
}
}
});
layout.show(getContentPane(), "layout");
pack();
setLocationRelativeTo(null);
}
public class LoginPane extends JPanel {
private JTextField userName;
private JButton newButton;
private JButton managerButton;
public LoginPane() {
setBorder(new EmptyBorder(20, 20, 20, 20));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
gbc.weightx = 1;
gbc.insets = new Insets(10, 10, 10, 10);
userName = new JTextField(10);
userName.setFont(new Font("Tahoma", Font.PLAIN, 34));
add(userName, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 1;
gbc.weightx = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
newButton = new JButton("Sign in");
newButton.setActionCommand("new");
managerButton = new JButton("Manager and Associate login");
managerButton.setActionCommand("manager");
add(newButton, gbc);
gbc.gridx++;
add(managerButton, gbc);
}
public void addActionListener(ActionListener listener) {
newButton.addActionListener(listener);
managerButton.addActionListener(listener);
}
public void remveActionListener(ActionListener listener) {
newButton.removeActionListener(listener);
managerButton.removeActionListener(listener);
}
public String getUserName() {
return userName.getText();
}
}
public class NewLoginPane extends JPanel {
public NewLoginPane() {
setLayout(new GridBagLayout());
add(new JLabel("New Login"));
}
}
public class ManagerLoginPane extends JPanel {
public ManagerLoginPane() {
setLayout(new GridBagLayout());
add(new JLabel("Welcome overlord"));
}
}
}
There has to be a cleaner way of making an app with 16 different panels than having it all inside one class. What are some other options.
You are free to create and use as many classes as need be. So if a JPanel holds a complex bit of GUI that you may wish to re-use elsewhere, or that has its own specific and separate functionality, by all means put the code in its own class.
Currently I only have 3 panels. I haven't gone any further because 2 of the panels aren't reflecting my changes. They are the two panels I call using
removeAll();
add();
revalidate();
repaint();
Smells like you're trying to re-invent the CardLayout. Why re-invent it when you can just use it?
And yes, everything MadProgrammer says about null layout is true. You should avoid using it.
Oh, the CardLayout may work for you. I thought about using a JTabbedPane. Here are my thoughts in a code example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
public class TabbedPaneDemo extends JFrame {
public TabbedPaneDemo() {
// set the layout of the frame to all the addition of all components
setLayout(new FlowLayout());
// create a tabbed pane
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setPreferredSize(new Dimension(500,500));
add(tabbedPane);
// create three panels to be added to this frame
JPanel redPanel = new JPanel();
JPanel greenPanel = new JPanel();
JPanel bluePanel = new JPanel();
// set the colors of the panels
redPanel.setBackground(Color.RED);
greenPanel.setBackground(Color.GREEN);
bluePanel.setBackground(Color.BLUE);
// set the preferred size of each panel
redPanel.setPreferredSize(new Dimension(150,150));
greenPanel.setPreferredSize(new Dimension(150,150));
bluePanel.setPreferredSize(new Dimension(150,150));
// add the panels to the tabbed pane
tabbedPane.addTab("Red Panel", redPanel);
tabbedPane.addTab("Green Panel", greenPanel);
tabbedPane.addTab("Blue Panel", bluePanel);
// finish initializing this window
setSize(500,500); // size the window to fit its components (i.e. panels in this case)
setLocationRelativeTo(null); // center this window
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // exit application when this window is closed
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TabbedPaneDemo().setVisible(true);
}
});
}
}
And for your other question about having 16 panels in one class:
You can have panels within panel to organize things.
You can subclass JPanel and put the subclasses in their own .java files.
You can send me an email if I can be of further assistance. kaydell#yahoo.com (I like helping people with their programming and I learn from it too.)