I am designing a software with multiple components - each with its own actionlistener.
For an example, I have a JPanel with a cardlayout that holds 10 cards - each its own JPanel and purpose.
On one side, there are multiple buttons, I.E. Login, Logout, Settings, etc.
When I click Login, it will switch to the card using the Login() method to the Login JPanel object where I want it to wait for a button to click I.E. Login, New User, or Cancel before continuing the Login() method and setting the current user.
Is there a method to pause the program until one of the buttons are clicked to retrieve the data from it? (Kind of like how JOptionPane.showInputMessage(null,"INPUT STRING") waits for you)
My Code is below:
FRAME:
/**
* Frame design
*/
public class Frame extends JFrame{
JPanel LeftSide, UpperRightSide;
EmployeeAdder employAdd;
ArrayList<ServiceView> serviceViewers;
ChartViewer viewChart;
PayByView viewPayBy;
SettingsViewer viewSettings;
LoginViewer viewLogin;
CategoryView viewCategory;
ServiceAdder serviceAdd;
Directory directory;
Employee currentEmployee;
ChargeViewer viewCharge;
JButton Login, Logout, Settings;
CardLayout LeftCard,RightCard;
String currentCard,currentRightCard;
ButtonListen listen;
public static String CARDCAT = "Category View";
public static String CARDPAY = "Pay By";
public static String CARDCHART = "Chart View";
public static String CARDLOGIN = "Log-in View";
public static String CARDSERVICEADD = "Service Adder";
Frame(){
listen = new ButtonListen();
//-------Current Card--------------------
currentCard = CARDCAT;
currentRightCard = "CHARGE";
//-----First Find Directory Folder-------
startDirectory();
//-----User Interface--------------------
//-------Left Side-----------------------
LeftSide = new JPanel();
LeftCard = new CardLayout();
LeftSide.setLayout(LeftCard);
viewPayBy = new PayByView();
viewLogin = new LoginViewer();
viewChart = new ChartViewer();
viewCategory = new CategoryView();
employAdd = new EmployeeAdder();
serviceAdd = new ServiceAdder();
LeftSide.add(viewCategory,"CAT");
LeftSide.add(viewChart, "CHA");
LeftSide.add(viewLogin,"LOG");
LeftSide.add(viewPayBy,"PAY");
LeftSide.add(employAdd,"EMA");
LeftSide.add(serviceAdd,"SEA");
LeftCard.show(LeftSide, "CAT");
viewCategory.setEnabled(false);
LeftSide.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK),currentCard));
serviceViewers = new ArrayList<ServiceView>();
//--------Right Side---------------------
JPanel RightSide = new JPanel();
RightSide.setLayout(new BorderLayout());
UpperRightSide = new JPanel();
RightCard = new CardLayout();
UpperRightSide.setLayout(RightCard);
viewSettings = new SettingsViewer();
viewCharge = new ChargeViewer();
viewCharge.setEnabled(false);
UpperRightSide.add(viewCharge,"CHARGE");
UpperRightSide.add(viewSettings,"SETTINGS");
UpperRightSide.setPreferredSize(new Dimension(350,500));
RightSide.add(UpperRightSide,BorderLayout.NORTH);
//--------Buttons at the bottom Panel---
JPanel Buttons = new JPanel();
Buttons.setLayout(new GridLayout(3,1));
Login = new JButton("LOG-IN");
Login.addActionListener(listen);
Logout = new JButton("LOG OUT");
Logout.addActionListener(listen);
Settings = new JButton("Settings");
Settings.addActionListener(listen);
Buttons.add(Login);
Buttons.add(Logout);
Buttons.add(Settings);
Buttons.setPreferredSize(new Dimension(350,150));
RightSide.add(Buttons,BorderLayout.SOUTH);
RightSide.setSize(new Dimension(400,200));
//------Other Stuff--------------------------
//-----add Panels----------------------------
setLayout(new BorderLayout());
add(LeftSide,BorderLayout.WEST);
add(RightSide,BorderLayout.EAST);
}
private void Login(){
LeftCard.show(LeftSide, "LOG");
//----I WANT IT TO WAIT HERE FOR AN ACTION-------
int clicked = viewLogin.getClicked();
if (clicked==LoginViewer.NEWUSER){
NewUser();
}else if (clicked==LoginViewer.LOGIN){
if (viewLogin.checkPassword()){
currentEmployee = directory.getEmployee(viewLogin.getSelectedName());
viewCategory.setEnabled(true);
viewCharge.setEnabled(true);
viewCharge.refreshName(currentEmployee.getName());
LeftCard.show(LeftSide, "CAT");
}
}else if (clicked==LoginViewer.CANCEL){
LeftCard.show(LeftSide, "CAT");
}
}
public class ButtonListen implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if (!viewLogin.isWaiting()){
if (e.getSource()==Login){
if (currentCard.equals(CARDLOGIN)){
LeftCard.show(LeftSide,"CAT");
currentCard = CARDCAT;
}else{
Login();
currentCard = CARDLOGIN;
}
}else{
//Don't change the screen
}
}
}
}
}
My Code for LoginViewer:
public class LoginViewer extends JPanel{
JComboBox User;
JPasswordField passField;
JButton NewUser, Login, Cancel;
Hashtable<String,String> namespass; //names and password
private int clicked = -1;
ButtonListen listen;
public static int NEWUSER = 1;
public static int LOGIN = 0;
public static int CANCEL = 2;
boolean waiting;
LoginViewer(){
waiting = false;
//---------------------------------------
setPreferredSize(new Dimension(100,100));
listen = new ButtonListen();
namespass = new Hashtable<String,String>();
//----------Panel Design-------------------
JPanel Center = new JPanel();
Center.setLayout(new GridLayout(3,3));
User = new JComboBox();
passField = new JPasswordField();
NewUser = new JButton("New User");
NewUser.addActionListener(listen);
Login = new JButton("Login");
Login.addActionListener(listen);
Cancel = new JButton("Cancel");
Cancel.addActionListener(listen);
Center.add(new JLabel("Choose User"));
Center.add(User);
Center.add(new JLabel(""));
Center.add(new JLabel("Type Password"));
Center.add(passField);
Center.add(new JLabel(""));
Center.add(Login);
Center.add(NewUser);
Center.add(Cancel);
Center.setPreferredSize(new Dimension(300,300));
Center.setMaximumSize(new Dimension(100,100));
Center.setAlignmentX(CENTER_ALIGNMENT);
setAlignmentX(CENTER_ALIGNMENT);
setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
add(Box.createHorizontalGlue());
add(Center);
add(Box.createHorizontalGlue());
}
public void uploadUserNames(Hashtable<String,String> names){
namespass.clear();
namespass.putAll(names);
User.removeAllItems();
Enumeration<String> name = names.keys();
while (name.hasMoreElements()){
User.addItem(name.nextElement());
}
}
public boolean checkPassword(){
boolean value = false;
String key = User.getSelectedItem().toString();
if (passField.getPassword().length==4){
if (namespass.get(key).equals(String.valueOf(passField.getPassword()))){
value = true;
}
}
return value;
}
public String getSelectedName(){
return User.getSelectedItem().toString();
}
public boolean isWaiting(){
return waiting;
}
public int getClicked(){
waiting = true;
return clicked;
}
public class ButtonListen implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
waiting = false;
if (e.getSource()==NewUser){
clicked = 1;
}else if (e.getSource()==Login){
clicked = 0;
}else if (e.getSource()==Cancel){
clicked = 2;
}
}
}
}
Or is it easier to just use an actionlistener to listen to ALL of the objects' buttons?
There are a LOT of buttons...
NOTE: Some of the methods are incomplete or test methods until I know how to make it work...
You don't want to use linear console-type code in a Swing GUI. Instead, with event-driven GUI programs you will want to have user interactions change a program's state, and then have the behavior of the program depend on the state. For instance, rather than have the login method pause, have it do some housekeeping -- change the state of the program to be ready to accept a login attempt -- and then where you plan to "wait", exit the login method. Then have the rest of the code for logging in reside in the login button's ActionListener.
As an aside, you've posted a lot of code, 95% of it unrelated to your problem and thus only serving as a distraction to us and preventing us from reading the code and understanding the specifics of your problem. In the future, consider creating and posting an sscce, where you condense your code into the smallest bit that still compiles, has no extra code that's not relevant to your problem, but still demonstrates your problem for us.
the way the Swing framework works is that you already "wait" for everything to happen, and it only happens once the users triggers the action corresponding to your listener.
So yes, basically you only have to wait for buttons to be clicked.
HOWEVER:
Designing responsive GUIs means that you won't let your user wait 10 seconds on a frozen interface until you do yout 10000 calculations and 10 million SELECT statements. Thus in case your action listeners (or whatever specific listeners you've got) have to perform heavy duty calculations, do them on a separate Thread, and inform the user if a task is done one way or another.
Related
Ok, i am just a beginner programmer, so i am having a lot of difficulty in figuring this out. Basically i am trying to create a one digit calculator(meaning that calculations only occur with single digits of numbers). I have created the buttons, assigned them action listener and their classes, and all those stuff. And then i try to display those numbers to a label. Now the problem i have is, that, i have a button, which when clicked, will use a class. From that class, what i want to do is, remove all the buttons form the panel, and add new buttons. But when i try to remove the buttons, something weird happens. If i click that button, the buttons instead of getting removed/disappering, they stay there, but i cant interact with them. Any help to fix that? I want to completely remove them from the panel. Then i want to add new buttons in their place.
Here is the code of the main class
package onecalculator;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class code {
static JLabel see = new JLabel("Int a");
static JLabel no = new JLabel("Int b");
static JLabel lol = new JLabel("Answer");
static JPanel area = new JPanel();
static JButton secn = new JButton("next");
static JButton one = new JButton("1");
static JButton two = new JButton("2");
static JButton three = new JButton("3");
static JButton four = new JButton("4");
static JButton five = new JButton("5");
static JButton six = new JButton("6");
static JButton seven = new JButton("7");
static JButton eight = new JButton("8");
static JButton nine = new JButton("9");
static JButton bone = new JButton("1");
static JButton btwo = new JButton("2");
static JButton bthree = new JButton("3");
static JButton bfour = new JButton("4");
static JButton bfive = new JButton("5");
static JButton bsix = new JButton("6");
static JButton bseven = new JButton("7");
static JButton beight = new JButton("8");
static JButton bnine = new JButton("9");
static JButton div = new JButton("div");
static JButton mul = new JButton("mul");
static JButton add = new JButton("add");
public int a;
public int b;
public static void main(String[] args) {
JFrame screen = new JFrame("One Digit Calculator");
screen.setSize(400,600);
screen.setResizable(false);
screen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
screen.add(area);
area.add(see);
area.add(no);
area.add(lol);
area.add(secn);
area.add(one);
area.add(two);
area.add(three);
area.add(add);
area.add(four);
area.add(five);
area.add(six);
area.add(mul);
area.add(seven);
area.add(eight);
area.add(nine);
area.add(div);
secn.addActionListener(new secn());
two.addActionListener(new Twoc());
three.addActionListener(new Threec());
four.addActionListener(new Fourc());
five.addActionListener(new Fivec());
six.addActionListener(new Sixc());
seven.addActionListener(new Sevenc());
eight.addActionListener(new Eightc());
nine.addActionListener(new Ninec());
one.addActionListener(new Onec());
area.setLayout(new GridLayout(4,4));
screen.setVisible(true);
}
}
Then here is the code of the class that removes the buttons in the panel
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class secn implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
code.area.remove(code.one);
code.area.remove(code.two);
code.area.remove(code.three);
code.area.remove(code.four);
code.area.remove(code.five);
code.area.remove(code.six);
code.area.remove(code.seven);
code.area.remove(code.eight);
code.area.remove(code.nine);
code.area.add(code.bone);
code.area.add(code.btwo);
code.area.add(code.bthree);
code.area.add(code.bfour);
code.area.add(code.bfive);
code.area.add(code.bsix);
code.area.add(code.bseven);
code.area.add(code.beight);
code.area.add(code.bnine);
}
}
Please help.
What you would want to do is to call repaint() and revalidate() on the container (i.e. 'JPanel area') that holds you buttons. If you want to know exactly what repaint and revalidate do, have a look at this answer.
Below your code where you add your new buttons inside of the actionPerformed method, add the following to update the container:
code.area.repaint();
code.area.revalidate();
Keep in mind that this will cause your new elements to be added to the end of the elements that weren't deleted and in the order that you add them. You can use GridBagConstraints to select where which button is placed.
But I would say that removing the old buttons just to create new ones only for the purpose of entering the second value seems like a bad idea. Additionally, having separate ActionListeners for each button also seems a little wasteful.
I would propose having a global variable (boolean for example) to indicate whether you're using the first or second value.
static boolean isFirst = true;
When the 'next button' is pressed, you could then change this variable to 'false' and not remove any of the buttons. In your ActionListener you would just look at this variable to know whether to assign the pressed number to value a or value b.
For your ActionListener for the number buttons, I would propose to reuse one for all of them like this:
class MyListener implements ActionListener{
int value;
//when creating new instances of MyListener, you give each listener
//an int equivalent to the buttons value
MyListener(int value){
this.value = value;
}
#Override
public void actionPerformed(ActionEvent arg0){
if(isFirst){ //first value
a = value; //add value to your first number in any way you like
} else { //second value
b = value; //add value to your second number in any way you like
}
}
}
You would assign your ActionListener as follows:
two.addActionListener(new MyListener(2));
three.addActionListener(new MyListener(3));
I hope this is helpful and understandable. There are probably better ways to do it, but this would be my suggestion. I'm open to feedback on this.
The easiest solution would be to create a new JPanel instead of deleting the old buttons.
JPanel newArea= new JPanel();
//Add new buttons
code.area = newArea;
However i think you should consider redesigning your code. First of all you should not use static variables for your code class. Instead make them private and make a objekt of your code class.
public class code{
private JLabel see = new JLabel("Int a");
private JLabel no = new JLabel("Int b");
//...
public static void main(String[] args){
code mainClass = new code();
}
This allows you to use multiple instances of your code class instead of just one. Secondly you should not make a new class for every Actionlistener. Ecspecially since i think they are all doing the same. Also i dont think you even need to remake all the buttons. If you just want to save 2 values you can check if the first one has been set already:
class ButtonListener implements ActionListener{
int buttonValue;
code callingClass;
//Save the buttonn number and the calling class
MyListener(int buttonValue, code callingClass){
this.buttonValue = buttonValue;
this.callingClass = callingClass;
}
//If a is null set a, otherwise set b
public void actionPerformed(ActionEvent arg0){
if(callingClass.a == null){
callingClass.a = buttonValue;
} else {
callingClass.b = buttonValue;
}
}
}
In your code class you should then initialize a and b with null in your constructor, alongside all the stuff you preivously initialized in your main and use the ButtonListener class as your new actionlistener.
public code(){
a = null;
b = null;
//Initialize all the other stuff
secn.addActionListener(new ButtonListener(2, this));
}
Whenever you add or remove elements to a visible Swing component, you should use revalidate() (to recalculate its layout now that children have changed) and repaint() (to repaint the component itself), as suggested by Custos' answer.
However, there is the question of why you need to do this. You have two visually identical sets of digit-buttons, that only differ in how they handle clicks. There is no need to replace the buttons - just handle those differences by keeping a little bit of extra state (hasA and hasB varibales in my code below).
Since the introduction of lambdas (inline, anonymous functions), writing handler code for Java UIs has become much more readable and less verbose: note how my code below has 1-line handlers to bind the interface with actual logic, and how easy it would be to, say, add a new operator to the code below.
Note also that you do not need expose all graphical elements of a class as fields - here, digits and operators are only used to call digitPressed and operatorPressed, and lead to a smaller set of fields in the Calc class.
Also, by making Calc a subclass of JPanel, and avoiding any and all static fields, I can easily create multiple calculators operating side-by-side, independent of each other.
package one;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class Calc extends JPanel {
private JLabel labelA = new JLabel();
private JLabel labelB = new JLabel();
private JLabel labelAnswer = new JLabel();
private int a;
private int b;
private boolean hasA = false;
private boolean hasB = false;
public Calc() {
setLayout(new GridLayout(0, 4));
add(labelA);
add(labelB);
add(labelAnswer);
reset(); // rewrites labels, resets state
JButton reset = new JButton("reset");
add(reset);
reset.addActionListener((e) -> reset());
for (int i=1; i<10; i++) {
JButton b = new JButton("" + i);
add(b);
final int index = i; // for use in lambda
b.addActionListener((e) -> digitPressed(index));
}
for (String op : new String[] {"add", "mul", "div"}) {
JButton b = new JButton(op);
add(b);
final String index = op; // for use in lambda
b.addActionListener((e) -> operatorPressed(index));
}
}
private void reset() {
labelA.setText("value A: ?");
labelB.setText("value B: ?");
labelAnswer.setText("no operator");
hasA = hasB = false;
}
private void digitPressed(int i) {
if ( ! hasA) {
hasA = true;
a = i;
labelA.setText("value A:" + a);
} else if ( ! hasB) {
hasB = true;
b = i;
labelB.setText("value B:" + b);
}
}
private void operatorPressed(String operator) {
String answer = "???";
if (operator.equals("mul")) {
answer = "= " + (a * b);
} else if (operator.equals("div")) {
answer = "= " + (a / b);
} else if (operator.equals("add")) {
answer = "= " + (a + b);
}
labelAnswer.setText(answer);
}
public static void main(String[] args) {
JFrame screen = new JFrame("One Digit Calculator");
screen.setSize(400,600);
screen.setResizable(false);
screen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
screen.add(new Calc());
screen.setVisible(true);
}
}
Ok so In my code I'm asking the user for their name and asking them to click one of 3 buttons which gives a variable a corresponding value. Now in another program I want to call upon this program and then pretty much display the string and use the int value for a certain purpose.
public class MainMenuofgame extends JFrame implements ActionListener{
JButton slow, medium, fast;
JLabel pic1, pic2, pic3, pic4;
JTextField username;
Container frame;
static String name;
static int xspeed = 0;
public MainMenuofgame() {
super ("Main Menu of Rocket Launch");
frame = getContentPane ();
frame.setLayout (null);
pic1 = new JLabel (new ImageIcon ("welcome.png"));
pic2 = new JLabel (new ImageIcon ("name.png"));
pic3 = new JLabel (new ImageIcon ("speed.png"));
pic4 = new JLabel (new ImageIcon ("backgnd.jpg"));
username = new JTextField ();
slow = new JButton("Slow");
// slow.setActionCommand("slowspeed");
slow.addActionListener (this);
medium = new JButton("Medium");
// medium.setActionCommand("mediumspeed");
medium.addActionListener (this);
fast = new JButton("Fast");
// fast.setActionCommand("fastspeed");
fast.addActionListener (this);
pic1.setBounds (30,50, 525, 173);//welcome
pic2.setBounds (100,230,212,73);//name
pic3.setBounds (80,350,428,84);//speed
username.setBounds(310,255,150,30);
slow.setBounds (100,450,100,100);
medium.setBounds (250,450,100,100);
fast.setBounds (400,450,100,100);
//background bound goes in the end
pic4.setBounds (0,0, 600,900);
frame.add (pic1);
frame.add (pic2);
frame.add (pic3);
frame.add (username);
frame.add (slow);
frame.add (medium);
frame.add (fast);
frame.add (pic4);
setSize(600, 900);
setVisible (true);
setDefaultCloseOperation (EXIT_ON_CLOSE);
}
public void actionPerformed (ActionEvent evt){
String name = username.getText();
if (evt.getSource () == slow)
{
xspeed = 1;
}
else if(evt.getSource () == medium)
{
xspeed = 5;
}
else
{
xspeed = 10;
}
}
public static void main(String[] args) {
new MainMenuofgame ();
}
}
The behavior that you describe is not in fact the "transfer values of an int and string from one program to another in Java", but rather much more simply the transfer of data from one object to another, here the objects are represented by GUI components. Don't create two separate programs, but rather create separate objects that interact in a meaningful way. That is the essence of OOPs with Java. The simplest solution is to have the main application display the sub-application's GUI within a modal dialog such as a modal JDialog, and then once the dialog has been dealt with (i.e., is no longer visible) then the main program/object queries the dialog for the state of its components -- the data that was entered.
Also you are painting yourself in a corner by having your class extend JFrame, forcing you to create and display JFrames, when often more flexibility is called for. In fact, I would venture that most of the Swing GUI code that I've created and that I've seen does not extend JFrame, and in fact it is rare that you'll ever want to do this. More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding.
For example:
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class MenuDemoMainPanel extends JPanel {
private MenuPanel menuPanel = new MenuPanel();
private JDialog menuDialog = null;
private String name;
private Speed speed;
private JTextField nameField = new JTextField(10);
private JTextField speedField = new JTextField(10);
public MenuDemoMainPanel() {
// these fields are for display only and should not allow user
// interaction
nameField.setFocusable(false);
speedField.setFocusable(false);
// not kosher to set this directly, per kleopatra, but oh well
setPreferredSize(new Dimension(600, 400));
// simple demo GUI -- add components
add(new JLabel("Name:"));
add(nameField);
add(new JLabel("Speed:"));
add(speedField);
add(new JButton(new GetNameAndSpeedAction("Get Name And Speed")));
}
// action for JButton that displays the menuDialog JDialog
private class GetNameAndSpeedAction extends AbstractAction {
public GetNameAndSpeedAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
if (menuDialog == null) {
// if the menu dialog has not been created yet -- create it
Window win = SwingUtilities.getWindowAncestor(MenuDemoMainPanel.this);
menuDialog = new JDialog(win, "Menu", ModalityType.APPLICATION_MODAL);
menuDialog.add(menuPanel);
menuDialog.pack();
menuDialog.setLocationRelativeTo(win);
}
// display the menu JDialog
menuDialog.setVisible(true);
// this code is called only when the dialog is no longer visible
// query the dialog for the state it holds
name = menuPanel.getNameText();
speed = menuPanel.getSpeed();
// and display the state in the main GUI
if (name != null && speed != null) {
nameField.setText(name);
speedField.setText(speed.getText());
}
}
}
private static void createAndShowGui() {
// create the main GUI JPanel
MenuDemoMainPanel mainPanel = new MenuDemoMainPanel();
// then create an application GUI
JFrame frame = new JFrame("Menu Demo -- Main GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel); // place the main panel into the GUI
// and pack and display it:
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
// JPanel to hold menu dialog components
#SuppressWarnings("serial")
class MenuPanel extends JPanel {
private JComboBox<Speed> speedCombo = new JComboBox<>(Speed.values());
private JTextField nameField = new JTextField(10);
public MenuPanel() {
speedCombo.setSelectedIndex(-1);
add(new JLabel("Name:"));
add(nameField);
add(new JLabel("Speed:"));
add(speedCombo);
add(new JButton(new SubmitAction("Submit")));
}
// allow outside classes to query the nameField JTextField's state
public String getNameText() {
return nameField.getText();
}
// allow outside classes to query the speedCombo JComboBox's state
public Speed getSpeed() {
return (Speed) speedCombo.getSelectedItem();
}
// Action for JButton that submits the dialog to the main GUI
private class SubmitAction extends AbstractAction {
public SubmitAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// if the data is not all entered or selected
if (nameField.getText().trim().isEmpty() || speedCombo.getSelectedIndex() == -1) {
Component comp = MenuPanel.this;
String msg = "You must enter your name and select a speed";
String title = "Invalid Data";
int msgType = JOptionPane.ERROR_MESSAGE;
// warn the user and leave this dialog still visible
JOptionPane.showMessageDialog(comp, msg, title, msgType);
} else {
// otherwise dispose of this dialog and thereby pass control
// back to the main application / GUI
Window win = SwingUtilities.getWindowAncestor(MenuPanel.this);
win.dispose();
}
}
}
}
// an enum to encapsulate possible game speeds
enum Speed {
SLOW("Slow"), MEDIUM("Medium"), FAST("Fast");
private String text;
private Speed(String text) {
this.text = text;
}
public String getText() {
return text;
}
#Override
public String toString() {
return getText();
}
}
There are one of two ways that come to mind on how to transfer information from one program to another...
Client-Server applications
This requires you to have a third application running accepting information from each of the other two application (clients) through a socket. For further information Google "Client-Server applications in Java"
Have a text file passing information
To do this you should have a text file that one application stores information in and the other application just simply reads it... This is an easier solution but is less of a learning experience. Here is example code.
Application 1:
private void storeMessage(String msg){
File centralFile = new File("path to your file");
BufferedWriter writer = new BufferedWriter(new FileWriter(centralFile));
writer.write(msg);
writer.close();
}
Application 2:
private String getMessage(){
File centralFile = new File("path to your file");
String msg = "";
BufferedReader reader = new BufferedReader(new FileReader(centralFile));
while (reader.hasNextLine()){
msg += reader.nextLine();
}
reader.close();
return msg;
}
Hope this helps
Um... really all I needed to do was call upon my variable that I wanted to store my data in and then well... store it. This is done in the If statement at the bottom. Thanks everyone for helping but honestly most of your answers rised more questions than answered mine and just confused me but I figured it out so thanks anyways :)
public class MainMenuofgame extends JFrame implements ActionListener{
JButton slow, medium, fast;
JLabel pic1, pic2, pic3, pic4;
JTextField username;
Container frame;
static String name;
static int xspeed = 0;
public MainMenuofgame() {
super ("Main Menu of Rocket Launch");
frame = getContentPane ();
frame.setLayout (null);
pic1 = new JLabel (new ImageIcon ("welcome.png"));
pic2 = new JLabel (new ImageIcon ("name.png"));
pic3 = new JLabel (new ImageIcon ("speed.png"));
pic4 = new JLabel (new ImageIcon ("backgnd.jpg"));
username = new JTextField ();
slow = new JButton("Slow");
// slow.setActionCommand("slowspeed");
slow.addActionListener (this);
medium = new JButton("Medium");
// medium.setActionCommand("mediumspeed");
medium.addActionListener (this);
fast = new JButton("Fast");
// fast.setActionCommand("fastspeed");
fast.addActionListener (this);
pic1.setBounds (30,50, 525, 173);//welcome
pic2.setBounds (100,230,212,73);//name
pic3.setBounds (80,350,428,84);//speed
username.setBounds(310,255,150,30);
slow.setBounds (100,450,100,100);
medium.setBounds (250,450,100,100);
fast.setBounds (400,450,100,100);
//background bound goes in the end
pic4.setBounds (0,0, 600,900);
frame.add (pic1);
frame.add (pic2);
frame.add (pic3);
frame.add (username);
frame.add (slow);
frame.add (medium);
frame.add (fast);
frame.add (pic4);
setSize(600, 900);
setVisible (true);
setDefaultCloseOperation (EXIT_ON_CLOSE);
}
public void actionPerformed (ActionEvent evt){
String name = username.getText();
Rocketlaunch.name = name;
if (evt.getSource () == slow)
{
Rocketlaunch.moveSpeed = 1;
Rocketlaunch.speed = "Slow";
setVisible (false);
}
else if(evt.getSource () == medium)
{
Rocketlaunch.moveSpeed = 5;
Rocketlaunch.speed = "Medium";
setVisible (false);
}
else
{
Rocketlaunch.moveSpeed = 10;
Rocketlaunch.speed = "Fast";
setVisible (false);
}
new Rocketlaunch();
}
public static void main(String[] args) {
new MainMenuofgame ();
}
}
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.
I have an application that uses JDialog popups. I'm using 1.6 (compatibility requirement for the customer.) The ENTER key dismisses the dialog, taking previous results. The problem is that the user can type-ahead on hitting the ENTER key (or any other text for that matter).
Here's a snippet:
private void promptForCredentials(final GenericSwitch sw) {
final JDialog jd = new JDialog();
jd.setModal(true);
jd.getContentPane().setLayout(new FlowLayout());
final JLabel l_user = new JLabel("Username: ");
final JLabel l_pass = new JLabel("Password: ");
final JTextField tf_user = new JTextField(25);
final JTextField tf_pass = new JPasswordField(25);
JButton b_ok = new JButton("OK");
JButton b_same = new JButton("Same as previous");
JButton b_cancel = new JButton("Cancel");
final JLabel l_authfail = new JLabel("Authentication failed, try again.");
ActionListener okSameListener = new ActionListener() {
public void actionPerformed(ActionEvent ev) {
// if (((JButton) ev.getSource()).isVisible()) {
// return; // always returns for 'OK' button!
// }
String name = ((JButton) ev.getSource()).getText();
if (name.equals("OK")) {
// If user hits OK, save user/pw, unless they're both empty
// (treat that as "use last")
if (! tf_user.getText().isEmpty()
&& ! tf_pass.getText().isEmpty()) {
mLastUsername = tf_user.getText();
mLastPassword = tf_pass.getText();
}
}
jd.dispose();
sw.setUsername(mLastUsername, true);
sw.setPassword(mLastPassword, true);
if (!sw.checkLogin()) {
// auth failed so don't save for next time
mLastUsername = "";
mLastPassword = "";
}
display(sw.mIndex);
poll();
}
};
b_ok.addActionListener(okSameListener);
b_same.addActionListener(okSameListener);
b_cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
System.out.print("Poll cancelled\n");
abort();
jd.dispose();
}
});
Box box0 = Box.createHorizontalBox();
Box box1 = Box.createHorizontalBox();
Box box2 = Box.createHorizontalBox();
Box box3 = Box.createHorizontalBox();
box0.add(l_authfail);
box1.add(l_user);
box1.add(tf_user);
box2.add(l_pass);
box2.add(tf_pass);
box3.add(b_ok);
box3.add(Box.createHorizontalStrut(10));
if (!mLastUsername.isEmpty() && !mLastPassword.isEmpty()) {
box3.add(b_same);
box3.add(Box.createHorizontalStrut(10));
}
box3.add(b_cancel);
if (sw.authFailed()) {
jd.add(box0);
}
jd.add(box1);
jd.add(box2);
jd.add(box3);
SwingUtilities.getRootPane(b_ok).setDefaultButton(b_ok);
jd.setTitle("Login for " + sw.mShortname);
jd.setPreferredSize(new Dimension(400, 150));
jd.setSize(new Dimension(400, 150));
jd.setLocationRelativeTo(getContentPane());
jd.setVisible(true);
}
Since this app polls a number of external resources, most of which usually have the same username/pw, it's nice to just hit "enter" to cycle through the lot, the first time. All good. (And yeah, I know I should have "use same for subsequent" checkbox. Maybe later.)
However, I noticed to my surprise that I can type ahead. Frankly, I like this, but I don't think it's really appropriate for general users. How can I disable it?
Would it work to consume all actions prior to setting the JDialog visible? I tried checking if the button is visible, but while the Cancel button is, the OK button isn't! (commented out above)
Thanks
Hey all I have one question I am new to GUI stuff so I need some help when I want to add an element to a window using some other method or if statement I don't get error but it doesn't show up hears a code I marked problem I am working in java by the way this is not whole program but only this is a problem
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Gui extends JFrame{
private JTextField usernameTF;
private JPasswordField passwordField;
private String username,password;
private JRadioButton A,B,C,D,F;
//private JComboBox box;
private JLabel logo,errorPic,promt;
private JButton logIn;
private boolean value;
private Apples function= new Apples();
public Gui(){
super ("Awsome Progrma");
setLayout(new FlowLayout());
Icon errorIcon = new ImageIcon(getClass().getResource("wrong.png"));
errorPic = new JLabel(errorIcon);
usernameTF = new JTextField(10);
usernameTF.setToolTipText("Enter your user name hear");
add(usernameTF);
passwordField = new JPasswordField(10);
passwordField.setToolTipText("Enter your password hear");
add(passwordField);
logIn = new JButton("Log IN");
add(logIn);
usernameTF.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
username = event.getActionCommand();
password = passwordField.getText();
value = function.chack(username,password);
if (value == true){add(errorPic);} // this is a problem JLabel dosn't show up in my window
}
}
);
passwordField.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
username = usernameTF.getText();;
password = event.getActionCommand();
value = function.chack(username,password);
if (value == true){add(errorPic);} // this is a problem JLabel dosn't show up in my window
}
}
);
logIn.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
username = usernameTF.getText();
password = passwordField.getText();
value = function.chack(username,password);
if (value == true){add(errorPic);} // this is a problem JLabel dosn't show up in my window
}
}
);
}
}
The only GUI element that won't show up is the Jlabel errorPic. This is because the container needs to be validated after the component has been added. You need to call:
revalidate();
repaint();
after adding the JLabel. A better approach would be to add a JLabel with no image when adding components to the JFrame and later simply call JLabel.setIcon to update the label.
Some side notes:
Don't extend JFrame. Instead create an instance of the window component directly.
JPassword.getText is deprecated. Safer to use JPassword.getPassword instead.
Consider using Initial Threads at application startup.