I'm trying to create a name generator that generates names by random.
Now when i click the button, it generates a name, but it shows up in the Eclipse console and not in the same window as the button, which is what I want it to do.
Eventually I would like to be able to have a specific picture for for the button and for the background (window/frame). Also, as a bonus I'm hoping to add a bit of music to it that can play in the background once you open the app.
Now, I'm fairly new to java and I've only watched a couple of tutorials, but it's gotten me this far and hopefully I can learn a thing or two from one of you guys.
So please be kind, Best regards leal.
import javax.swing.*;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.*;
public class ClanNameGenerator {
public static void main (String[] args){
JFrame frame = new JFrame("ExETesT");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,350);
JPanel panel = new JPanel ();
frame.add(panel);
JButton button = new JButton("Click me");
panel.add(button);
button.addActionListener(new Action());
}
static class Action implements ActionListener{
public void actionPerformed (ActionEvent e){
String[] names = {"test", "Zero", "Club", "Moonkys", "znakes", "SeamOnster", "dnktwhm", "Rambo", "OmG", "siste"};
String[] names2 = {"Ylos", "zzzzz", "sdsd", "OK"};
String[] names3 = {"Hei", "ok", "jadd", "så drar vi", "det var det"};
int random = (int) (Math.random()*names.length);
int random2 = (int) (Math.random()*names2.length);
int random3 = (int) (Math.random()*names3.length);
System.out.println("Your clan name is: " + names[random] +" "+ names2[random2] +" "+ names3[random3]);
}
}
}
if you do something like this, the name will appear in JFrame:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ClanNameGenerator {
private static JLabel label;
public static void main (String[] args){
JFrame frame = new JFrame("ExETesT");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,350);
JPanel panel = new JPanel ();
frame.add(panel);
JButton button = new JButton("Click me");
panel.add(button);
label = new JLabel();
panel.add(label);
button.addActionListener(new Action());
}
static class Action implements ActionListener{
public void actionPerformed (ActionEvent e){
String[] names = {"test", "Zero", "Club", "Moonkys", "znakes", "SeamOnster", "dnktwhm", "Rambo", "OmG", "siste"};
String[] names2 = {"Ylos", "zzzzz", "sdsd", "OK"};
String[] names3 = {"Hei", "ok", "jadd", "så drar vi", "det var det"};
int random = (int) (Math.random()*names.length);
int random2 = (int) (Math.random()*names2.length);
int random3 = (int) (Math.random()*names3.length);
label.setText("Your clan name is: " + names[random] +" "+ names2[random2] +" "+ names3[random3]);
}
}
}
There's a lot going on in your question without you actually asking any questions. As for your text problem though, System.out.println(); will always print to the console, wherever it may be. To add it to the JFrame, you have a variety of options. The one you probably want is to use a JLabel, unless you have a lot of text, in which case a JTextArea may be better suited, or if you intend to do something a little fancier than regular text you may want to draw it directly using the Graphics class and drawString(String).
How to add text to JFrame?
As for the other parts of your... "question," do some research and try things before asking for help on the Stack. This community is for assisting you when things don't work, not for writing your projects for you.
Add a JLabel to your UI, then call the setText method of that JLabel object.
jLabelObject.setText("Your clan name is: " +
names[random] +" "+ names2[random2] +" "+ names3[random3);
Related
I'm trying to create a personality quiz. The idea is that a JPanel will show up with the first question and then once the user selects one of the radio buttons, the second JPanel with the second question will show up.
Since I have 5 questions each with 3 answer choices I thought it would be faster and more efficient to create a method that creates radio buttons and adds an ActionListener but I'm having trouble getting the listener to work. Right now to see if it works I'm just trying to change the button text when it is selected.
I tried adding the listener to the button in the createButton method but I haven't had luck. Originally I had it as a parameter in the method but that didn't get the expected result so I tried to create it without the listener as a parameter. Inserting the listener as a parameter didn't change the text.
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.WindowConstants;
public class UserInterface extends ClickListener implements Runnable
{
private ActionListener listeners;
private JFrame frame;
public UserInterface(){
}
#Override
public void run() {
frame = new JFrame("title");
frame.setPreferredSize(new Dimension(1000, 1000));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
createComponents(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
public JFrame getFrame(){
return frame;
}
private void createComponents(Container container){
BoxLayout layout = new BoxLayout(container, BoxLayout.Y_AXIS);
container.setLayout(layout);
container.add(QuizIntro());
container.add(QuestionOne());
container.add(QuestionOneGroup());
}
public JLabel QuizIntro(){
JLabel text = new JLabel("Intro text");
return text;
}
public JLabel QuestionOne(){
JLabel text = new JLabel("1. this is the first question");
return text;
}
public JPanel QuestionOneGroup(){
JRadioButton int1 = createButton("This button was created with my createButton method");
JRadioButton e1 = new JRadioButton("This button was created without that method");
JPanel panel = new JPanel();
panel.add(int1);
panel.add(e1);
return panel;
}
public JRadioButton createButton(String text){
JRadioButton b = new JRadioButton(text);
b.addActionListener(listeners);
return b;
}
}
here's my action listener
public class ClickListener implements ActionListener {
private UserInterface ui;
private JRadioButton b;
#Override
public void actionPerformed(ActionEvent ae) {
if (b.isSelected()){
b.setText("this works");
}
}
}
The actual result is that the button is selected but the text does not change. I'm having trouble figuring out if I'm running the wrong test to see if my listener works or if my listener just does not work.
Your main problem is here:
private ActionListener listeners;
You create an ActionListener but you never call it.
You're also inheriting from ClickListener but never using it.
public class UserInterface extends ClickListener implements Runnable
In your code you call:
b.addActionListener(listeners); //Listeners is null!
So, you're telling your JRadioButton to have a listener that is null.
So, here you have 2 approaches:
Remove private ActionListener listeners; from the top of your program and change:
b.addActionListener(listeners);
To:
b.addActionListener(this);
Remove extends ClickListener from your class definition and keep:
b.addActionListener(listeners);
But adding
listeners = new ClickListener();
Before
createComponents(frame.getContentPane());
IMO I would take the 2nd approach.
BTW for your ActionListener to actually change the text you don't need private variables but rather get the source and cast it. For example:
public void actionPerformed(ActionEvent ae) {
JRadioButton b = (JRadioButton) ae.getSource();
b.setText("this works");
}
Forgot to mention, please follow Java naming conventions so that your program is more readable and understandable by everyone who reads it.
firstWordLowerCaseVariable
firstWordLowerCaseMethod()
FirstWordUpperCaseClass
ALL_WORDS_UPPER_CASE_CONSTANT
And indent your code correctly as well :)
First of all the GUI should not extend the listener class. Not good. Better to keep them separate and to pass references where needed. For example, if the listener needs a reference to the GUI, pass it in as a paramter
Also, you apparently want to do is to respond to JRadioButton selection immediately with useful behavior. I would use an ItemListener not an ActionListener, since the ItemListener will tell you if the radio button has been selected. Calling getSource() on the ItemEvent will give you the current JRadioButton that was selected.
e.g.,
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class UserInterface2 extends JPanel {
public static final Object QUESTION = "question";
// fill label with blank text to expand it
private JLabel resultLabel = new JLabel(String.format("%150s", " "));
// CardLayout to allow swapping of question panels
private CardLayout cardLayout = new CardLayout();
private JPanel centerPanel = new JPanel(cardLayout);
public UserInterface2(List<Question> questions) {
centerPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for (Question question : questions) {
centerPanel.add(createQPanel(question), question.getQuestion());
}
JPanel bottomPanel = new JPanel(new BorderLayout());
// add button that allows swapping question panels
bottomPanel.add(new JButton(new AbstractAction("Next") {
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.next(centerPanel);
}
}), BorderLayout.LINE_START);
bottomPanel.add(resultLabel);
setLayout(new BorderLayout());
add(bottomPanel, BorderLayout.PAGE_END);
add(centerPanel);
}
private JPanel createQPanel(Question question) {
JPanel radioPanel = new JPanel(new GridLayout(0, 1));
radioPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
ButtonGroup buttonGroup = new ButtonGroup();
ItemListener myItemListener = new MyItemListener(this);
for (String answer : question.getAnswers()) {
JRadioButton answerButton = new JRadioButton(answer);
// this is present in case you want to extract the Question
// object from the JRadioButton, useful for if you want to
// test if the selected answer is correct
answerButton.putClientProperty(QUESTION, question);
// add our listener to the JRadioButton
answerButton.addItemListener(myItemListener);
// add to button group so only one can be selected
buttonGroup.add(answerButton);
// add to JPanel for display
radioPanel.add(answerButton);
}
JPanel qPanel = new JPanel(new BorderLayout());
qPanel.add(new JLabel(question.getQuestion()), BorderLayout.PAGE_START);
qPanel.add(radioPanel);
return qPanel;
}
// public method that the item listener will use to display selection
public void displayResult(String selectedText) {
resultLabel.setText(selectedText);
}
private static void createAndShowGui() {
// create mock questions
// likely this information will be in a text file
List<Question> questions = new ArrayList<>();
for (int i = 0; i < 10; i++) {
String question = "Question " + i;
List<String> answers = new ArrayList<>();
for (int j = 0; j < 4; j++) {
answers.add(String.format("Answer [%d %d]", i, j));
}
int correctIndex = (int) (Math.random() * answers.size());
// future iteration will also need correctIndex int
questions.add(new Question(question, answers, correctIndex));
}
UserInterface2 mainPanel = new UserInterface2(questions);
JFrame frame = new JFrame("User Interface");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MyItemListener implements ItemListener {
private UserInterface2 ui;
public MyItemListener(UserInterface2 ui) {
this.ui = ui;
}
#Override
public void itemStateChanged(ItemEvent e) {
JRadioButton source = (JRadioButton) e.getSource();
String selected = "The JRadioButton " + source.getText();
selected += e.getStateChange() == ItemEvent.SELECTED ? " has been selected"
: " has been unselected";
// to get the actual Question object get the client property:
Question question = (Question) source.getClientProperty(UserInterface2.QUESTION);
// now can get answer Strings and check if correct one selected
System.out.println(question);
String correctAnswer = question.getAnswers().get(question.getCorrectIndex());;
if (source.getText().equals(correctAnswer)) {
selected += " and is correct";
} else {
selected += " and is incorrect";
}
// tell the GUI to display the result
ui.displayResult(selected);
}
}
class Question {
private String question;
private List<String> answers;
private int correctIndex;
public Question(String question, List<String> answers, int correctIndex) {
this.question = question;
this.answers = answers;
this.correctIndex = correctIndex;
}
public String getQuestion() {
return question;
}
public List<String> getAnswers() {
return answers;
}
public int getCorrectIndex() {
return correctIndex;
}
#Override
public String toString() {
return "Question [question=" + question + ", correctIndex="
+ correctIndex + "]";
}
}
Since there are many things to be improved in your code, I thought I'll write a sample program to show you how this kind of a thing should be done in Swing. Try it and see.
(There are few things we can improve in this sample code as well. But I just wanted to keep things simple and address only the key points.)
import javax.swing.*;
import java.awt.event.*;
public class Questions {
public static void main(String[] args) {
JFrame f = new JFrame("Questions");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new QuestionPanel());
f.setBounds(300, 200, 400, 300);
f.setVisible(true);
}
}
class QuestionPanel extends JPanel implements ActionListener {
private static final String ANSWER_1_TEXT = "Answer 1";
private static final String ANSWER_2_TEXT = "Answer 2";
private static final String ANSWER_3_TEXT = "Answer 3";
private JRadioButton answer1;
private JRadioButton answer2;
private JRadioButton answer3;
QuestionPanel() {
answer1 = new JRadioButton(ANSWER_1_TEXT);
answer2 = new JRadioButton(ANSWER_2_TEXT);
answer3 = new JRadioButton(ANSWER_3_TEXT);
answer1.addActionListener(this);
answer2.addActionListener(this);
answer3.addActionListener(this);
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(answer1);
buttonGroup.add(answer2);
buttonGroup.add(answer3);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(answer1);
add(answer2);
add(answer3);
}
#Override
public void actionPerformed(ActionEvent e) {
JRadioButton selectedAnswer = (JRadioButton) e.getSource();
if (selectedAnswer == answer1) {
answer1.setText(ANSWER_1_TEXT + " (selected)");
answer2.setText(ANSWER_2_TEXT);
answer3.setText(ANSWER_3_TEXT);
}
else if (selectedAnswer == answer2) {
answer1.setText(ANSWER_1_TEXT);
answer2.setText(ANSWER_2_TEXT + " (selected)");
answer3.setText(ANSWER_3_TEXT);
}
else if (selectedAnswer == answer3) {
answer1.setText(ANSWER_1_TEXT);
answer2.setText(ANSWER_2_TEXT);
answer3.setText(ANSWER_3_TEXT + " (selected)");
}
}
}
How many programmers do you need to change a lightbulb? 76, 1 to change it and 75 to say how they could've done it better.
You do have bad code practices, but thats usually because of a shaky understanding of the fundamental concepts behind the language design. So I won't comment on how your code is bad for this or that, just explain the basics you should know.
To simplify, an ActionListener is an object that will react on an ActionPerformedEvent. Lets define one, a class called Observer:
Observer has no idea who generated the event, so lets tell him, and if it is a JRadioButton, lets use it as one
public class Observer implements ActionListener{
#Override
public void ActionPerformed(ActionEvent ae){
Object source = ae.getSource();
if (source instanceof JRadioButton)
((JRadioButton) source).setText("this works");
}
Any of your JRadioButton are objects that generates ActionEvents constantly, but nobody we care about is usually watching, when we add an ActionListener we are basically saying: make this ActionListener object observe my behaviour.
So we need someone to be observed and an observer, lets make those in your UI (or a simplified version of it):
Since you are trying to use a global listener, you need to make sure there is one there, observer (our ActionListener) is null for now. Lets instantiate it This time, we know that observer is not null
public class UserInterface implements runnable{
private ActionListener observer new Observer();
//...
public void someMethodToCreateButtons(){
JRadioButton observableButton = new JRadioButton("Created here");
observableButton.addActionListener(observer);
}
And thats it, when you select observableButton, it will change its text to "this works".
Those are the basics, now, I used those names observableButton and Observer for a reason, ActionListeners are based on what is known as the observer design pattern you could pick up a book regarding designs patterns, you wont regret it.
Finally, it seems that you are making things too difficult for yourself, try to simplify your logic. Perhaps making a JPanel containing different sets of buttons and displaying it whenever a condition is true? just spitballing here, but try to keep it simple, hope it helps, good luck!
Im still pretty new to java and I wrote a magic 8 ball program awhile ago. Well I just learned about JFrames and JPanels, so i wanted to update it.
Im having trouble with a couple of things, and i dont know if this is asking too much because of never used this website before. i dont understand actionlisteners too well and i need help putting one on the b button to make it paint a new JPanel that paints my random chooser statements. That's the other thing, how do i make it paint one of my array elements?
window
package pack;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class window extends ball {
public static void main (String []args) {
JFrame f = new JFrame("hello");
JPanel p = new JPanel();
JLabel l = new JLabel("What do you ask the magic conch shell?");
JTextField t = new JTextField(25);
JButton b = new JButton();
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { }
});
//panel
b.setText("Ask");
p.add(l);
p.add(b);
p.add(t);
//frame
f.add(p);
f.setSize(300, 400);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}}
ball
package pack;
import java.util.Scanner;
import java.util.Random;
public class ball {
public static void main(String[]args) {
String question = ("What do you ask the Magic Conch shell?");
Scanner userInput =new Scanner(System.in);
String answer = userInput.nextLine();
String[] array;
array = new String[8];
array[0] = ("yes");
array[1] = ("no");
array[2] = ("maybe");
array[3] = ("never");
array[4] = ("ask again later");
array[5] = ("positive");
array[6] = ("unlikely");
array[7] = ("yes");
Random dice = new Random();
int n = dice.nextInt(8);
System.out.println(array[n]);
}
}
Take the code from your ball class, use it to create a method which returns the result of the roll, this provides you a point of re-use
public class Ball {
private String[] results = new String[] {
"yes", "no", "maybe", "never", "ask again later", "postive", "unlikely", "yes"
};
private Random random = new Random();
public String roll() {
int n = random.nextInt(results.length);
return results[n];
}
}
Now, in your buttons ActionListener, you need to "roll" the ball
Ball ball = new Ball();
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String result = ball.roll();
}
});
Now, you next problem is, you don't actually have anywhere to display the result.
You really don't want to introduce a new component at this stage if you can help it, instead, you want to have one ready to use, so, let's add another JLabel to act as the "answer"
Ball ball = new Ball();
JLabel answer = new JLabel("...");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String result = ball.roll();
answer.setText(result);
}
});
//panel
b.setText("Ask");
p.add(l);
p.add(b);
p.add(t);
p.add(answer);
Adding components at runtime isn't difficult, but it does introduce a number of other issues you need to aware of. In this, we've limited some of the issues by introducing a component which we can simply update as needed
so I am trying to make a small java program to count the number of characters in a given string.
Right now, my code works in the console output, but it is not updating the text field I have created in a JFrame and I am unsure why. Can someone please explain this to me?
BTW: I have set "onPress" to true, so the button doesn't really have an effect right now, I'm just trying to test the functionality of the program before I implement button functionality.
Thank you :)! Here is my code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class characterCounterTwov2 extends JFrame {
static boolean onPress = true;
public characterCounterTwov2(){
/*******************/
/* Local Variables */
/*******************/
//creates a new Jframe to put our frame objets in
JFrame frame = new JFrame();
//creates a text field frame object
JTextField txtField = new JTextField("Enter your text here", 25);
//stores the string of the the jtextfield into a variable text
String text = txtField.getText();
//creates a text field that is uneditable with the word "characters"
String charString = "Characters: ";
JTextField charField = new JTextField(charString, 25);
charField.setEditable(false);
//integer to count the characters
int charCounter = 0;
//string that will be used in a text field to display the # of chars
String charCount = Integer.toString(charCounter);
//Text field that displays charCount
JTextField charFieldTwo = new JTextField(charCount, 10);
//calculate button
JButton calcButton = new JButton("Calculate");
calcButton.addActionListener(new calcButtonFunc());
/*******************/
/* Frame Setup */
/*******************/
//sets the layout of the frame
frame.setLayout(new BorderLayout());
//add's elements to the frame
frame.add(txtField, BorderLayout.NORTH);
frame.add(charField, BorderLayout.CENTER);
frame.add(charFieldTwo, BorderLayout.SOUTH);
frame.add(calcButton, BorderLayout.EAST);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
//begin while loop
//infinite while loop
System.out.println("Entering main while loop");
while(true)
{
while(onPress == true)
{
System.out.println("text length is:" + charCount);
for(int i = 0; i < text.length(); i++)
{
charCounter++;
System.out.println("Number of characters:" + charCounter);
}
//charCount = Integer.toString(charCounter);
onPress = false;
}
}
}
static class calcButtonFunc implements ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent event)
{
onPress = true;
}
}
public static void main(String[] args){
new characterCounterTwov2();
System.out.println("End of program. Should not get here");
}
}
~~~~~~~~~
EDIT
I was given a lot of helpful tips by Hovercraft Full of Eels, and cleaned up my code. I am still having a problem with calculating the character count on button press, and having it reflect in the GUI. I am thinking my bug lies within the line "text = txtField.getText();" inside my button listener class.
Here is my updated code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class characterCounterTwov4{
//creates a new Jframe to put our frame objets in
JFrame frame = new JFrame();
//creates a text field frame object
JTextField txtField = new JTextField(25);
//stores the string of the the jtextfield into a variable text
String text = txtField.getText();
//creates a text field that is uneditable with the word "characters"
String charString = "Characters: ";
JTextField charField = new JTextField(charString, 25);
public characterCounterTwov4(){
charField.setEditable(false);
//integer to count the characters
int charCounter = 0;
//string that will be used in a text field to display the # of chars
String charCount = Integer.toString(text.length());
//Text field that displays charCount
JTextField charFieldTwo = new JTextField(charCount, 10);
//calculate button
JButton calcButton = new JButton("Calculate");
calcButton.addActionListener(new ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent event)
{
System.out.println("button pressed");
//stores the string of the the jtextfield into a variable text
text = txtField.getText();
//string that will be used in a text field to display the # of chars
String charCount = Integer.toString(text.length());
//Text field that displays charCount
JTextField charFieldTwo = new JTextField(charCount, 10);
}
});
/*******************/
/* Frame Setup */
/*******************/
//sets the layout of the frame
frame.setLayout(new BorderLayout());
//add's elements to the frame
frame.add(txtField, BorderLayout.NORTH);
frame.add(charField, BorderLayout.CENTER);
frame.add(charFieldTwo, BorderLayout.SOUTH);
frame.add(calcButton, BorderLayout.EAST);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args){
new characterCounterTwov4();
System.out.println("End of program. Should not get here");
}
}
Your code is not structured for correct Swing GUI event-driven programming but rather looks like a linear console program that is being shoe-horned into a GUI. Get rid of that while loop, get rid of that static boolean variable. Instead give your class a non-static (instance) int counter variable and a JTextField non-static variable and simply increment your counter in the actionPerformed method and display the results in the JTextField (or JLabel if you prefer).
So the actionPerformed could look something like:
public void actionPerformed(ActionEVent e) {
counter++; // increment the counter variable
charCount.setText("Count: " + counter); // display the results
}
and again, counter and charCount are non-static and are declared and initialized in the class, not inside of the constructor or any method.
Edit
Additional notes:
Why does your class extend JFrame when you don't use it as a JFrame?
In general, it's a good idea to start all Swing proggrams on the Swing Event Dispatch Thread or EDT. This can be done by passing a Runnable with your start-up code in it to the SwingUtilities static method invokeLater(...).
For example:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
// create and display your GUI from in here
MainGui mainGui = new MainGui();
JFrame mainFrame = new JFrame("Main GUI");
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainFrame.add(mainGui);
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
Edit 2
Oops, I read your requirements wrong. You need to count the chars in a String, and so you will need another class instance JTextField, one to hold the user's String, get rid of the counter instance field since it no longer will be needed, and then in the actionPerformed method, simply get the String from the JTextField, get its length, and display the length in another JTextField or in a JLabel, again your choice.
Edit 3
Your code is now almost there!
Problems:
The charFieldTwo variable is a non-final local variable. To be able to use it in your anonymous inner class, either make it final, and note that doing this won't harm its ability to work since it is a reference variable, not a primite,
Or you could move its declaration out of the constructor, like you do the other variables.
Once you've done this, it is easy to call charFieldTwo.setText(charCount); on it at the bottom of your ActionListener, and you're pretty much done.
The problem that I am having is when I try to replace the main screen with a second one and it deletes the old one but is stuck placing in the new one. If I maximize the screen I can see the new Panels. Another question I had was how to take up spaces in a grid layout without using all of the filler jpanels that I have to do. The code is below:
package home.personalprojects.jordan.ArrayGame;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
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;
public class GuiMain extends JFrame
{
private JButton Inventory, Store, Up, Down, Left, Right, Move, GameInfo, Back = new JButton("Back");
private JLabel pstats, roominfo;
private JPanel Filler1,Filler2,Filler3,Filler4,Filler5,Filler6,Filler7,Filler8,Filler9,Filler10,Filler11;
private JPanel Controls, Main = new JPanel(), BackPanel;
PlayerTraits pt = new PlayerTraits();
Rooms rm = new Rooms();
public GuiMain(){
super("Dungeon Crawler v 0.0.1 Created By: Jordan Savage");
Main.setLayout(new GridLayout(4,3));
//mainbuttons
Inventory = new JButton("Inventory");
Inventory.setToolTipText("Gives you access to all of your items and lets you manage them");
Store = new JButton("Store");
Store.setToolTipText("The marketplace where you can buy and sell items such as swords and armor");
Move = new JButton("Move");
Move.setToolTipText("Choose where you want to move next");
GameInfo = new JButton("Game Information and Settings");
GameInfo.setToolTipText("All the info for the game including instructions, version info, and settings");
//main labels
pstats = new JLabel(pt.name + ": " + pt.gold + " Gold, " + pt.health + " Health, and Level is " + pt.lvl);
roominfo = new JLabel("You are at: (" + pt.x + "," + pt.y + ") In room: " + rm.name);
//fillers for grid layout
Filler1 = new JPanel();Filler2 = new JPanel();Filler3 = new JPanel();Filler4 = new JPanel();Filler5 = new JPanel();Filler6 = new JPanel();Filler7 = new JPanel();Filler7 = new JPanel();Filler8 = new JPanel();Filler9 = new JPanel();Filler10 = new JPanel();Filler11 = new JPanel();
//action listeners
Move.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
ControlScheme();
BackToMain();
getContentPane().removeAll();
getContentPane().add(Controls, BorderLayout.CENTER);
getContentPane().add(BackPanel, BorderLayout.SOUTH);
getContentPane().doLayout();
update(getGraphics());
}
});
Back.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
getContentPane().removeAll();
getContentPane().add(Main);
getContentPane().doLayout();
update(getGraphics());
}
});
Main.add(Inventory);
Main.add(Filler1);
Main.add(Store);
Main.add(Filler2);
Main.add(pstats);
Main.add(Filler3);
Main.add(Filler4);
Main.add(roominfo);
Main.add(Filler5);
Main.add(Move);
Main.add(Filler6);
Main.add(GameInfo);
add(Main);
}
public void BackToMain(){
BackPanel = new JPanel();
BackPanel.setLayout(new FlowLayout());
BackPanel.add(Back);
}
public void ControlScheme(){
Up = new JButton("Up");
Down = new JButton("Down");
Left = new JButton("Left");
Right = new JButton("Right");
Controls = new JPanel();
Controls.setLayout(new GridLayout(3,3));
Controls.add(Filler7);
Controls.add(Up);
Controls.add(Filler8);
Controls.add(Left);
Controls.add(Filler9);
Controls.add(Right);
Controls.add(Filler10);
Controls.add(Down);
Controls.add(Filler11);
}
public static void main(String[] args)
{
GuiMain gm = new GuiMain();
gm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gm.setSize(800, 600);
gm.setVisible(true);
gm.setLocationRelativeTo(null);
}
}
Any Help Is Appreciated :)
The short answer would be to call revalidate on the frame.
The better answer would be to use a CardLayout, which was designed to do exactly what you are trying to do...
As to your second question, it can't be done with GridLayout, in fact, you might find it difficult to achieve even with GridBagLayout which gives you control over the placement of components within the virtual grid.
What you might be able to do, is use the fill the grid with empty panels, keeping them in some kind of matrix lookup (ie getComponentAt(gridx, gridy)) and use these to place your components onto instead.
So, for example. If you wanted to place a panel at grid 2x3, you would simply look at the panel at that grid location and place your components onto it.
ps- While I think about, you might also need repaint after revalidate if revalidate along doesn't work...
I have a dialog for a client-GUI that asks for the IP and Port of the server one wants to connect to. I have everything else, but how would I make it so that when the user clicks "OK" on my dialog box, that it runs something? Here's what I have so far:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class ClientDialog {
JTextField ip = new JTextField(20);
JTextField port = new JTextField(20);
GUI gui = new GUI();
Client client = new Client();
JOptionPane optionPane;
public void CreateDialog(){
Object msg[] = {"IP: ", ip, "\nPort: ", port};
optionPane = new JOptionPane();
optionPane.setMessage(msg);
optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = optionPane.createDialog(null, "Connect to a server");
dialog.setVisible(true);
if(dialog == JOptionPane.OK_OPTION){
System.out.println(ip);
String ipMsg = ip.getText();
int portMsg = Integer.parseInt(port.getText());
gui.CreateConsole(client, ipMsg, portMsg);
}
}
} //End class
I know that the code isn't correct, but what I want is that when the user hits "OK" on the dialog, I can run some code. Thanks!
I'd suggest to use showConfirmDialog instead
int result = JOptionPane.showConfirmDialog(myParent, "Narrative",
"Title", JOptionPane.INFORMATION_MESSAGE);
and there you can test for various returns value from JDialog/JOptionPane
if (result == JOptionPane.OK_OPTION,
JOptionPane.CANCEL_OPTION,
JOptionPane.CLOSED_OPTION, etc..
I'd suggest creating a JPanel and using JOptionpane.showConfirmDialog() (or even JOptionPane.showOptionDialog() to display the dialog and retrieve the option. Here's a modification of your code as an example:
import java.awt.*;
import javax.swing.*;
class ClientDialog {
private JTextField ip = new JTextField(20);
private JTextField port = new JTextField(20);
private JOptionPane optionPane;
private JPanel panel;
public void CreateDialog(){
panel = new JPanel(new GridLayout(2, 2));
panel.add(new JLabel("IP"));
panel.add(ip);
panel.add(new JLabel("Port"));
panel.add(port);
int option = JOptionPane.showConfirmDialog(null, panel, "Client Dialog", JOptionPane.DEFAULT_OPTION);
if (option == JOptionPane.OK_OPTION) {
System.out.println("OK!"); // do something
}
}
}
public class Test {
public static void main(String args[])
{
ClientDialog c = new ClientDialog();
c.CreateDialog();
}
}
Damn, took too long to post. Anyway just design the layout of the JPanel as you would for any other sort of frame.
Please understand that the 2nd parameter in a JOptionPane, the object parameter, can be any Swing component including a JPanel that holds a simple or complex GUI.
Consider creating a JPanel, placing a few components in it including JLabels and two JTextFields, one for IP, one for port, and then displaying this JPanel in a JOptionPane. Then you can easily check if OK has been pressed and act accordingly.
import javax.swing.*;
public class OptionEg {
public static void main(String[] args) {
final JTextField ipField = new JTextField(10);
final JTextField portField = new JTextField(10);
JPanel panel = new JPanel();
panel.add(new JLabel("IP:"));
panel.add(ipField);
panel.add(Box.createHorizontalStrut(15));
panel.add(new JLabel("Port:"));
panel.add(portField);
int result = JOptionPane.showConfirmDialog(null, panel,
"Enter Information", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
System.out.println("IP: " + ipField.getText());
System.out.println("Port: " + portField.getText());
}
}
}
Good solutions.
If you want not to use something else, this is a working example:
1) set DO_NOTHING_ON_CLOSE to ensure user MUST press OK
2) verify if the JDialog is still visible.
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setModal(false);
dialog.setVisible(true);
dialog.setAlwaysOnTop(true);
while(dialog.isVisible())try{Thread.sleep(50);}
catch(InterruptedException e){}
This can be a solution if you want to implement a non-modal dialog box.