Java Swing- Panel not appearing in frame - java

I am new to swing and am wondering why my login panel isn't appearing in the frame. I believe it should show on the left side of the frame, is this correct? What needs to be changed to make the panel appear. Thanks.
Here is the GUIFrame code
public class GUIFrame extends JFrame {
private static final long serialVersionUID = 1L;
public GUIFrame(){
Container container = getContentPane();
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension screenDimension = toolkit.getScreenSize();
setSize(screenDimension.width/2, screenDimension.height/2);
setLocation(screenDimension.width/4,screenDimension.height/4);
setLayout(new GridLayout(1,2));
add(new Login(this));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
Here is the panels code:
public class Login extends JPanel {
private JPanel panel = new JPanel();
private JButton cancel = new JButton("Cancel");
private JButton submit = new JButton("Submit");
private JLabel username_label = new JLabel("Username :");
private JLabel password_label = new JLabel("Password :");
private JTextField username_text = new JTextField();
private JPasswordField password_text = new JPasswordField();
private GUIFrame frame;
public Login(GUIFrame frame){
this.frame = frame;
setLayout(new GridLayout(3,2,20,40));
addComponents();
}
public void addComponents(){
panel.add(username_label);
panel.add(username_text);
panel.add(password_label);
panel.add(password_text);
panel.add(cancel);
panel.add(submit);
}
}
Here is the main method which displays the frame:
public class Project {
public static void main(String[] args){
Project project = new Project();
}
public Project() {
//Login login = new Login();
GUIFrame frame = new GUIFrame();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});
}
}

panel.add(username_label);
panel.add(username_text);
panel.add(password_label);
panel.add(password_text);
panel.add(cancel);
panel.add(submit);
You create a separate JPanel and add the component to this panel, but you never add the panel to your Login panel.
Your Login panel already is a JPanel, so there is no need to create another JPanel.
The code should just be:
add(username_label);
add(username_text);
add(password_label);
add(password_text);
add(cancel);
add(submit);
There is also no reason to pass the JFrame as a parameter to your Login class.
Also, you are using the invokeLater() incorrectly. All Swing components should be created on the Event Dispatch Thread (EDT). So you should also include the new GuiFrame() inside the invokeLater().
Generally there is no need to have a separate JFrame class. The logic in your Project class should simply create an instance of the frame and add the Login panel to the frame. In other words don't extend JFrame.

Related

Waiting for an ActionListener actionPerformed (with Timer?)

I am trying to populate a variable from a JFrame and am having significant difficulties trying to get the program to wait for the action performed to occur before continuing. See code below.
JFrame implementation class:
public class Frame extends JFrame implements ActionListener {
static Scanner sc = new Scanner(System.in);
static String s;
static JTextField textfield;
static JButton jButton;
public void showFrame() {
JFrame jf = new JFrame();
textfield = new JTextField("", 10);
jButton = new JButton("Enter");
jButton.addActionListener(new Frame());
JPanel panel = new JPanel();
JLabel jl = new JLabel("Options");
jf.setSize(200, 200);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(panel);
panel.add(jl);
panel.add(textfield);
panel.add(jButton);
}
#Override
public void actionPerformed(ActionEvent arg0) {
s = textfield.getText();
}
public String reportVal(){
return s;
}
}
Main Java File:
Frame frame = new Frame();
frame.showFrame();
Timer t = new Timer(1000, frame);
t.start();
int trials = Integer.parseInt(frame.reportVal());
I want trials to populate with the value from the JFrame, but right now the thread doesn't wait, so it executes all the way through before I can click enter on the frame. I do not know much about swing/awt components (clearly) so I appreciate any help you can provide.

How can I dynamically add these elements to my JFrame?

I separated my GUI/JFrame from my Panel class so that I can keep the Swing components away from the rest of my code. However, I have a button that I would like to update my Frame in real time before I run a method from my Main class, but I can't get it to work. It looks something like (pseudocode):
public class GUI extends JFrame
{
public GUI()
{
//frame setup
Login login = new Login(this);
frame.add(login);
while(login.shouldContinue){login.panel.revalidate()}
//continue
}
}
public class Login
{
Jpanel panel;
Main main;
Frame frame;
boolean shouldContinue;
public Login(Frame frame)
{
this.frame = frame;
this.panel= new JPanel();
this.main = new Main();
//other panel elements
JButton btn1 = new JButton ("Login");
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0){
JLabel label = new JLabel("Logging in");
panel.add(label);
frame.add(panel);
main.login();
panel.remove(label1);
JLabel label2 = new JLabel("Login Successful");
panel.add(label2);
frame.add(panel);
this.shouldContinue=false;
}
}
}
The other elements of the panel display just fine, but when I click the button, nothing happens. How can I make the frame display the updated panel before running main.login()? I tried revalidating/repainting the panel but it didn't work.
You are describing the functionality provided by (J)Dialog.setModal(). But these days, an even easier way to do this is to just use JOptionPane
Login l = new Login();
res = JOptionPane.showConfirmDialog(null, login, "login", JOptionPane.OK_CANCEL_OPTION);
if (res == JOptionPane.OK_OPTION) {
...
}

Why is my text field not appearing?

I have to create a text field, a text area, and two buttons, but I am stuck on the text field because I cant get it to appear when I run my program. My JFrame keeps appearing empty.
public class SentanceBuilder extends JFrame {
private JTextField textField = new JTextField(50);
private JTextArea textArea = new JTextArea(200,200);
private JButton Submit = new JButton();
private JButton Cancel = new JButton();
public SentanceBuilder(){
textField.setVisible(true);
textField.setLocation(50, 50);
this.textField();
this.setSize(400, 300);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public void textField(){
String textContent = textField.getText();
}
}
You never add the textField variable to a container such as a JPanel that is held by the top-level window, such as a JFrame. In fact, in your code, you add nothing to your JFrame!
If this were my GUI, I'd
Create my JTextField
Create a main JPanel to hold my components.
Add it and other components to the main JPanel via the JPanel's add(...) method.
Add the main JPanel to the JFrame's contentPane via the JFrame's add(...) method.
Call pack() and then setVisible(true) on the JFrame, but only after adding all components to it, not before.
Read the Swing tutorials since this beats guessing every time. You can get links to the tutorials at the Swing Tag Info link.
e.g.,
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class MyFoo extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField textField = new JTextField(10);
private JButton button = new JButton("Foo Button");
public MyFoo() {
super("My JFrame");
// so Java will end when GUI is closed
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// code to be called when button is pushed
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO code that runs when button is pushed.
}
});
// panel to hold everything
JPanel mainPanel = new JPanel();
// add all to the panel
mainPanel.add(new JLabel("Text Field:"));
mainPanel.add(textField);
mainPanel.add(button);
// add the panel to the main GUI
add(mainPanel);
}
// start up code
private static void createAndShowGui() {
JFrame mainFrame = new MyFoo();
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
public static void main(String[] args) {
// call start up code in a Swing thread-safe way
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Trying to use GUI, having trouble adding buttons and labels

The assignment is simple, all we need to do is have the code create a window with a red panel with a single button and label. Here is the code thus far as well as the tester class.
I got the label to display on the window, but its in a weird place. I cant get the button to display at all as well getting the background to display as red.
This is where I'm having trouble with the most:
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MyCustomFrame extends JFrame
{
public MyCustomFrame()
{
createComponents();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
private void createComponents()
{
JPanel panel=new createPanel();
button=new JButton("Push Me");
label=new JLabel("This is a label");
add(button);
add(label);
}
private JButton button;
private JLabel label;
final int FRAME_WIDTH = 800;
final int FRAME_HEIGHT = 800;
public void createPanel()
{
JPanel panel=new JPanel();
panel.setBackground(Color.RED);
//button=new JButton("Push Me");
//label=new JLabel("This is a label");
}
public void createFrame()
{
JFrame frame=new JFrame();
add(frame);
frame.setVisible(true);
}
}
And this is the tester class:
import javax.swing.JFrame;
public class MyCustomFrameViewer
{
public static void main(String[] args)
{
MyCustomFrame frame = new MyCustomFrame();
frame.setTitle("My first frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
You create the JPanel, panel, but add nothing to it, and then never add the panel to your JFrame. You should add your components to the JPanel, panel, and then add the panel object to your JFrame.
Note that a JPanel uses FlowLayout by default, and so it will more easily accept multiple other components without special add methods. The JFrame's contentPane uses BorderLayout which is slightly more complicated to use.
Add the panel to the frame instead of the label and button, and add the label and button to the panel...
private void createComponents()
{
JPanel panel=new createPanel();
add(panel);
button=new JButton("Push Me");
label=new JLabel("This is a label");
panel.add(button);
panel.add(label);
}
You may also want to take a look at Initial Threads and make sure you are creating your UI from within the context of the Event Dispatching Thread
Some side notes...
This scares me...
public void createFrame()
{
JFrame frame=new JFrame();
add(frame);
frame.setVisible(true);
}
You're trying to add a frame to a frame, which is an illegal operation in Swing, but thankfully, you're not actually calling it from what I can see.
Instead of using setSize(FRAME_WIDTH, FRAME_HEIGHT);, you may wish to use pack instead.
See also the tips in comments in this example:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
// Don't extend frame, just use an instance
//public class MyCustomFrame extends JFrame {
public class MyCustomFrame {
private JFrame frame;
private JButton button;
private JLabel label;
private JPanel panel;
// better to override the preferred size of the component of interest
final int GAME_WIDTH = 300;
final int GAME_HEIGHT = 100;
public MyCustomFrame() {
createComponents();
// better to override the preferred size of the component of interest
//setSize(GAME_WIDTH, GAME_HEIGHT);
}
private void createComponents() {
// compilation error! createPanel() does not return anything..
//JPanel panel = new createPanel();
createPanel();
// create the frame!
createFrame();
}
private void createPanel() {
// creates a local instance
//JPanel panel = new JPanel();
panel = new JPanel() {
/* override the preferred size of the component of interest */
#Override
public Dimension getPreferredSize() {
return new Dimension(GAME_WIDTH, GAME_HEIGHT);
}
};
panel.setBackground(Color.RED);
button = new JButton("Push Me");
label = new JLabel("This is a label");
panel.add(button);
panel.add(label);
}
private void createFrame() {
// create a local instance of a JFrame that goes out of scope at end
// of method..
//JFrame frame = new JFrame();
frame = new JFrame("My first frame");
// add the panel to the frame!
frame.add(panel);
// better to use DISPOSE_ON_CLOSE
//frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// a good way to position a GUI
frame.setLocationByPlatform(true);
// this was trying to add a JFrame to another JFrame
//add(frame);
frame.pack();
}
public final JFrame getFrame() {
return frame;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
MyCustomFrame myFrame = new MyCustomFrame();
JFrame frame = myFrame.getFrame();
frame.setVisible(true);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}

CardLayout (swing) with action listeners on buttons?

I've been trying to figure out CardLayout with action listeners on button
(so like - starts on a load-up page- and on a button click switches to a different "card"
my code won't even run right now i'm not entirely sure why - most implementations I can find use ItemListeners and Combo Boxes
The basic process I've done is create a master JPanel, but my cards JPanel onto the master JPanel, but my different cards into the cards JPanel, then add the master JPanel to the frame to display...
Also, for one of my cards I only need to display a picture - I previously implemented this by just creating a new pop-up window but It would be nice to be able to switch the frame to show it... I don't know why I can't figure this out
Here's my code:
import java.awt.*;
/**
* Game
* Main class that specifies the frame and widgets of the GUI
*/
public class Game implements Runnable {
public void run(){
final String ON_OPEN = "Welcome!"; //Opening frame
final String GAME = "Play!"; // Game Frame
final String STATS = "Stats"; // Post-Game Stat Frame
final String HELP = "Help"; //tutorial frame
JPanel cards = new JPanel();
JPanel master; // a panel for the card layout
final JFrame frame = new JFrame(ON_OPEN);
frame.setLocation(500,200);
//Create the master layout for the program
master = (JPanel) frame.getContentPane();
master.setLayout(new BorderLayout()); // creating master layout
//Create panel for all the cards in CardLayout
final CardLayout cLay = new CardLayout();
cards.setLayout(cLay);
// all the cards
final JPanel help = new JPanel();
final JPanel stats = new JPanel();
final JPanel game = new JPanel (new BorderLayout());
final JPanel open = new JPanel (new FlowLayout());
// setting up ON_OPEN layout - uses JPanel open
final ImageIcon img = new ImageIcon("Instructions.png", "My Instructions..."); // the image I want shown under HELP card
final JButton info = new JButton("Help");
info.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// cLay.show(help, HELP); // WHAT I NORMALLY SHOULD BE DOING, RATHER JUST MAKE A NEW FRAME FOR THIS THOUGH
// frame.pack();
final JFrame infoFrame = new JFrame("Tutorial");
infoFrame.setLocation(500,50);
JLabel tutorialImg = new JLabel(img);
// int w = img.getIconWidth();
// int h = img.getIconHeight();
//infoFrame.setSize(w, h);
infoFrame.pack();
infoFrame.add(tutorialImg);
infoFrame.setVisible(true);
}
});
open.add(info); // the open-tutorial button
//Add them to the cards JPanel
cards.add(open, ON_OPEN);
cards.add(help, HELP);
cards.add(stats, STATS);
cards.add(game, GAME);
//Add the cards panel to the Master layout panel
master.add(cards);
// This code is all commented out because I'm not sure what I'm doing here...
// frame.add(cards);
// cLay.show(cards, ON_OPEN);
// frame.add(open, BorderLayout.CENTER);
// Main playing area - I want this to be shown in the GAME card...
GridLayout tileGrid = new GridLayout(4,4);
final JPanel grid = new JPanel(tileGrid);
// game.add(grid, BorderLayout.CENTER);
// grid.setLayout(tileGrid);
// frame.add(grid, BorderLayout.CENTER);
// Input - holds typing box
// final JPanel status_panel = new JPanel();
// frame.add(cards, BorderLayout.CENTER);
// frame.add(open, BorderLayout.CENTER);
final JTextField typingArea = new JTextField();
typingArea.setFocusTraversalKeysEnabled(false);
typingArea.setEditable(true);
typingArea.setFocusable(true);
typingArea.requestFocus();
frame.add(typingArea, BorderLayout.SOUTH);
typingArea.addKeyListener(new KeyAdapter() {
public void keyPressed (KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) { // enter key is pressed
String userWord = typingArea.getText().toLowerCase();
typingArea.setText("");
}
}
});
final JLabel status = new JLabel("Running...");
// status_panel.add(status);
// Reset button
final JPanel control_panel = new JPanel();
frame.add(control_panel, BorderLayout.NORTH);
]
// Put the frame on the screen
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Game());
}
}
Problems:
Your code doesn't compile for us since we don't have the JLetterField class.
You're trying to add the JFrame's contentPane back on itself, and causes an exception and doesn't make sense.
Edit 1:
Your latest code shows you putting everything into one very large run() method but in doing so, you loose much and gain nothing.
I suggest getting rid of the Runnable interface, there's no need for it, and creating a true OOP compliant class, one with private fields and public and private methods.
Your actionPerformed method shows no attempt at changing the CardLayout's displayed card.
I suggest that you get rid of the code to show a new window and try to place card swapping code there.
Make your CardLayout and the card-displaying JPanel fields of the class so that other methods can access them and call their methods.
Edit 2:
For example the following code shows the swapping of cards using 3 JButtons. One to get the previous card, one to get the next card, and one to show how to get a specific card (here the 2nd):
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class CardLayoutEg extends JPanel {
private static final String[] CARD_LABELS = { "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine", "ten" };
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private CardLayout cardlayout = new CardLayout();
private JPanel cardHolder = new JPanel(cardlayout);
private Action[] actions = { new ShowPreviousAction(), new ShowNextAction(),
new ShowTwoCardAction() };
public CardLayoutEg() {
for (String cardLabelText : CARD_LABELS) {
JLabel cardLabel = new JLabel(cardLabelText, SwingConstants.CENTER);
cardHolder.add(cardLabel, cardLabelText);
}
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
for (Action action : actions) {
btnPanel.add(new JButton(action));
}
setLayout(new BorderLayout());
add(cardHolder, BorderLayout.CENTER);
add(btnPanel, BorderLayout.SOUTH);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private class ShowPreviousAction extends AbstractAction {
public ShowPreviousAction() {
super("Previous");
}
#Override
public void actionPerformed(ActionEvent e) {
cardlayout.previous(cardHolder);
}
}
private class ShowNextAction extends AbstractAction {
public ShowNextAction() {
super("Next");
}
#Override
public void actionPerformed(ActionEvent e) {
cardlayout.next(cardHolder);
}
}
private class ShowTwoCardAction extends AbstractAction {
public ShowTwoCardAction() {
super("Show Two");
}
#Override
public void actionPerformed(ActionEvent e) {
cardlayout.show(cardHolder, CARD_LABELS[1]);
}
}
private static void createAndShowGui() {
CardLayoutEg mainPanel = new CardLayoutEg();
JFrame frame = new JFrame("CardLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_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();
}
});
}
}

Categories