I see this has been asked multiple times and apologize in advance if I'm just missing something simple...
I've created a custom JDialog with the examples provided in the Java docs here and from a similar question asked here.
My main application is a JFrame that contains a JPanel with an array of JButtons that display various employee names. I've added a custom ActionListener to each JButton that calls the mentioned JDialog:
//inner class for handling user button pushes
private class UserButtonHandler implements ActionListener
{
//handle button event
#Override
public void actionPerformed(ActionEvent event)
{
statusDialog = new ChangeDialog(statusWindow);
statusDialog.setVisible(true);
statusDialog.setLocationRelativeTo(null);
//set title for dialog box
String dialogTitle = "Status change for " + event.getActionCommand();
statusDialog.setTitle(dialogTitle);
statNum = ((ChangeDialog) statusDialog).getInputStatus();
System.out.println("Current num is: " + statNum);
//statNum = statusDialog.getInputStatus();
}
}
Here is the class for the custom JDialog (ChangeDialog):
class ChangeDialog extends JDialog implements ActionListener, PropertyChangeListener
{
//create panel where users can modify their status
private final ChangePanel empStatusChangePanel;
//text of buttons in dialog
private String btnString1 = "OK";
private String btnString2 = "Cancel";
private String btnString3 = "Clear Time-Off";
private JOptionPane statusPane;
//determines message to return for user input
private int inputStatus;
public ChangeDialog(JFrame statusFrame)
{
empStatusChangePanel = new ChangePanel();
//create an array specifying the number
//of dialog buttons and their text
Object[] options = {btnString1, btnString2, btnString3};
//create the JOptionPane
statusPane = new JOptionPane(empStatusChangePanel,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.YES_NO_CANCEL_OPTION,
null,
options,
options[0]);
//set contents of dialog
setContentPane(statusPane);
//handle window closing
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
//register event handler for changes in status pane state
statusPane.addPropertyChangeListener(this);
pack();
}
#Override
public void actionPerformed(ActionEvent e)
{
statusPane.setValue(btnString1);
}
#Override
public void propertyChange(PropertyChangeEvent e)
{
String prop = e.getPropertyName();
if (isVisible()
&& (e.getSource() == statusPane)
&& (JOptionPane.VALUE_PROPERTY.equals(prop)))
{
Object value = statusPane.getValue();
if (value == JOptionPane.UNINITIALIZED_VALUE)
{
//ignore reset
return;
}
//Reset the JOptionPane's value. If this is not done,
//then if the user presses the same button next time,
//no property change event will be fired
statusPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
if(value.equals(btnString1)) //user clicked "OK"
{
//validation of user input
inputStatus = empStatusChangePanel.validateUserInput();
//handle validation results
switch (inputStatus)
{
case 0: //user input is good
JOptionPane.showMessageDialog(this, "Good input given");
dispose();
break;
case 1: //one (or both) of the date pickers are empty
JOptionPane.showMessageDialog(this, "PTO pickers can't be empty.",
"ERROR", JOptionPane.ERROR_MESSAGE);
break;
case 2:
case 3: //bad date range (start before end or visa-versa)
JOptionPane.showMessageDialog(this, "Bad date range.",
"ERROR", JOptionPane.ERROR_MESSAGE);
break;
case 99: //dates are equal
JOptionPane.showMessageDialog(this, "Single-day PTO");
dispose();
break;
}
}
else if(value.equals(btnString3)) //user clicked "Clear Input"
{
JOptionPane.showMessageDialog(this, "User clicked 'clear input");
//more processing should be done here
empStatusChangePanel.recycle();
//dispose();
}
else //user clicked "Cancel" or closed dialog
{
JOptionPane.showMessageDialog(this, "User closed status window");
dispose();
}
}
}
//returns value from user validation
public int getInputStatus()
{
return inputStatus;
}
}
I need to access the method getInputStatus from the custom dialog but each attempt I've tried comes back stating that:
getInputStatus is undefined for the type JDialog
I have looked at several other similar posts but feel that I'm missing something fundamental in trying to solve this problem (or I've been looking at the code too long).
Another thing that has me stumped (and why I left it in the first snippet) is that if I cast the method to the type ChangeDialog
statNum = ((ChangeDialog) statusDialog).getInputStatus();
It suddenly has access (this was a suggestion from Eclipse and doesn't make sense to me). Thanks again for any and all help.
That is how inheritance works, you have defined statusDialog as a JDialog reference and JDialog doesn't have a getInputStatus method.
To access the members of ChangeDialog, you have to define statusDialog as variable of ChangeDialog.
Related
I've set a JTextField visibility to false, and when I click a button it is supposed to immediately show but it doesn't until I resize the window.
I'm building a login/'sign up' app using Swing containing tree text fields (Username, password and confirm password (which visibility is set to false until I press the signup button). But the text field does not appear until I resize the window and I can't seem to figure out what the problem is. I used the same 'code structure' as I did in another project, and didn't have any problem at all.
You can see the code below:
setTxtusername(new JTextField("Entrez username",20));
getTxtusername().setVisible(true);
setTxtpassword(new JTextField("Entrez Password",20));
getTxtpassword().setVisible(true);
setTxtconfirmer(new JTextField("Confirmer Password",20));
getTxtconfirmer().setVisible(false);
setBtnlogin(new JButton("Login"));
getBtnlogin().setVisible(true);
getBtnlogin().addActionListener(l);
getBtnlogin().setActionCommand("login");
setBtnsignup(new JButton("Sign up"));
getBtnsignup().setVisible(true);
getBtnsignup().addActionListener(l);
getBtnsignup().setActionCommand("Signup");
//Hb is an horizontal box and Vb is a vertical one
getHb2().add(btnlogin);
getHb2().add(btnsignup);
getHb2().add(warninglabel);
getHb2().setVisible(true);
getVb().add(txtusername);
getVb().add(txtpassword);
getVb().add(txtconfirmer);
getVb().add(hb2);
getVb().setVisible(true);
pnl.add(vb);
pnl.setVisible(true);
Here is the ActionListener
public class Listener implements ActionListener{
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String action = e.getActionCommand().toString();
switch(action){
case "login":
break;
case "Signup":
ConfirmerVisible(true, txtconfirmer);
conteneur.revalidate();
creationCompte();
break;
}
}
public void creationCompte() {
if(getTxtconfirmer().getText().length() >=6 && getTxtpassword().getText() == getTxtconfirmer().getText()) {
if(admin.isSelected()) {
Utilisateur u = new Utilisateur(txtusername.getText(), getTxtpassword().getText(), 1);
//Connexionuser.create(u);
//Connexionuser.login(u)
}
}
}
}
private void ConfirmerVisible(boolean b, Component c) {
c.setVisible(b);
}
}
To refresh GUI Use:
revalidate();
repaint();
I guess once you doing "resize" it's triggered automatically by JFrame and recursively triggering refresh on child components also.
Could you help me with this little problem?
I'm trying to make a menu system which shows the options in a JEditorPane, it's something like this:
Welcome
Select an option.
1.) New register.
2.) New input.
3.) Exit.
the options are chosen by the user through a JTextField, when "1" is entered it shows another menu:
New register
1.) Option X.
2.) Option Y.
3.) Back.
and so on, the problem is that I don't know how I can capture the user's input, advance to the next menu, and re-capture the user's input all in a JTextField.
textField.addActionListener(new ActionListener () {
public void actionPerformed(ActionEvent e) {
String cap = "";
cap = textField.getText();
switch(cap) {
case "1":
paintEditorPane("Welcome");
// here is my problem, I don't know how to re-capture JTextField input
switch(cap){
case "1":
paintEditorPane("NewRegister");
break;
}
break;
}
}
});
Here's Basic. Now you have to make many cases to judge states.
public static class MainPanel extends JPanel{
private JTextArea textArea;
public MainPanel() {
this.setLayout(new BorderLayout());
this.textArea = new JTextArea();// you can use constructor to set Text but I like use method "setText".
this.textArea.addKeyListener(new keyHandler());
this.textArea.setText("Welcome\r\nSelect an option. 1.) New register. 2.) New input. 3.) Exit.\r\n");
this.textArea.setCaretPosition(this.textArea.getText().length());// move caret to last
this.add(this.textArea, BorderLayout.CENTER);
}
public void addText(String text) {textArea.setText(textArea.getText() + "\r\n" + text +"\r\n");}
public class keyHandler extends KeyAdapter{
#Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_1 : addText("New register"); break;
case KeyEvent.VK_2 : addText("New input"); break;
case KeyEvent.VK_3 : addText("Exit"); break;
}
}
}
}
Its my first time programming checkboxes; I figured out how to make a checkbox appear, and do a command when checked. However, when the box is unchecked, instead of undoing the command, it instead does the command a second time. How can I undo the command when unchecking the box?
Code: (instantiation of checkboxes)
negA = new JCheckBox("Neg");
negA.addActionListener(this);
negA.setActionCommand("A-5");
tossupA = new JCheckBox("Tossup");
tossupA.addActionListener(this);
tossupA.setActionCommand("A10");
powerA = new JCheckBox("Power");
powerA.addActionListener(this);
powerA.setActionCommand("A05");
Command:
public void actionPerformed(ActionEvent e)
{
//get the String value from the button pressed
String result = e.getActionCommand();
char team = result.charAt(0);
//set text on screen to reflect new score
String screenText = "Team "+(team)+"'s total score for this tossup: ";
//add score to subtotal and show on screentext
if(team=='A'){
teamATempScore += Integer.parseInt(result.substring(1));
screenText += teamATempScore;
}
//and now for B
else if(team=='B'){
teamBTempScore += Integer.parseInt(result.substring(1));
screenText += teamBTempScore;
}
When the box is unchecked, I want the score to decrement by the amount that it was incremented, but instead the score just increments again :(
Thanks!
(yes, if you were wondering, this is a scorekeeping program for a game of Quizbowl) :D
The listener just checks to see if the checkBox was clicked -- It doesn't check if it went from unchecked to checked, or vice versa.
Use the .isSelected() method to determine whether the checkbox is checked or not after it becomes clicked.
For example:
if (negA.isSelected())
{
//the checkbox was checked after they clicked it, do something
}
else
{
//the checkbox was unchecked after they clicked it, do something else
}
You have to check the state of the control and then either increment or decrement. The compiler cannot auto generate the reverse of your code.
To check the state of the checkbox, you call the isSelected() method on it like in the example below.
import javax.swing.JOptionPane;
public class CheckboxExample extends javax.swing.JFrame {
private javax.swing.JCheckBox jCheckBox1;
public CheckboxExample() {
jCheckBox1 = new javax.swing.JCheckBox();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new java.awt.FlowLayout());
jCheckBox1.setText("CheckMe");
jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
jCheckBox1ActionPerformed(evt);
}
});
getContentPane().add(jCheckBox1);
pack();
}
// this will get called when the state of the checkbox changes
private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {
if(jCheckBox1.isSelected()) {
JOptionPane.showMessageDialog(this, "Checked", "Message",
JOptionPane.INFORMATION_MESSAGE);
}
else {
JOptionPane.showMessageDialog(this, "Unchecked", "Message",
JOptionPane.INFORMATION_MESSAGE);
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new CheckboxExample().setVisible(true);
}
});
}
}
I have a simple game in which I have a JOptionPane popup giving the choice of YES or NO.
So if the user hits NO then the game shuts down ofcourse however if the user hits YES I want the game to restart.
I have got this to work by the following : (Just by calling the main() method again.
main.Main.main(null);
The problem :
It's starting another instance of the game however the previous instead is there as well.
How can I close the previous instance before starting a new instance? or what other ways are there to get around this?
Here is the class code with the JOptionPane
public void popupWinMessage(String message)
{
//default icon, custom title
int n = JOptionPane.showConfirmDialog(
null,
message,
"",
JOptionPane.YES_NO_OPTION);
if(n == JOptionPane.YES_OPTION){
JOptionPane.showMessageDialog(null, "Alright, here we go again");
main.Main.main(null);
}
else {
JOptionPane.showMessageDialog(null, "Thanks for playing the battleships game");
System.exit(0);
}
Here is my updated main method (I'm still pretty confused on what is going on):
package main;
imports
public class Main {
public Controller theController = new Controller(new Game(), new Frame());
/**
* #param args
*/
public static void main(String[] args)
{
newGame();
}
public static void newGame()
{
theController.;
}
}
The directory of my whole game looks like this
http://i.imgur.com/7iKJQwu.png
The method where the JOption pane is located is in the view's Frame class.
public Controller(final Game newGame, final Frame newView)
{
this.game = newGame;
this.view = newView;
this.view.setVisible(true);
//Gets the board arrays into these local variables here for us to use
playerBoard = newGame.DisplayPlayerBoard();
computerBoard = newGame.DisplayCompBoard();
colourGrids();
this.view.addGridActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent ae)
{
Object o = ae.getSource();
if(o instanceof JButton)
{
JButton btn = (JButton) o;
int xValue = (Integer) btn.getClientProperty("row");
int yValue = (Integer) btn.getClientProperty("column");
int tempShipType = computerBoard[xValue][yValue];
newGame.tryHitComputer(xValue, yValue);
btn.setEnabled(false);
if(tempShipType != -1)
{
if(newGame.checkShipStatus(tempShipType) == true)
{
System.out.println(shipDowns[tempShipType]);
newView.popupMessage(shipDowns[tempShipType]);
}
}
//Code here for the computer to try hit your ships
newGame.tryHitPlayer();
colourGrids();
System.out.println(newGame.isGameWon());
if (newGame.isGameWon() == true)
{
System.out.println("Game has been won, do something to stop it at some point");
newView.popupWinMessage("Game has been won\nDo you wish to play again?");
}
if (newGame.isGameLost() == true)
{
System.out.println("Game has been lost, the silly AI has beaten you\nDo you wish to play again?");
newView.popupWinMessage("Game has been lost, the silly AI has beaten you\nDo you wish to play again?");
}
}
else
{
System.out.println("The listener was not attached to a JButton as expected - " + o.getClass());
}
}
});
}
Don't call the main method again. Have a start() method which starts your game and get the dialog to call that when the answer is "yes"
One option is to add a restartGame() method to your Controller class. Since you call popupWinMessage() from the Controller constructor, you can modify it to take a Controller object and pass it the this reference. Then popupWinMessage() method can simply call the restartGame() method on the instance that is passed to it.
I am following the Oracle tutorial on how to create a custom dialog box: http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html
I have two buttons: Save Object and Delete Object which when clicked should execute a certain piece of code. Unfortunately I can't seem to add any ActionListener to the JOptionPane buttons so when they're clicked nothing happens.
Can anyone help tell me how I can go about doing this? Here is the class I have for the dialog box so far:
class InputDialogBox extends JDialog implements ActionListener, PropertyChangeListener {
private String typedText = null;
private JTextField textField;
private JOptionPane optionPane;
private String btnString1 = "Save Object";
private String btnString2 = "Delete Object";
/**
* Returns null if the typed string was invalid;
* otherwise, returns the string as the user entered it.
*/
public String getValidatedText() {
return typedText;
}
/** Creates the reusable dialog. */
public InputDialogBox(Frame aFrame, int x, int y) {
super(aFrame, true);
setTitle("New Object");
textField = new JTextField(10);
//Create an array of the text and components to be displayed.
String msgString1 = "Object label:";
Object[] array = {msgString1, textField};
//Create an array specifying the number of dialog buttons
//and their text.
Object[] options = {btnString1, btnString2};
//Create the JOptionPane.
optionPane = new JOptionPane(array,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.YES_NO_OPTION,
null,
options,
options[0]);
setSize(new Dimension(300,250));
setLocation(x, y);
//Make this dialog display it.
setContentPane(optionPane);
setVisible(true);
//Handle window closing correctly.
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
/*
* Instead of directly closing the window,
* we're going to change the JOptionPane's
* value property.
*/
optionPane.setValue(new Integer(
JOptionPane.CLOSED_OPTION));
}
});
//Ensure the text field always gets the first focus.
addComponentListener(new ComponentAdapter() {
public void componentShown(ComponentEvent ce) {
textField.requestFocusInWindow();
}
});
//Register an event handler that puts the text into the option pane.
textField.addActionListener(this);
//Register an event handler that reacts to option pane state changes.
optionPane.addPropertyChangeListener(this);
}
/** This method handles events for the text field. */
public void actionPerformed(ActionEvent e) {
optionPane.setValue(btnString1);
System.out.println(e.getActionCommand());
}
/** This method reacts to state changes in the option pane. */
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if (isVisible()
&& (e.getSource() == optionPane)
&& (JOptionPane.VALUE_PROPERTY.equals(prop) ||
JOptionPane.INPUT_VALUE_PROPERTY.equals(prop))) {
Object value = optionPane.getValue();
if (value == JOptionPane.UNINITIALIZED_VALUE) {
//ignore reset
return;
}
//Reset the JOptionPane's value.
//If you don't do this, then if the user
//presses the same button next time, no
//property change event will be fired.
optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
if (btnString1.equals(value)) {
typedText = textField.getText();
String ucText = typedText.toUpperCase();
if (ucText != null ) {
//we're done; clear and dismiss the dialog
clearAndHide();
} else {
//text was invalid
textField.selectAll();
JOptionPane.showMessageDialog(
InputDialogBox.this,
"Please enter a label",
"Try again",
JOptionPane.ERROR_MESSAGE);
typedText = null;
textField.requestFocusInWindow();
}
} else { //user closed dialog or clicked delete
// Delete the object ...
typedText = null;
clearAndHide();
}
}
}
/** This method clears the dialog and hides it. */
public void clearAndHide() {
textField.setText(null);
setVisible(false);
}
I think you're missing the point of the JOptionPane. It comes with the ability to show it's own dialog...
public class TestOptionPane02 {
public static void main(String[] args) {
new TestOptionPane02();
}
public TestOptionPane02() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JTextField textField = new JTextField(10);
String btnString1 = "Save Object";
String btnString2 = "Delete Object";
//Create an array of the text and components to be displayed.
String msgString1 = "Object label:";
Object[] array = {msgString1, textField};
//Create an array specifying the number of dialog buttons
//and their text.
Object[] options = {btnString1, btnString2};
int result = JOptionPane.showOptionDialog(null, array, "", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, "New Object", options, options[0]);
switch (result) {
case 0:
System.out.println("Save me");
break;
case 1:
System.out.println("Delete me");
break;
}
}
});
}
}
To do it manually, you're going to have to do a little more work.
Firstly, you're going to have to listen to the panel's property change events, looking for changes to the JOptionPane.VALUE_PROPERTY and ignoring any value of JOptionPane.UNINITIALIZED_VALUE...
Once you detect the change, you will need to dispose of your dialog.
The you will need extract the value that was selected via the JOptionPane#getValue method, which returns an Object. You will have to interrupt the meaning to that value yourself...
Needless to say, JOptionPane.showXxxDialog methods do all this for you...
Now if you worried about having to go through all the setup of the dialog, I'd write a utility method that either did it completely or took the required parameters...but that's just me
UPDATED
Don't know why I didn't think it sooner...
Instead of passing an array of String as the options parameter, pass an array of JButton. This way you can attach your own listeners.
options - an array of objects indicating the possible choices the user
can make; if the objects are components, they are rendered properly;
non-String objects are rendered using their toString methods; if this
parameter is null, the options are determined by the Look and Feel
For the flexibility you seem to want you should have your class extend JFrame instead of JDialog. Then declare your buttons as JButtons:
JButton saveButton = new JButton("Save"); and add an actionListnener to this button:
saveButton.addActionListener();
either you can put a class name inside the parenthesis of the saveButton, or you can simply pass it the keyword 'this' and declare a method called actionPerformed to encapsulate the code that should execute when the the button is pressed.
See this link for a JButton tutorial with more details:
http://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html