I am writing a wizard of sorts and would like to switch what is displayed using methods. Every time I run this code I get a null pointer exception.
public class EventDispatch {
public static void main(String [] args){
WizardScreen wiz = new WizardScreen();
new Thread(wiz).start();
wiz.welcomeScreen();
}
}
public class WizardScreen implements Runnable{
protected JFrame wizardFrame;
protected JPanel contentPane;
protected JButton newQuote;
protected JButton openQuote;
protected JLabel title;
GridBagConstraints c;
public WizardScreen(){
wizardFrame = new JFrame();
contentPane = new JPanel(new GridBagLayout());
wizardFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
wizardFrame.setSize(550, 450);
wizardFrame.setResizable(false);
wizardFrame.setLocationRelativeTo(null);
wizardFrame.setTitle("Welcome!");
wizardFrame.setContentPane(contentPane);
wizardFrame.setVisible(true);
}
#Override
public void run() {
System.out.println("Running wizardScreen");
}
public void welcomeScreen(){
title = new JLabel("Welcome to ExSoft Quote Calculator Alpha 1.0");
c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = .5;
contentPane.add(title, c);
wizardFrame.validate();
contentPane.repaint();
}
}
What am I doing wrong?
Take a walk through your code...
First, you create an instance of WizardScreen this initialises
wizardFrame
contentPane
Second, you start a Thread...
Third, you call welcomeScreen on the instance of WizardScreen, this initialises...
title
It then tries to access the gridx property of c...which hasn't yet been initialised...
You should have checked the information that the NullPointerException was giving you...
Exception in thread "main" java.lang.NullPointerException
at eventdispatch.EventDispatch$WizardScreen.welcomeScreen(EventDispatch.java:52)
at eventdispatch.EventDispatch.main(EventDispatch.java:20)
It clear states where the exception occurred, this is invaluable information both to you and us.
Beware, Swing is not thread safe, all interactions and modifications to the UI are expected to occur from within the context of the Event Dispatching Thread. See Concurrency in Swing
FYI:
It's generally advisable to use pack of setSize, which should be done last, right before you call setVisible. Also beware, that using setResizable(false) changes the size of the window...
wizardFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//wizardFrame.setSize(550, 450);
//wizardFrame.setResizable(false);
//wizardFrame.setLocationRelativeTo(null);
wizardFrame.setTitle("Welcome!");
wizardFrame.setContentPane(contentPane);
wizardFrame.setResizable(false);
wizardFrame.pack();
wizardFrame.setLocationRelativeTo(null);
wizardFrame.setVisible(true);
Related
I noticed something that I considered to be strange it this following code:
public class QuestionFour extends JFrame {
private JTextArea txta1;
private JTextField txt1;
private JButton btnSort;
private JButton btnShuffle;
private JButton btnReverse;
private JPanel pnl1;
private JLabel lbl1;
private LinkedList linkedList;
public QuestionFour() {
super();
this.setLocationRelativeTo(null);
this.setSize(500, 200);
this.setVisible(true);
this.setLayout(new FlowLayout());
txt1 = new JTextField(); // 1
lbl1 = new JLabel("Enter a number: "); // 2
this.add(lbl1);
}
public static void main(String args[]) {
QuestionFour ob = new QuestionFour();
}
}
The problem that was occuring was, when I run the code the JLabel does not appear but if I comment the line where typed 1 as a comment, the JLabel appears, which I consider odd since I only instantiate the TextField but don't add it to the JFrame.
Can someone please explain this to me?
Possibly, it's an anomaly caused by invocation of setVisible(true) outside of UI thread. Try this one:
public QuestionFour()
{
setLocationRelativeTo(null);
this.setSize(500, 200);
setLayout(new FlowLayout());
this.txt1 = new JTextField(); // 1
this.lbl1 = new JLabel("Enter a number: "); // 2
this.add(this.lbl1);
javax.swing.SwingUtilities.invokeLater(() -> setVisible(true));
}
Notice: Read/write access to any UI component (such as JTextField etc.) must be done within Event Dispatching Thread (UI thread). SwingUtilities provides you convenient methods. You should invoke setVisible() within EDT, too.
One further problem was that you invoke setVisible(true) at the beginning and then add UI components, belatedly. This represents a "write access" to UI components ("you're adding something into the main panel"). Your class constructor doesn't run within EDT, so in this case you had to encapsulate this.add(this.lbl1) into the method of SwingUtilities. But it's better when you construct your entire UI first and then finally set it visible.
For more information about the Swing library and thread-safety take a look at this: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
I've been working on this project for an assignment and I've been stuck on this problem. I new and don't understand much of the programming jargon so if someone could help explain why my program isn't working that would be great.
The programs purpose is to display a randomly generated matrix of 1's and 0's in a 10x10 layout and have some buttons on the top that have functions. I'm just stock on how to get everything to display.
Thanks in advance.
UPDATE:: Told providing all my code would help
public class Module5 extends JFrame {
private static JTextArea area = new JTextArea();
private static JFrame frame = new JFrame();
private static JPanel general = new JPanel();
private static JPanel buttons = new JPanel();
private static JPanel numbers = new JPanel();
private static JButton button0 = new JButton("Reset to 0");
private static JButton button1 = new JButton("Resset to 1");
private static JButton buttonReset = new JButton("Reset");
private static JButton quit = new JButton("Quit");
public static class Numbers extends JPanel {
public Numbers() {
area.setText(Integer.toString((int) Math.round(Math.random())));
this.add(area);
}
public void Module5(){
numbers.setLayout(new GridLayout(10, 10));
for (int i = 0; i < 100; i++) {
this.add(new Numbers());
}
}
}
public static void main (String[] args) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setVisible(true);
general.setLayout(new BoxLayout(general, BoxLayout.Y_AXIS));
general.add(buttons);
general.add(numbers);
buttons.add(button0);
buttons.add(button1);
buttons.add(buttonReset);
buttons.add(quit);
quit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
}
}
Since this does look like homework I'll give you some pointers but am not going to give you the code.
Move your constructor for Module5 out of the numbers class and into its own class. Also remove the void return type from this to make it a correct constructor.
Move the code in your main into the constructor for Module5. This is the main frame so when you build a new one it should be initialised here, not in main. And remove the setVisible call for now (this is addressed in number 6)
After doing 1 and 2, get rid of your frame variable, your Module5 is a JFrame so anything to do with frame can just be changed to the keyword this (meaning this Module5 object)
Also move the area variable to be within the Numbers class - otherwise every Number is essentially going to share the same text area and This is not what you want.
Don't have your variables as static they should not need to be.
Once this is all done make sure it is running on the Event Dispatch Thread by making your main method like this (the one piece of code I will give you)
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
Module5 mod5 = new Module5();
mod5.setVisible(true);
}
});
}
I copied all of the relevant code below, and my problem is that after running the action performed (which is connected to a button) the values I tried to change in the action performed didn't actually change.
I put a sout(ques) at the end of the action performed and I can see the change in value but when I move outside of it, it reverts back to the 0;
public class GameRunner extends JPanel implements ActionListener{
private int x=50,y=600;
private Ball b = new Ball(x,y);
private Timer timer;
private boolean correct , incorrect;
private JButton button;
private JTextField f;
private int ques = 0;
private String[][] math = {{"2X^2","4x"},{"q2","a2"},{"q3","a3"},{"q4","a4"},{"q5","a5"},
{"q6","a6"},{"q7","a7"},{"q8","a8"}};
public void actionPerformed(ActionEvent actionEvent) {
if (f.getText().equals(math[ques][1])) {
correct = true;
} else {
incorrect = true;
}
f.setText("");
if(ques<7)
ques++;
else
ques = 0;
System.out.println(ques);
//I can see the change here
}
public void paint(Graphics g){//called whenever refreshed...
System.out.println(ques);
// But now outside of the action performed the ques and the correct incorrect do not change
if(correct)
b.move();
if(incorrect)
b.move2();
}
public static void main(String[] args) {
GameRunner gui = new GameRunner ();
gui.go();
}
public void go(){
button = new JButton("Guess");
f = new JTextField(15);
button.addActionListener(this);
JFrame frame = new JFrame("Derivative Game");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(700, 700));
JPanel pan = new JPanel(new BorderLayout());
JPanel pan2 = new GameRunner();
JPanel pan3 = new JPanel();
pan3.add( f);
pan3.add(button);
pan3.setBackground(new Color(80, 218, 213));
pan.add( pan3,BorderLayout.CENTER);
pan.setBackground(new Color(80, 218, 213));
frame.add(pan2);
frame.getContentPane().add(BorderLayout.SOUTH, pan);
frame.setSize(700, 760);
frame.setVisible(true);
frame.setResizable(false);
}
}
The basic problem is that you've actually got two instances of GameRunner here: the one you create in main(), and another one that you add to the JFrame. Since you only call go() on the one not in the JFrame, that instance's paint() method will never be called.
You need to refactor your code to eliminate that second stray GameRunner instance. While you're at it, you should also use paintComponent() instead of paint(), and you should take any "business logic" (like those calls to move()) out of your painting code.
In other words, get rid of this line:
JPanel pan2 = new GameRunner();
Since you're already "in" an instance of GameRunner, you shouldn't be creating another one. Then to use the "current" instance of GameRunner, you can use the this keyword:
frame.add(this);
Edit- You also aren't telling your GameRunner JPanel to repaint itself after the button is clicked. You might want to add a call to repaint() in your actionPerformed() method.
The class is called operating systems and I have to make a simulated clock that reads information at certain time and does something with it but I am only asking about the clock part here. Right now, I have 4 buttons which are run, tick, read, and show status. I have an input, an output, and a timer text field. I have a clockstarter class that starts the clock when the program starts and writes it in the console. I'm supposed to have two threads so that while that is happening I can click "run" and the timer textfield starts continuously counting or if run is not clicked, I can manually add time with tick. I need help getting it to show in the text field.
public class ClockStarter implements Runnable {
private Thread thread;
private int currentTime;
private javax.swing.JTextField time;
public ClockStarter(javax.swing.JTextField t){
System.out.println("Clock Starter Constructor");
currentTime = -1;
time = t;
thread = new Thread(this);
thread.start();
}
public void run(){
while(true){
incrementTime();
System.out.println("Clock Starter Current Time ");
time = ("" + getCurrentTime());// I need to fix this line
try{Thread.sleep(1000);} catch(Exception e){}
}
}
public void incrementTime(){
currentTime++;
}
public int getCurrentTime(){
return currentTime;
}
}
Do not use Thread.sleep() as it will freeze your Swing application.
Instead you should use a javax.swing.Timer.
See the Java tutorial How to Use Swing Timers and Lesson: Concurrency in Swing for more information and examples.
Please read the Swing tutorial How to Use Text Fields:
A text field is a basic text control that enables the user to type a small amount of text. When the user indicates that text entry is complete (usually by pressing Enter), the text field fires an action event. If you need to obtain more than one line of input from the user, use a text area.
Example Code
/* TextDemo.java requires no other files. */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TextDemo extends JPanel implements ActionListener {
protected JTextField textField;
protected JTextArea textArea;
private final static String newline = "\n";
public TextDemo() {
super(new GridBagLayout());
textField = new JTextField(20);
textField.addActionListener(this);
textArea = new JTextArea(5, 20);
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
//Add Components to this panel.
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
add(scrollPane, c);
}
public void actionPerformed(ActionEvent evt) {
String text = textField.getText();
textArea.append(text + newline);
textField.selectAll();
//Make sure the new text is visible, even if there
//was a selection in the text area.
textArea.setCaretPosition(textArea.getDocument().getLength());
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TextDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add contents to the window.
frame.add(new TextDemo());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I seem to have the opposite problem of everyone else.
My JDialog has both minimize and maximize buttons by default.
When the maximize button is pressed, the dialog maximizes - but the content doesn't. It just stays the same size, centered in a huge dialog.
Same happens when you just grab the edge and re-size the dialog.
I've tried adding a WindowStateListener - but it never gets invoked.
I added a WindowListener - and it's only invoked on Open/Close/Activate/Deactivate.
So, I either need to be able to get the dialog content to re-size with the dialog, OR remove the maximize button.
(and I'd like to get rid of the minimize button.)
I do do a pack() after creating the dialog, as the controls in the dialog are dynamically created from a block of data, so I don't have an initial size to work with.
Okay, so here's the code. All the generated UI panels are in GridBagLayouts as well.
public class FastAccessDialog extends JDialog implements BeanActionListener {
private static final long serialVersionUID = 1L;
private static final Cursor waitCursor = new Cursor(Cursor.WAIT_CURSOR);
private Cursor oldCursor;
private JPanel cmdOutput;
private JScrollPane cmdOutputScroll;
public FastAccessDialog(Frame owner, ObjectName bean, String methodName) throws InstanceNotFoundException, IntrospectionException,
ReflectionException, IOException {
super(owner);
setResizable(true);
setModal(false);
setTitle(BeanUtil.cleanUpCamelCase(methodName));
boolean enabled = (UIHintUtil.isEnabled(bean) == EnableState.ENABLED);
// Find the BeanOperationInfo for that method.
MBeanInfo info = JMXConnectionSingleton.getInstance().getMBeanInfo(bean);
MBeanOperationInfo[] operations = info.getOperations();
JComponent comp = null;
for (MBeanOperationInfo opInfo : operations) {
if (opInfo.getName().equals(methodName)) {
comp = OperationsManager.getInstance().createControls(bean, opInfo, this, true, enabled);
break;
}
}
if (comp == null) {
throw new IllegalArgumentException("Unknown method name: " + methodName);
}
Container cont = getContentPane();
cont.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(4, 4, 4, 4);
cont.add(comp, gbc);
cont.validate();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
pack();
}
});
return;
}
... other methods invoked when an operation is performed ...
... none of which are invoked before having the re-size problem ...
}
JPanel.(re)validate();
JPanel.repaint();
JDialog.pack();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JDialog.setVisible(true);
}
});
don't extends Top-Level Containers
don't use ContentPane, there no reason ... from Java5
nothing else in the case that JDialog.pack(); and JDialog.setVisible(true); are last code lines in void, method or constructor that returns JDialog instance