I fixed up the code and updated, but now I do not know where to place the constructor:
private JPanel panel;
public RollButton(JPanel panel){
this.panel = panel;
}
I looked at some examples of where to place the constructor and it seems like it is placed around my RollButton class, but I have tried to put it in multiple times and in multiple places but I cannot seem to get it right.
Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.Random;
public class DiceRollGUI {
public static JLabel label;
public static JFrame frame;
public static JPanel panel;
private static JButton button;
private static JButton buttonRollDie;
private static JLabel diceRoll;
public static void main (String[] args) {
JFrame frame = new JFrame("Dice Roll GUI");
JPanel contentPanel = new JPanel(new GridLayout(0,2,5,10));
button = new JButton("Roll");;
frame.setVisible(true);
frame.setResizable(false);
frame.setSize(750, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.setActionCommand("Roll");
button.addActionListener(new RollButton());
panel.setPreferredSize(new Dimension(750, 500));
frame.setContentPane(panel);
frame.pack();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.add(button);
button.setAlignmentX(Component.CENTER_ALIGNMENT);
}
private static class RollButton implements ActionListener {
public void actionPerformed(ActionEvent event){
int roll = (int) (Math.round((Math.random() * 5) + 1));
ImageIcon dice = null;
if(roll == 1){
dice = new ImageIcon("DiceRollGUI Pictures/dice_face_1.png");
}
else if(roll == 2){
dice = new ImageIcon("DiceRollGUI Pictures/die_face_2.png");
}
else if(roll == 3){
dice = new ImageIcon("DiceRollGUI Pictures/die_face_3.png");
}
else if(roll == 4){
dice = new ImageIcon("DiceRollGUI Pictures/die_face_4.png");
}
else if(roll == 5){
dice = new ImageIcon("DiceRollGUI Pictures/die_face_5.png");
}
else if(roll == 6){
dice = new ImageIcon("DiceRollGUI Pictures/die_face_6.png");;
}
JLabel diceRoll = new JLabel("",dice, JLabel.CENTER);
panel.add(diceRoll);
panel.revalidate();
}
}
}
Edit: It's a NullPointerException or as some of us say, an NPE.
Key here is to learn how to fix most NPE's when you get them:
Find the line that throws the NPE. The exceptions stacktrace will tell you, for example yours is telling you at DiceRollGUI$RollButton.actionPerformed(DiceRollGUI.java:40) meaning at line 40 in your DiceRollGUI.java class.
Check to see if you're calling any methods on variables on that line or if you are "dereferencing" a variable in some other way.
Check to see if any of the variables on that line are null (a debugger can help, or failing that, a couple of println's before the line of interest can help).
Then trace back in your program to see why that variable is null when you thought that it wasn't.
In your case your JLabel, label, is null because, well because you never initialize it. You need to assign it a new JLabel object before trying to use it.
Also, as I mentioned in my comment, in the future, if you ask questions about exceptions or errors, always post the full exception or error message, and indicate for us which line is causing the problem. The error message will usually tell you exactly which line it is, but you will have to translate the line numbers to the actual line in your program.
This is a simple NullPointerException, which should have being fixed by checking the nearest line to the cause of the exception within your source code and/or debugging the program
When I ran the program, I got the following exception...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at dicerollgui.DiceRollGUI$RollButton.actionPerformed(DiceRollGUI.java:55)
Which pointed me to label.setText(" "); within the actionPerformed method...
if(rolldie.equals("Roll")) {
label.setText(" ");
This automatically suggested to me that label has not yet being initialised (and therefore is null).
Updated...
This...
JFrame frame = new JFrame();
frame.add(dice6);
Seems very weird to me. Basically on each dice roll, you are creating a new JLabel and a new JFrame but you're not showing the resulting frame...
Instead, you should have a single JLabel which maintains the value of the last roll and simply use either setText or setIcon to change it's state based on your requirements.
Updated with example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DiceRoll {
public static void main(String[] args) {
new DiceRoll();
}
public DiceRoll() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new DicePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DicePane extends JPanel {
private JLabel diceRoll;
private JButton rollDice;
public DicePane() {
setLayout(new BorderLayout());
diceRoll = new JLabel();
Font font = diceRoll.getFont();
diceRoll.setFont(font.deriveFont(128f));
diceRoll.setHorizontalAlignment(JLabel.CENTER);
add(diceRoll);
rollDice = new JButton("Papper needs a new pair of shoes");
rollDice.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int roll = (int) (Math.round((Math.random() * 5) + 1));
diceRoll.setText(Integer.toString(roll));
}
});
add(rollDice, BorderLayout.SOUTH);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Related
I'm working on a simple GUI. On Button press i want to increase/decrease a variable and update the corresponding JLabel.
class JFrameSetUp
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class JFrameSetUp extends JFrame implements ActionListener {
private int RecHeight = 0;
private int RecWidth = 0;
//Here Buttons
JButton HeightIncrease = new JButton("+");
JButton HeightDecrease = new JButton("-");
JLabel height = new JLabel(Integer.toString(RecHeight));
JLabel width = new JLabel(Integer.toString(RecWidth));
GridLayout gridLayout = new GridLayout(2, 4);
public JFrameSetUp(){
}
public void addComponentsToPane(final Container pane){
//Create GridPanel and set Layout
JPanel grid = new JPanel();
grid.setLayout(gridLayout);
//Create buttondrawPanel and set Layout
JPanel buttondraw = new JPanel();
buttondraw.setLayout(new GridLayout(2, 0));
//Adding Components to GridPanel
//Adding Layouts to pane
pane.add(grid, BorderLayout.NORTH);
pane.add(new JSeparator(), BorderLayout.CENTER);
pane.add(buttondraw, BorderLayout.SOUTH);
}
#Override
public void actionPerformed(ActionEvent e) {
//Setting up ActionListener to Buttons
if (e.getSource() == this.HeightDecrease) {
RecHeight -= 1;
height.setText(Integer.toString(RecHeight));
} else if (e.getSource() == this.HeightIncrease) {
RecHeight += 1;
height.setText(Integer.toString(RecHeight));
}
}
}
Class with MainMethod
import javax.swing.JFrame;
public class Program {
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrameSetUp frame = new JFrameSetUp();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
frame.addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
I'm aware, that's kind a newbish question. I think I'm wrong with my Code Structure. Any help is appreciated.
Thanks in advance.
You never register any ActionListeners to the buttons...
HeightIncrease.addActionListener(this);
HeightDecrease.addActionListener(this);
You also never add the buttons to the GUI
buttondraw.add(HeightIncrease);
buttondraw.add(HeightDecrease);
You also never add the labels to the GUI either...
grid.add(height);
grid.add(width);
I reworked the code, because your example was messing with my mind, hope you don't mind...
It's conceptually the same idea, just done slightly more efficently
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
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.JSeparator;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int recHeight = 0;
private int recWidth = 0;
//Here Buttons
JButton heightIncrease = new JButton("+");
JButton heightDecrease = new JButton("-");
JLabel height = new JLabel(Integer.toString(recHeight));
JLabel width = new JLabel(Integer.toString(recWidth));
GridLayout gridLayout = new GridLayout(2, 4);
public TestPane() {
setLayout(new BorderLayout());
//Create GridPanel and set Layout
JPanel grid = new JPanel();
grid.setLayout(gridLayout);
grid.add(height);
grid.add(width);
//Create buttondrawPanel and set Layout
JPanel buttondraw = new JPanel();
buttondraw.setLayout(new GridLayout(2, 0));
heightIncrease.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
recHeight += 1;
height.setText(Integer.toString(recHeight));
}
});
heightDecrease.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
recHeight -= 1;
height.setText(Integer.toString(recHeight));
}
});
buttondraw.add(heightIncrease);
buttondraw.add(heightDecrease);
//Adding Components to GridPanel
//Adding Layouts to pane
add(grid, BorderLayout.NORTH);
add(new JSeparator(), BorderLayout.CENTER);
add(buttondraw, BorderLayout.SOUTH);
}
}
}
I would encourage you to spend some time having a look at How to Use Buttons, Check Boxes, and Radio Buttons and How to Write an Action Listeners for more details
After changing the value call
frame.repaint();
Good to see you learning Java! A few things I should point out.
Firstly, your variable names are good, but they don't follow the Java naming convention. Even though it seems small, it's just good practice to follow.
Of course, your actual problem; the action listener you've implemented is on the JFrame. (See how you extend JFrame and implement ActionListener?) This ActionListener should be on the button. You'll can do this a few ways.
Method 1: By adding it inline with your code
JButton heightButton = new JButton("Increase Height");
heightButton.addActionListener(new ActionListener(){
#Override
public void run(){
//run method here
}
});
Method 2: Create a class which implements ActionListener
class ButtonListener implements ActionListener{
#Override
public void run(){
//actionListener code here
}
}
And then instantiate an object of this type and add it directly to your code.
ActionListner buttonListener = new ButtonListener(); //or ButtonListener buttonListener = new ButtonListener();
JButton heightButton = new JButton("Increase Height");
heightButton.addActionListener(buttonListener);
Of course, as in MadProgrammers answer, don't forget to add the labels and such to your JFrame or JPanel. Good luck learning Java!
I bet that your program just shows nothing, isn't it? That's because in addComponentsToPane method, you didn't add any component but empty JPanels. After the comment //Adding Components to GridPanel, you should:
buttondraw.add(HeightIncrease);
buttondraw.add(HeightDecrease);
grid.add(height);
grid.add(width);
Then, to listen to button event, you should also add :
HeightIncrease.addActionListener(this);
HeightDecrease.addActionListener(this);
"this" is because your frame JFrameSetUp implements ActionListener, so when either bootton is clicked the method actionPerformed is invoked.
As JLabel.setText method will repaint itself and consequently its component hierarchi is repainted as well, you haven't to do anything othr.
I have recently learned how to use the timer java class and have created a program which counts down using a timer and displays this countdown using a label. My issue is that the program counts down by two instead of 1.
package test;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.Timer;
import static javax.swing.UIManager.get;
public class Test extends JFrame implements ActionListener{
//Declare Global Variable
int timerValGlobal = 25;
//Define components to add
JButton startTimer = new JButton("Start Timer");
JButton exitButton = new JButton("Exit");
JLabel time = new JLabel();
Timer timer = new Timer(1000, this);
//Define panels
JPanel pane = new JPanel();
JPanel exitPane = new JPanel();
public Test(){
setExtendedState(JFrame.MAXIMIZED_BOTH);
setUndecorated(true);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//Add buttons to panels
pane.add(startTimer);
pane.add(time);
exitPane.add(exitButton);
//Add panels to form;
add(pane, BorderLayout.NORTH);
add(exitPane, BorderLayout.SOUTH);
//Add ActionListeners to Buttons
startTimer.addActionListener(this);
exitButton.addActionListener(this);
timer.addActionListener(this);
}
public static void main(String[] args) {
Test t = new Test();
}
public void actionPerformed(ActionEvent evt){
Object source = evt.getSource();
if(source == exitButton){
System.exit(0);
}
else if(source == startTimer){
timer.start();
}
else if (source == timer){
time.setText(String.valueOf(timerValGlobal));
timerValGlobal = timerValGlobal - 1;
if(timerValGlobal == 0){
timer.stop();
timerValGlobal = 25;
}
}
}
}
This is certainly hard bug to notice! (at least for me :D)
When you create the timer, you did this, right?
Timer timer = new Timer(1000, this);
Why do you write the word this in that piece of code? You're saying that this should be used as an action listener for the timer so that each second, one of the methods in the class will be called. Right?
Now, here's where it goes wrong. In the constructor, you set this as the action listener again!
public Test(){
setExtendedState(JFrame.MAXIMIZED_BOTH);
setUndecorated(true);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//Add buttons to panels
pane.add(startTimer);
pane.add(time);
exitPane.add(exitButton);
//Add panels to form;
add(pane, BorderLayout.NORTH);
add(exitPane, BorderLayout.SOUTH);
//Add ActionListeners to Buttons
startTimer.addActionListener(this);
exitButton.addActionListener(this);
// LOOK! THIS LINE!
// VVVVVVVVVVVVVVV
timer.addActionListener(this);
}
You even wrote comments that says the following block of code is used to add action listeners to the buttons!
Because of the two identical action listeners, the actionPerformed method is called twice a second, hence the output!
Just remove the line that adds a second action listener!
Side note, you should create your frame on the Event Queue like this:
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
Or this, in Java 8:
public static void main(String[] args) {
EventQueue.invokeLater(Test::new);
}
Previously I have asked a question about this program and I fixed it with you people. Now I have created new panel on the first panel which is containing the game of shapes. So I tried to set JButton on the new panel. But I cannot change the location of Jbuttons.
I am trying to set center of new panel.I have tried already FLowLayout(), BorderLayout() and setBounds(); Something is going wrong.
Previous questions; How to move JFrame shape
public class myshapestry extends JFrame implements ActionListener {
JFrame frame=new JFrame("Deneme");
Startthegame panelstart= new Startthegame();
Container l ;
JLabel statusbar = new JLabel("default");
static JButton start;
static JButton exit;
myshapestry() {
l=this.getContentPane();
this.setLayout(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.add(panelstart);
frame.add(statusbar, BorderLayout.SOUTH);
frame.setVisible(true);
frame.setSize(getPreferredSize());
start = new JButton("Start");
exit = new JButton("Exit");
panelstart.add(start);
panelstart.add(exit);
}
public Dimension getPreferredSize() {
return new Dimension(500,600);
}
public static void main (String args[]){
myshapestry tr=new myshapestry();
tr.setTitle("Game of Shapes");
}
public class Startthegame extends JPanel {
}
}
You're extending from JFrame, but creating a new instance of JFrame within the class and interacting with both, which is just confusing the issues. Start by getting rid of extends JFrame, you're not adding any new functionality to the class and it's just locking you into a single use case
static is not your friend and you should avoid using it where possible. In this case, you can move the buttons to the Startthegame. This is basic OO principle of isolation responsibility to units of work.
To get the buttons to center horizontally and vertically within the container, you can use a GridBagLayout
public class Startthegame extends JPanel {
private JButton start;
private JButton exit;
public Startthegame() {
setLayout(new GridBagLayout());
start = new JButton("Start");
exit = new JButton("Exit");
add(start);
add(exit);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 600);
}
}
You should also call setVisible AFTER you've established the basic UI, otherwise you could end up within components not been displayed
For example...
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MyShapesTry {
JFrame frame = new JFrame("Deneme");
Startthegame panelstart = new Startthegame();
Container l;
JLabel statusbar = new JLabel("default");
public MyShapesTry() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panelstart);
frame.add(statusbar, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
MyShapesTry tr = new MyShapesTry();
}
});
}
}
I have the following code to get 2 input from user through JCombo box, then I return the value s of the obtained input to the calling function but the problem is that this code displays the frame to obtain user input but before user can press the 'Ok' button it returns the null value to the calling function.I am looking to halt the code in this method till user presses 'Ok' button.
Please suggest something.
package io;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Insets;
import java.io.FileNotFoundException;
public class SrcAndTargLangInput implements ActionListener {
public static JFrame frame;
public static JComboBox sourcLang;
public static JComboBox targLang;
public static JLabel setSrcLang;
public static JLabel setTargLang;
public static JButton ok;
static String[] lang=new String[2];
public SrcAndTargLangInput(){
ok = new JButton("Ok");
ok.setBounds(150,150,100,50);
frame = new JFrame();
frame.getContentPane().setLayout(null);
frame.getContentPane().add(ok);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Insets ins = frame.getInsets();
frame.setSize(400+ins.left+ins.right, 200+ins.bottom+ins.top);
setSrcLang=new JLabel("Source Language");
frame.getContentPane().add(setSrcLang);
setSrcLang.setBounds(50, 50, 100, 40);
setTargLang=new JLabel("Target Language");
frame.getContentPane().add(setTargLang);
setTargLang.setBounds(50, 100, 100, 40);
String[] srcLangList={"English","Spanish","French"};
sourcLang = new JComboBox(srcLangList);
frame.getContentPane().add(sourcLang);
sourcLang.setBounds(250,50,100,40);
String[] targLangList={"English","Spanish","French"};
targLang = new JComboBox(targLangList);
frame.getContentPane().add(targLang);
targLang.setBounds(250,100,100,40);
frame.setVisible(true);
ok.addActionListener(this);
}
public static String[] langInfo(){
SrcAndTargLangInput ob = new SrcAndTargLangInput();
return lang;
}
public void actionPerformed(ActionEvent e){
lang[0]=(sourcLang.getSelectedItem().toString());
lang[1]=(targLang.getSelectedItem().toString());
frame.setVisible(false);
}
}
The calling function is :
String[] lg = new String[2];
lg = io.SrcAndTargLangInput.langInfo();
System.out.println(lg[0]);
System.out.println(lg[1]);
In your code you can add a boolean variable with a default value as false.
In the actionPerformed method set that value to true. Update your logInfo method to make the thread sleep till no action is performed. Look at the code below.
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Insets;
import java.io.FileNotFoundException;
public class SrcAndTargLangInput implements ActionListener {
public static JFrame frame;
public static JComboBox sourcLang;
public static JComboBox targLang;
public static JLabel setSrcLang;
public static JLabel setTargLang;
public static JButton ok;
static String[] lang=new String[2];
boolean actionPerformed = false;
public SrcAndTargLangInput(){
ok = new JButton("Ok");
ok.setBounds(150,150,100,50);
frame = new JFrame();
frame.getContentPane().setLayout(null);
frame.getContentPane().add(ok);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Insets ins = frame.getInsets();
frame.setSize(400+ins.left+ins.right, 200+ins.bottom+ins.top);
setSrcLang=new JLabel("Source Language");
frame.getContentPane().add(setSrcLang);
setSrcLang.setBounds(50, 50, 100, 40);
setTargLang=new JLabel("Target Language");
frame.getContentPane().add(setTargLang);
setTargLang.setBounds(50, 100, 100, 40);
String[] srcLangList={"English","Spanish","French"};
sourcLang = new JComboBox(srcLangList);
frame.getContentPane().add(sourcLang);
sourcLang.setBounds(250,50,100,40);
String[] targLangList={"English","Spanish","French"};
targLang = new JComboBox(targLangList);
frame.getContentPane().add(targLang);
targLang.setBounds(250,100,100,40);
frame.setVisible(true);
ok.addActionListener(this);
}
public static String[] langInfo() throws InterruptedException{
SrcAndTargLangInput ob = new SrcAndTargLangInput();
while(!ob.actionPerformed) {
Thread.sleep(1000);
}
return lang;
}
public void actionPerformed(ActionEvent e){
lang[0]=(sourcLang.getSelectedItem().toString());
lang[1]=(targLang.getSelectedItem().toString());
actionPerformed = true;
frame.setVisible(false);
Thread.currentThread().interrupt();
}
}
Based on these lines:
String[] lg = new String[2];
lg = io.SrcAndTargLangInput.langInfo();
The problem is your SrcAndTargLangInput class uses a JFrame to ask the user for the input. Having said this, JFrame is not modal and thus it doesn't block the current thread waiting for an input as you wish. You have to use a modal JDialog or JOptionPane(which displays a modal dialog) instead in order to wait until users confirm their input.
Take a look to these topics:
The Use of Multiple JFrames, Good/Bad Practice?
How to Use Modality in Dialogs
How to Make Dialogs
Off-topic
As many developers have already said, Swing is designed to be used with Layout Managers and you should avoid methods such as setBounds(), setLocation() or setSize(). You may want to take a look to these topics too:
Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
Nested Layout Example
Providing white space in a Swing GUI
Example (using JOptionPane)
Note the text field's text doesn't change until you confirm your input.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Demo {
private void createAndShowGui() {
final JTextField textField = new JTextField(10);
textField.setEditable(false);
JButton button = new JButton("Show dialog");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JComboBox languagesComboBox = new JComboBox(new Object[]{"English","Spanish","French"});
JPanel dialogPanel = new JPanel();
dialogPanel.add(new JLabel("Please select an option:"));
dialogPanel.add(languagesComboBox);
int option = JOptionPane.showConfirmDialog(null, dialogPanel, "Select an input"
, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if(option == JOptionPane.OK_OPTION) {
String selectedInput = (String)languagesComboBox.getSelectedItem();
textField.setText(selectedInput);
}
}
});
JPanel content = new JPanel();
content.add(new JLabel("User input:"));
content.add(textField);
content.add(button);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().createAndShowGui();
}
});
}
}
so I have a frame 1 and frame 2 in the frame 1 by having 4 and has 1 JButton JTextField at 4 JTextField a user to input an integer value .. after the user input, the user presses a JButton and JFrame will feature 2 ..
and in the second frame I have 1 JTextArea which will print out a value that a user input
so how to send values from frame 1 to frame 2?
actually in this project I've given constructor in which I made into a class and in Jframe1 "coba.java" I make new objeck with this code:
coba ar = new coba();
in a Jframe1 I have a method in which DDA has a code:
double X0 = Double.parseDouble (x0.getText ());
double X1 = Double.parseDouble (x1.getText ());
double Y0 = Double.parseDouble (y0.getText ());
double Y1 = Double.parseDouble (y1.getText ());
int no = 1;
ar.X0 = X0;
ar.X1 = X1;
ar.Y0 = Y0;
ar.Y1 = Y1;
You can make a thread that can check some static variables for changes and update the frames accordingly. For example somewhere after showing the two frames:
new Thread(new Runnable(){
public void run(){
try{
while(true){
if(coba.HASNEWVALUE){
updateFrame(); // some function that does the updating and communicating
coba.HASNEWVALUE = false;
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}).start();
Whenever you want to pass a new value, set the appropriate values and set coba.HASNEWVALUE to true, this way your frame will fetch the required update automatically through the updateFrame() function everytime coba.HASNEWVALUE is TRUE.
Basically, Frame 1 will need a reference to Frame 2 either directly or indirectly via some kind of observer implementation...
This way, all you need to do is provide some kind of method in Frame 2 that will allow you to pass the information you need to it so it can update the text area in question.
Personally, I prefer to use interfaces for this, as it prevents the caller from messing with things it shouldn't
Oh, and you might also want to have a read through The Use of Multiple JFrames: Good or Bad Practice?
For example...
The NotePad interface prevents SecretaryPane from making changes to the underlying implementation, because the only method it actually knows about is the addNote method
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CrossCalling {
public static void main(String[] args) {
new CrossCalling();
}
public CrossCalling() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
NotePadPane notePadPane = new NotePadPane();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SecretaryPane(notePadPane));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
JFrame noteFrame = new JFrame("Testing");
noteFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
noteFrame.setLayout(new BorderLayout());
noteFrame.add(notePadPane);
noteFrame.pack();
noteFrame.setLocation(frame.getX(), frame.getY() + frame.getHeight());
noteFrame.setVisible(true);
}
});
}
public interface NotePad {
public void addNote(String note);
}
public class SecretaryPane extends JPanel {
private NotePad notePad;
public SecretaryPane(NotePad pad) {
this.notePad = pad;
setLayout(new GridBagLayout());
JButton btn = new JButton("Make note");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pad.addNote(DateFormat.getTimeInstance().format(new Date()));
}
});
add(btn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class NotePadPane extends JPanel implements NotePad {
private JTextArea ta;
public NotePadPane() {
setLayout(new BorderLayout());
ta = new JTextArea(10, 20);
add(new JScrollPane(ta));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void addNote(String note) {
ta.append(note + "\n");
}
}
}