I'm trying to write the contents of an array to a JTextArea. I've tried everything I can think of, and I can't understand what isn't working here. I've stripped the unnecessary stuff out of my code, here's the two relevant classfiles:
Main class:
package irclogtest;
public class BriBotMain {
public static void main(String args[]) throws Exception {
boolean startup = true;
//frame test launch
BriDisplayGUI data = new BriDisplayGUI(startup);
data.irclog.append("BriBot Startup Successful!" + "\n");
//example access through function when startup is false (only in main class for sample code to demonstrate issue)
try {
BriDisplayGUI data2 = new BriDisplayGUI(false); //tells us which class we're accessing
String[] textForGUI = new String[2]; //tells us the array has 2 lines
textForGUI[0] = "this is the first line"; //set the first line of the array to this text
textForGUI[1] = "this is the second";
data2.arrayToDisplay(textForGUI); //appends contents of array to text window
}
catch(Exception e) {
System.out.println(e);
}
}
}
GUI display class:
package irclogtest;
import java.awt.event.*;
import java.io.IOException;
import javax.swing.*;
public class BriDisplayGUI extends JFrame implements ActionListener {
private static final long serialVersionUID = -7811223081379421773L;
String file_name = "C:/Bribot/logfile.txt";
//these lines create the objects we use
JFrame frame = new JFrame();
JPanel pane = new JPanel();
JButton pressme = new JButton("Click here");
JButton pressme2 = new JButton("Also here");
JTextArea irclog = new JTextArea( 20, 70);
JScrollPane scrollirc = new JScrollPane(irclog);
public BriDisplayGUI(boolean startup) { //startup function, opens and sets up the window
if(startup == true){
frame.setTitle("Bribot Test Frame"); frame.setBounds(100,100,840,420); //sets title of window, sets position and size of window
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //tells program to end on window close
frame.add(pane); //adds the main display pane to the window
//panel customization goes here
pressme.addActionListener(this);
pane.add(pressme);
pressme2.addActionListener(this);
pane.add(pressme2);
pressme.requestFocusInWindow();
irclog.setEditable(false);
scrollirc.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
pane.add(scrollirc);
irclog.setLineWrap(true);
irclog.setWrapStyleWord(true);
//pane.add(inputthing);
frame.setVisible(true);
} else {
System.out.println("Display Class Called");
}
}
public void arrayToDisplay(String[] text) throws IOException {
int i;
for ( i=0; i < text.length; i++) {
irclog.append( text[i] + "\n");
System.out.println( i + ": " + text[i]);
}
}
public void singleToDisplay(String text) throws IOException {
irclog.append(text + "\n");
System.out.println(text);
}
//basic event handler
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == pressme) {
} else if(source == pressme2) {
}
}
}
The first append works fine, but the second doesn't, and I can't figure out why (although the for loop does, as the contents of the array get written to console). I've searched quite a bit and nothing I've tried works. Can anyone point out the inevitable obvious oversight here? I'm the definition of a novice, so any advice is appreciated.
Thanks!
The default constructor doesn't do anything, meaning it doesn't construct any kind of UI or display, what would be, an empty frame.
You seem to be thinking the text will appear in data when you are appending it to data1
Try calling this(false) within the default constructor
A better solution would be to construct the core UI from the default constructor and from the "startup" constructor call this() and then modify the UI in what ever way this constructor needs
It seems like you write a new program. Why do you use Swing? Did you take a look at JavaFX?
I am not sure if that is going to fix your problem but you could try a foreach
for(String s : text){
irclog.append(s+"\n");
}
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
For this problem, my enter key for JTextField is not initalizing the if-else statement inside the chat();
I tried putting the userinput.addKeyListener(this); inside public guitest(); as well but its not working.
How do I get it work so that I can initialize the if else statement to reply me an answer. The error given was:
Exception in thread "main" java.lang.NullPointerException
public class guitest extends JFrame implements KeyListener{
ArrayList questionarray = new ArrayList();
ArrayList answerarray = new ArrayList();
public JTextArea scriptarea = new JTextArea();
public JTextField userinput = new JTextField();
public String stringinput;
public ArrayList getquestionarray(){
return questionarray;
}
public ArrayList getanswerarray(){
return answerarray;
}
public guitest(){
//gui
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600, 600);
this.setVisible(true);
this.setResizable(false);
this.setLayout(null);
this.setTitle("Minion AI");
setLocationRelativeTo(null);
//jtextfield location and field
userinput.setLocation(7, 530);
userinput.setSize(580, 30);
//jtextarea location and size
scriptarea.setLocation(15, 5);
scriptarea.setSize(560, 510);
scriptarea.setEditable(false);
//adding methods to frame
this.add(userinput);
this.add(scriptarea);
chat();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyChar() == KeyEvent.VK_ENTER){
stringinput = userinput.getText();
scriptarea.append("[You] " + stringinput + "\n");
userinput.setText("");
}
if(e.getKeyChar() == KeyEvent.VK_ESCAPE){
System.exit(0);
}
}
#Override
public void keyReleased(KeyEvent e) {
}
public void chat(){
Random random = new Random();
ArrayList greetingarray = greetings();
ArrayList quotesarray = quotes();
scriptarea.append("[AI Minion] "+greetingarray.get(random.nextInt(greetingarray.size()))+"\n");
userinput.addKeyListener(this);
if(greetingarray.contains(stringinput)){
for(int i=0; i<1; i++){
scriptarea.append("[AI Minion] "+greetingarray.get(random.nextInt(greetingarray.size()))+"\n");
}
}else if(questionarray.contains(stringinput)){
scriptarea.append("[AI Minion] "+answerarray.get(questionarray.indexOf(stringinput))+" \n");
}else if(stringinput.contains("who")){
scriptarea.append("[AI Minion] I am a creature created to assist you in your experience in talking to me. \n");
}else if(stringinput.contains("bye")||stringinput.contains("end")){
scriptarea.append("[AI Minion] Bye byee ♥‿♥ \n");
}else{
scriptarea.append("[AI Minion] Sorry, I dont understand your alien language. \n");
}
}
public static void main(String[] args){
new guitest();
}
}
Too many problems in your code:
You're having the below statement at the begining of the program:
this.setVisible(true);
This should be one of the last lines in your program, and after pack().
extends JFrame you shouldn't extend a JFrame because you're not changing any of its functionallity and as it's a rigid container, you cannot place it inside other containers. Build your program based on JPanels instead. Read: Extends JFrame vs. creating it inside the program
guitest -> GuiTest and stringinput; -> stringInput, please follow the Java naming conventions:
firstWordLowerCaseVariable
firstWordLowerCaseMethod()
FirstWordUpperCaseClass
ALL_WORDS_UPPER_CASE_CONSTANT
And use them consistently as this will make the program easier to read to you and us
this.setLayout(null); and .setLocation(...); are going to give you headaches, instead use one (or combine) Layout Manager, take this answer as an example of what happens when you use it and try to export it to be seen in another PC. Swing was designed to work with layout managers not with absolute pixel positioning as it has to work with different PLAFs, OS, screen sizes and resolutions, a layout manager will solve all of these.
Regarding to (3), your method names should be verbs greetings() should be getGreetings() for example (method which you haven't included in your question and which may be returning null)
I would also only declare my variables as class members but initialize them on the constructor only.
this.setSize(600, 600); call pack() instead (after you use the layout managers)
And as your code is incomplete, learn to use a debugger and see what variable is null that is why your code is breaking, the exception will tell you in the first three lines.
I am trying to make a simple program that will ask the user a question and then compare their answer with a stored correct answer. The problem seems to be that the main loop of the program is not running when I click the Ready JButton.
I tried changing the main method to another non-default name and adding a call to it in the actionPerformed() method, and it did seem to execute the loop at least once, but then led to not being able to close the applet without the task manager once I clicked the button. I don't know if that means it hit an endless loop or what.
I'm sure there is more to fix in this code besides this issue, but I cannot make any progress on that without clearing this up first. If there is a problem with the way I went about creating the GUI please let me know. I tried to base it off of an assignment I did that worked just fine, so I don't know whether or not that is the issue.
Any help provided is appreciated.
Here is the code:
import java.awt.*;
import javax.swing.*;
public class Langarden_App extends JApplet{
private int width = 800, height = 600;
private LangardenPanel langPanel;
public void init(){
langPanel = new LangardenPanel();
getContentPane().add(langPanel);
setSize(width, height);
}
}
And the class with the logic
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.*;
public class LangardenPanel extends JPanel{
private static JButton submit;
private static JButton ready = new JButton("Ready");
private static JLabel instruct;
private JTextField input = new JTextField(100);
private static String inString;
private static ArrayList<String> questions;
private static ArrayList<String> answers;
private static Random rand = new Random();
public LangardenPanel(){
questions = new ArrayList<String> (Arrays.asList("¿Qué es la palabra para 'inveirno' en ingles?", "¿Qué es la forma de 'yo' del verbo 'venir'?"));
answers = new ArrayList<String> (Arrays.asList("winter", "voy"));
instruct = new JLabel("Welcome to Langarden! Press Submit to begin. You have one minute and three attempts for each question.");
submit = new JButton("Submit");
this.setLayout(new BorderLayout());
add(BorderLayout.SOUTH, ready);
add(BorderLayout.NORTH, instruct);
add(BorderLayout.CENTER, input);
ready.addActionListener(new SubListener());
}
public static void main(String[] args){
try{
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e){
}
System.out.println("Setting text");
instruct.setText("Alright! Let's Go!");
try{
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e){
}
do{
System.out.println("Running loop");
int qnum = rand.nextInt(questions.size());
instruct.setText(questions.get(qnum));
for (int i=0; i<3; i++){
try {
TimeUnit.SECONDS.sleep(60);
} catch (InterruptedException e) {
}
if(checkAnswer(qnum, inString)){
instruct.setText("Correct!");
break;
} else {
instruct.setText("Try again...\n" + questions.get(qnum));
}
}
instruct.setText("The correct answer was " + answers.get(qnum));
try{
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e){
}
questions.remove(qnum);
answers.remove(qnum);
instruct.setText("Would you like to continue? Enter No and click Submit to exit.");
} while (!inString.equalsIgnoreCase("No") && questions.size() != 0);
instruct.setText("Congratulations, you have completed this module!");
}
private static boolean checkAnswer(int qnum, String inString) {
if (answers.get(qnum).equalsIgnoreCase(inString))
return true;
return false;
}
private class SubListener implements ActionListener{
public void actionPerformed(ActionEvent e){
System.out.println("Button Pressed!");
if(e.getSource() == ready){
add(BorderLayout.SOUTH, submit);
submit.addActionListener(new SubListener());
} else {
inString = input.getText();
}
}
}
}
Get rid of the main method. If this is running as an applet, then the program has no business having a main method.
Make all fields non-static. Yes all.
Get rid of the while-true loop. If this runs, this will squelch your Swing event thread rendering your GUI frozen and helpless. Use a Swing Timer instead as a "pseudo" loop. Please check out the Swing Timer Tutorial for more on this.
Any time you add a component to a container, you should call revalidate() and repaint() on that same container so that the container's layout managers can layout the new component, and so that the OS can repaint over any "dirty" pixels.
Rather than add a new JButton as you're doing, much better is to swap components using a CardLayout. The tutorial can be found here: CardLayout tutorial.
I'm very new to coding(2 months) and i attempted to make Tic-Tac-Toe in java. I'm in a little over my head but i managed to create it using swing. My main problem is in the button1 class. I was going to use the getText() method but ended up not needing it or so i thought. I tried deleting it but as it turns out my tictactoe buttons don't switch letters without it. The compiler told me it overrides AbstractButton's getText() method but i don't see why that should matter since i never actually used it i thought. I'm thinking it's maybe a scope issue handled by it being overwritten somehow but i'm not sure. I was trying to use the text variable to update the button with setText() and that doesn't seem to work like i thought it should. I also don't understand why the 3 by 3 gridlayout seems to work properly most of the time but sometimes the number of buttons added is wrong.
So in summation the program works(mostly) but i'm not fully understanding how the button1 class is working.
TicTacToe.java
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class TicTacToe extends JFrame {
public static void main(String[] args) {
JFrame window = new JFrame("Tic-Tac-Toe");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.setSize(600, 600);
window.setLayout(new GridLayout(3, 3));
ArrayList<button1> buttonArrayList = new ArrayList<>(9);
for (int i = 0; i < 9; i++) {
button1 newbutton = new button1();
buttonArrayList.add(newbutton);
window.add(buttonArrayList.get(i));
}
}
}
button1.java
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
public class button1 extends JButton {
int value = 0;
String text = "";
public button1() {
class ButtonAction extends AbstractAction {
public ButtonAction() {}
#Override
public void actionPerformed(ActionEvent Switcher) {
System.out.println(text + " " + value);
value++;//value is a relic from earlier attempts that i just felt like keeping.
if (text.equals("O")) {
text = "X";
} else if (text.equals("X")) {
text = "";
} else if (text.equals("")) {
text = "O";
}
}
}
this.setAction(new ButtonAction());
this.setText(text);
this.setFont(new Font("Arial",Font.PLAIN,120));
}
public String getText()// <----culprit
{
return text;
}
}
A JButton class has a methods defined for it, including setText() (which will set the displayed text on the button) and getText() (which will return the current text that is displayed on the button).
You created a class button1 (note: classes should start with Capital Letters).
You added an Action to the button1 class, which means that when the action is activated, something happens. Note that in that actionPerformed method, you should call setText(text) to update the displayed value.
You have also defined a getText() method that overrides the getText() method defined in JButton. This approach is fine if it is a conscious design decision. As it is, I think you should remove the getText() method from the button1 class, and allow the standard JButton class to handle the update. Right now, you are attempting to keep an instance variable text with the value, but it is possible for that instance variable to not be in alignment with the actual displayed value of the button (consider another class calling .setText() on the button).
EDIT: It is true that this referring to the JButton in the ButtonAction is not available. However, the Action itself contains the button that was pressed.
#Override
public void actionPerformed(ActionEvent e)
{
JButton btn = (JButton)e.getSource();
// if desired, String cur = btn.getText() may be called to find the
// current setting; get and process if needed
btn.setText(WHAT_EVER_TEXT);
}
Unless it is a specific requirement to process the current text, however (allowing selecting an O to an X to a blank), I would implement something to keep track of the current turn. This code is something I was experimenting with, and has good and bad points to it (as it is illustrative):
static class TurnController
{
// whose turn it is; start with X
private Player whoseTurn = Player.X;
// the instance variable
private static final TurnController instance = new TurnController();
private TurnController()
{
}
public static Player currentTurn()
{
return instance.whoseTurn;
}
public static Player nextTurn()
{
switch (instance.whoseTurn) {
case X:
instance.whoseTurn = Player.O;
break;
case O:
instance.whoseTurn = Player.X;
break;
}
return instance.whoseTurn;
}
public static String getMarkerAndAdvance()
{
String marker = currentTurn().toString();
nextTurn();
return marker;
}
enum Player
{
X,
O,
;
}
}
Using this TurnController, the actionPerformed becomes:
#Override
public void actionPerformed(ActionEvent e)
{
JButton btn = (JButton)e.getSource();
btn.setText(TurnController.getMarkerAndAdvance());
}
and the Button1 class may have the String text instance variable removed.
What you have tried is Try to make a Custom Button Class and its EventHandler just by extending AbstractAction namee button1 as we See in Your Question.
You have Override the method actionPerformed(ActionEvent Switcher) which actually belongs to Class AbstractAction by your own definition (What should Performed on Action Event of Every Button).
class ButtonAction extends AbstractAction {
public ButtonAction() {}
#Override
public void actionPerformed(ActionEvent Switcher) { // Your Definition For actionPerformed..
System.out.println(text + " " + value);
value++;//value is a relic from earlier attempts that i just felt like keeping.
if (text.equals("O")) {
text = "X";
} else if (text.equals("X")) {
text = "";
} else if (text.equals("")) {
text = "O";
}
}
}
this.setAction(new ButtonAction()); // add ActionListener to each Button.
this.setText(text); // Setting Text to each Button
this.setFont(new Font("Arial",Font.PLAIN,120)); //add Font to each Button.
}
Now In this Code.
ArrayList buttonArrayList = new ArrayList<>();
for (int i = 0; i < 9; i++) {
button1 newbutton = new button1(); // Creating 9 new buttons.
buttonArrayList.add(newbutton); // add each button into the ArrayList.
window.add(buttonArrayList.get(i)); // each Button to the the AWT Window.
}
Above Code will generate 9 Button and add it to Your AWT Window. each button have actionPerformed() method which contains the overrided Definition.
Now Each button will performed action as per the definition you give to actionPerformed() Method.
Thank You.
I've got a JFrame subclass which waits for a specific console input before displaying a JFrame and its contained widgets using the setVisible(true) method. The widgets (which are a subclass of JPanels) are added to the parent JFrame from a LinkedList using an iterator, and are added to the LinkedList via another method in the class.
When I run the program, it keeps repeating the method which contains this.setVisible(true), and doesn't display anything. Any help would be greatly appreciated. I've pasted the code below.
public class GUI extends JFrame{
class KPanel extends JPanel{ //virtual class for Panels that displayed variable name in titled border
public KPanel(String varName){
TitledBorder varTitle = new TitledBorder(varName +":");
this.setBorder(varTitle);
}
}
private LinkedList<KPanel> buffer; //list containing components to be added to GUI
public GUI(String title){
setTitle(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,300);
buffer = new LinkedList<KPanel>(); //initializes linkedlist buffer
}
public void addBox(String var, String val){
//creates a panel containing a string, adds it to the buffer
KPanel temp = new KPanel(var);
JLabel valLabel = new JLabel(val);
temp.add(valLabel);
buffer.add(temp);
}
public void show(){
int i=0;
int wid_height;
int x = 0;
if ((x = buffer.size()) != 0)
wid_height = this.getHeight()/x; //calculates widget heights for even distribution along frame
else{
System.out.println("No variables set!");
return;
}
System.out.println("buffer: " + buffer.size() + "\nheights: " + wid_height);
Iterator<KPanel> iter = buffer.iterator();
KPanel temp = new KPanel("");
while(iter.hasNext()){
temp = iter.next();
temp.setSize(this.getWidth(), wid_height);
temp.setLocation(0, wid_height*i);
this.add(temp);
i++;
}
this.setVisible(true);
return;
}
}
Your show() method is overriding an existing method in JFrame. Use a different name, or, better yet, don't extend JFrame unless you really need to change how a frame behaves.
The problem is that your show() method is overriding the show() method in JFrame. What leads to the StackOverflowError is that it's calling setVisible(true). This method is inherited from Component, and it is simple. Here's the code:
public void setVisible(boolean b) {
show(b);
}
and show(b) calls show():
public void show(boolean b) {
if (b) {
show();
} else {
hide();
}
}
So, your show calls setVisible, which calls your show, with nothing to break the cycle. I would use a different name for your show method to prevent this infinite loop.
I have a school assignment that i need to create. Below is the info:
Create a frame with ten buttons, labeled 0 through 9. To exit the program, the user must click on the correct three buttons in order, something like 7-3-5. If the wrong combination is used, the frame turns red.
I already finish the frame and the buttons with online research helps, but i just cant make the functionality to work. Please take a look at my codes and thanks in advance.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ComboNumber extends JFrame implements ActionListener{
//variable declaration
int ans1 = 3;
int ans2 = 7;
int ans3 = 1;
int one, two, three;
String inData1, inData2, inData3;
JButton[] button;
//constructs the combolock object
public ComboNumber()
{
//sets flowlayout
getContentPane().setLayout(new FlowLayout());
Container c = getContentPane();
//creates buttons
button = new JButton[10];
for(int i = 0; i < button.length; ++i) {
button[i] = new JButton("" + i);
//adds buttons to the frame
c.add(button[i]);
//registers listeners with buttons
button[i].addActionListener(this);
}
//sets commands for the buttons (useless)
//sets title for frame
setTitle("ComboLock");
}
//end combolock object
//listener object
public void actionPerformed(ActionEvent evt)
{
Object o = evt.getSource();
for(int i = 0; i < button.length; ++i) {
if(button[i] == o) {
// it is button[i] that was cliked
// act accordingly
return;
}
}
}
//end listener object
//main method
public static void main (String[] args)
{
//calls object to format window
ComboNumber frm = new ComboNumber();
//WindowQuitter class to listen for window closing
WindowQuitter wQuit = new WindowQuitter();
frm.addWindowListener(wQuit);
//sets window size and visibility
frm.setSize(500, 500);
frm.setVisible(true);
}
//end main method
}
//end main class
//window quitter class
class WindowQuitter extends WindowAdapter
{
//method to close the window
public void windowClosing(WindowEvent e)
{
//exits the program when the window is closed
System.exit(0);
}
//end method
}
//end class
The basic idea is simple.
You need two things.
What the combination actually is
What the user has guessed
So. You need to add two variables. One contains the combination/secret, the other contains the guesses.
private String secret = "123";
private String guess = "";
This allows you to make the combination as long as you like ;)
Then in your actionPerformed method, you need to add the most recent button click to the guess, check it against the secret and see if they've made a good guess. If the length of the guess passes the number of characters in the secret, you need to reset the guess.
public void actionPerformed(ActionEvent evt) {
Object o = evt.getSource();
if (o instanceof JButton) {
JButton btn = (JButton) o;
guess += btn.getText();
if (guess.equals(secret)) {
JOptionPane.showMessageDialog(this, "Welcome Overloard Master");
dispose();
} else if (guess.length() >= 3) {
JOptionPane.showMessageDialog(this, "WRONG", "Wrong", JOptionPane.ERROR_MESSAGE);
guess = "";
}
}
}