I'm currently in a java class and I'm trying to work on build a my first interface. The one below is not the one I'm working on, but a test one so I can figure out how to do what I want to do. Here is the code, the question will follow:
package test;
import java.awt.*;
import java.awt.event.*;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import javax.swing.*;
/**
*
* #author StrifeX
*/
public class Test {
public static class buttonTest extends JFrame {
private int number;
private JButton push;
public ButtonTest(){
setLayout(new GridBagLayout ());
//Creates an instance of the layout
GridBagConstraints panel = new GridBagConstraints();
// Establishes the pixels suronding each object within the layout
panel.insets = new Insets (5, 5, 5, 5);
//create the withdraw button and its properties
push = new JButton("push");
panel.fill = GridBagConstraints.HORIZONTAL;
panel.gridx = 0;
panel.gridy = 0;
panel.gridwidth = 1;
add(push, panel);
MyEvent buttonClick = new MyEvent();
push.addActionListener(buttonClick);
}//end constructor
public class MyEvent implements ActionListener {
public void actionPerformed (ActionEvent buttonClick){
String operation = buttonClick.getActionCommand();
if(operation.equals("Withdraw")){
JOptionPane.showMessageDialog( null, "test" );
}
}
}
}//end button test
public static class TestObject{
int testField;
public void testObject(){
testField = 10;
}
public void setterMethod(int newInt){
this.testField = newInt;
}
public int getterMethod(){
return this.testField;
}
}
public static void main(String[] args)
{
TestObject obj1 = new TestObject();
buttonTest button = new buttonTest();
// Establish basic parameters for the GUI
button.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.setLocationRelativeTo(null);
button.setVisible(true);
button.setSize(450, 350);
button.setTitle("Change the Balance");
}
}
What I want to do is build an object, then use that objects methods with the GUI button. I can build the object, and pass it to the constructor that make the GUI (buttonTest), but the Event class cant see that object, and from the little I know, I can't pass it to the event class, but maybe the actionPerformed method like this:
public void actionPerformed (ActionEvent buttonClick, testObject thing)
However, when I tried to do that, I received and error that said
buttonTest.event is not abstract and does not override abstract method
actionPerformed(actionEvent) in ActionListener.
Any help would be greatly appreciated. Thank you.
The problem is wrongly defined the following:
public void actionPerformed (ActionEvent buttonClick, testObject thing)
The correct definition will be:
public void actionPerformed (ActionEvent buttonClick)
Getting passed all your previous issues and getting to the heart of the question
Passing objects to a gui in java
You basically need to pass the TestObject to all the classes which need access to it.
Start by modifying your MyEvent class to take a reference to TestObject
public class MyEvent implements ActionListener {
private TestObject obj;
public MyEvent(TestObject obj) {
this.obj = obj;
}
#Override
public void actionPerformed(ActionEvent buttonClick) {
String operation = buttonClick.getActionCommand();
// Now you have acces to obj
if (operation.equals("Withdraw")) {
JOptionPane.showMessageDialog(null, "test");
}
}
}
This will require you to modify your ButtonTest class to allow it to pass the TestObject through to the event handler...
public static class ButtonTest extends JFrame {
//...
public ButtonTest(TestObject obj) {
//...
MyEvent buttonClick = new MyEvent(obj);
//...
And finally, you create and pass the object to the instance of ButtonTest which needs it
public static void main(String[] args) {
TestObject obj1 = new TestObject();
ButtonTest button = new ButtonTest(obj1);
// Establish basic parameters for the GUI
button.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.setLocationRelativeTo(null);
button.setVisible(true);
button.setSize(450, 350);
button.setTitle("Change the Balance");
}
Related
I have 2 classes, the first class is where I am creating GUI and all of the components needed. Including the buttons. This is being done outside of the main method and in there own respective methods. I want to .addActionListener, but from another class outside of this one. I do not want to use inner classes.
Here is the classes containing Main and the Gui components and the button.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class PasswordGeneratorGui {
private JFrame interfaceFrame;
private JPanel interfacePanel;
private JMenuBar interfaceMenuBar;
private JMenu interfaceMenu;
private JMenuItem interfaceMenuItemFile;
private JButton interfaceButtonGenerate;
public static void main(String[] args) {
new PasswordGeneratorGui();
}
public PasswordGeneratorGui() {
createInterfacePanel();
createInterfaceFrame();
createInterfaceMenuBar();
createInterfaceMenu();
createInterfaceMenuItem();
createInterfaceButton();
PasswordGeneratorButtonHandler b = new PasswordGeneratorButtonHandler();
interfaceFrame.add(interfacePanel);
interfaceFrame.setVisible(true);
}
public void createInterfacePanel() {
interfacePanel = new JPanel();
interfacePanel.setLayout(null);
}
public void createInterfaceFrame() {
interfaceFrame = new JFrame();
interfaceFrame.setTitle("Password Generator");
interfaceFrame.setBounds(50, 50, 700, 400);
interfaceFrame.setResizable(false);
interfaceFrame.setJMenuBar(interfaceMenuBar);
}
public void createInterfaceMenuBar() {
interfaceMenuBar = new JMenuBar();
interfaceMenuBar.setBounds(0, 0, 700, 20);
interfaceMenuBar.setVisible(true);
interfacePanel.add(interfaceMenuBar);
}
public void createInterfaceMenu() {
interfaceMenu = new JMenu("File");
interfaceMenuBar.add(interfaceMenu);
}
public void createInterfaceMenuItem() {
interfaceMenuItemFile = new JMenuItem("Exit");
interfaceMenu.add(interfaceMenuItemFile);
}
**public void createInterfaceButton() {
interfaceButtonGenerate = new JButton("Generate");
interfaceButtonGenerate.setBounds(0, 358, 700, 20);
interfaceButtonGenerate.addActionListener();
interfacePanel.add(interfaceButtonGenerate);
}**
}
Here is the class for the ActionListener
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class PasswordGeneratorButtonHandler implements ActionListener {
PasswordGeneratorButtonHandler generate = new PasswordGeneratorButtonHandler();
public PasswordGeneratorButtonHandler() {
}
public void interfaceButtonGenerateHandler(ActionEvent event) {
System.exit(1);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
I just want to be able to call the AcitonListener method from the second class. I have tried initiating a new instance of the class and calling it however I think I wasn't quite going in the correct direction.
I'm a little confused about what your asking. You said
I just want to be able to call the AcitonListener method from the second class
Taken literally this means that while you're inside of the PasswordGeneratorButtonHandler class, you want to call the actionPerformed() method. If so, just use this.actionPerformed(), where this is a special keyword in java, representing the current instance of your class.
If however you want to add your handler to the button you created in the first class, which seems like what you might want to do, then you just need to call the JButton#addActionListener() method.
public PasswordGeneratorGui() {
createInterfacePanel();
createInterfaceFrame();
createInterfaceMenuBar();
createInterfaceMenu();
createInterfaceMenuItem();
createInterfaceButton();
PasswordGeneratorButtonHandler b = new PasswordGeneratorButtonHandler();
interfaceButtonGenerate.addActionListener(b); // Add handler to button
interfaceFrame.add(interfacePanel);
interfaceFrame.setVisible(true);
}
Also, inside of the PasswordGeneratorButtonHandler class, you instantiate an instance of the class called generate. This is unnecessary.
I have the class BossInfo which extends JPanel and has a few components like JLabel, JTextField. My main method is in another file ("DamageCalculator").
Basically, a value is entered into a JTextField via an action listener and I'd like to pass that value to a different file (to use it in calculations). I'm having a lot of trouble with the logic. Here is my class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BossInfo extends JPanel {
private JLabel bossLabel, resultLabel;
private JTextField bossHp;
String bossHpText = new String("");
int valRecd = 0;
public BossInfo() {
//Labels
bossLabel = new JLabel("Boss HP: (Hit Enter to set)");
resultLabel = new JLabel("---");
//Text field for user input of boss hp
bossHp = new JTextField(15);
bossHp.addActionListener(new TempListener());
//add components
add(bossLabel);
add(bossHp);
add(resultLabel);
} //end BossInfo object
public void setVal(int valRecd) {
this.valRecd = valRecd;
}
private class TempListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
int hp;
bossHpText = bossHp.getText();
hp = Integer.valueOf(bossHpText);
dc.setVal(hp);
resultLabel.setText(bossHpText);
}//end action performed
}//end TempListener
} //end class BossInfo
How can I use bossHpText in another class? The "actionPerformed" gets mad if it's any return type other than void so I'm not sure it's meant to return anything.
EDIT: Code updated based on suggestions.
Have a variable valRecd in the MainClass.
On your actionPerformed, call the setter method for this valRecd, e.g,
MainClass obj = new MainClass(); //in your constructor.
public void actionPerformed(ActionEvent event) {
int hp;
bossHpText = bossHp.getText();
hp = Integer.parseInt(text);
obj.setVal(hp); //add this line.
resultLabel.setText(bossHpText);
}
where setVal might be something like this:
public void setVal(int valRecd) {
this.valRecd = valRecd;
}
Still learning Java.
Again Swing has caused me to ask this but it is really a general OO question. If I have a master class (that contains main()) it creates a new object "A" that does something, the master class now has a reference to that object, how does object "B" get access to the attributes of that object?
The only way I can think of is for the master class to create a new object "B", passing object "A" as a parameter to the constructor, which I suppose is O.K. but doesn't this make event handling potentially difficult.
For example, and perhaps this is a poor design which is causing the problem. I have a master class with the programme logic, that creates a standard Swing frame, with a menu, the menu items having action listeners. But the actionlistener needs to interact with external objects.
So some code (ignoring the details) :
The main class, containing the programme logic and the save and load methods, etc :
public final class TheProgramme implements WindowListener }
private static final TheProgramme TP = new TheProgramme();
// Declare Class variables, instance variables etc.
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShewGUI();
}
});
}
private static void createAndShewGUI() {
TP.populateAndShew();
}
private void populateAndShew() {
final StandardFrame sF = new StandardFrame("TheProgramme");
theFrame = sF.getMainFrame();
theFrame.addWindowListener(this);
theFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
theFrame.pack(); theFrame.setVisible(true);
}
...
}
So we have created a standard frame object which has created a menu, empty panel and status bar, but with event listeners on the menu items :
public class StandardFrame {
// Declare instance variables that must be visible to the ActionListener inner class
public StandardFrame(String theTitle) {
mainFrame = new JFrame(theTitle);
mainFrame.setJMenuBar(createMenuBar()); // ... the menu bar and ...
mainFrame.setContentPane(createBlankPanel()); // ... a blank panel
java.net.URL imageURL = TheProgramme.class.getResource("images/icon.png");
if (imageURL != null) {
ImageIcon icon = new ImageIcon(imageURL);
mainFrame.setIconImage(icon.getImage());
}
}
public JMenuBar createMenuBar() {
ActionListener menuEvents = new MenuListener();
JMenuBar aMenuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File"); fileMenu.setMnemonic(KeyEvent.VK_F);
...
aMenuBar.add(fileMenu);
...
JMenuItem newItem = new JMenuItem("New", KeyEvent.VK_N); newItem.addActionListener(menuEvents);
newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
...
fileMenu.add(newItem);
...
return aMenuBar;
}
}
class MenuListener implements ActionListener {
public void actionPerformed(ActionEvent ae) {
String actionCommand = ae.getActionCommand();
switch (actionCommand) {
case "New":
// !!! here we need to call a method in an object to create a new document object !!!
break;
case "Reformat":
// !!! here we need to call a method in the object created above
}
}
}
The first problem is the actionlistener on the menu items calls a method to create an object but it is not a call to a static method.
The second problem is it needs to be be able to call a method in that new object later on as a result of another menu choice.
The classic way to do this in Model-View-Controller is to bind the objects together at runtime. The controller, your action listener, takes parameters to indicate which view and model it is to act on.
This use of parameters is also called "Dependency Injection," as Aqua mentions.
public static void main( String[] args )
{
Model model = new Model();
View view = new View();
ActionListener listener = new MyActionListener( model, view );
view.addActionListener( listener );
}
private static class MyActionListener implements ActionListener
{
private Model model;
private View view;
public MyActionListener( Model model, View view )
{
this.model = model;
this.view = view;
}
}
In Java you can cheat a little since the ActionEvent has a pointer to the source of the event (normally the view/JComponent that generated the event.
private static class MyActionListener implements ActionListener
{
private Model model;
public MyActionListener( Model model )
{
this.model = model;
}
#Override
public void actionPerformed( ActionEvent e )
{
JComponent source = (JComponent) e.getSource();
// source == "view"...
}
}
To set a new document, you can create a "document holder" class. The "new" menu item puts a new document in the holder class. All other menu items "get" the document from the holder class. This is a fairly strict OO paradigm which uses no static methods or fields, although it is a little tedious.
Set up:
public static void main( String[] args )
{
ModelDocumentHolder model = new ModelDocumentHolder();
View view = new View();
ActionListener listener = new NewDocument( model );
view.addActionListener( listener );
View view2 = new View();
view2.addActionListener( new RegularListener( model ) );
}
New document listener:
private static class NewDocument implements ActionListener
{
private ModelDocumentHolder model;
public NewDocument( ModelDocumentHolder model )
{
this.model = model;
}
#Override
public void actionPerformed( ActionEvent e )
{
model.setDoc( new Document() );
}
}
Most other menu items:
private static class RegularListener implements ActionListener
{
private ModelDocumentHolder model;
public RegularListener( ModelDocumentHolder model )
{
this.model = model;
}
#Override
public void actionPerformed( ActionEvent e )
{
JComponent source = (JComponent) e.getSource();
Document doc = model.getDoc();
// do stuff...
}
}
The holder class:
private static class ModelDocumentHolder
{
private Document doc;
public Document getDoc()
{
return doc;
}
public void setDoc( Document doc )
{
this.doc = doc;
}
}
Generally, (and it's really hard to know if this is an answer to your question, as it's quite vague) this is what setModel(...) and addListener(...) are for.
The "constructor coordinator" aka "master class", creates the models (the swing Model classes). It creates the views (JWidgets) and it sets the models of the views. In Swing it is easy to rely upon the default constructed model (populated with the JWidget default constructor), but maybe in your case, you should find the one widget causing problems and rewrite it make the model setting explicit.
If you have extended a Jwhatever, then keep in mind that setModel(...) typically does something like
if (this.model != null) {
this.model.removeListener(this);
}
// clear the cached last "view" of the model
clearCachedData(...);
if (model != null) {
this.model = model;
// restore the "view" of the new model.
grabCachedData(...);
this.model.addListener(this);
}
I hope my interpretation of the question is correct. You can inject/provide whatever object you need to the action implementation. Here is an example that uses an interface for better abstraction as a callback from actionPerformed. When action completes it call its callback to notify whoever is interested. In this case, the panel is notified and updates its text area with some text.
The interface:
public interface ActionCallback {
public void documentCreated(String name);
}
Here is the UI:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TestAction extends JPanel implements ActionCallback {
private JTextArea area;
public TestAction() {
setLayout(new BorderLayout());
area = new JTextArea();
add(new JScrollPane(area));
}
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void documentCreated(String name) {
area.append(String.format("Created %s\n", name));
}
public static class NewAction extends AbstractAction {
private ActionCallback callback;
private Component parent;
public NewAction(ActionCallback callback, Component parent){
super("New");
this.callback = callback;
this.parent = parent;
}
#Override
public void actionPerformed(ActionEvent e) {
String value = JOptionPane.showInputDialog(parent, "Name", "new name");
if (value != null){
callback.documentCreated(value);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
TestAction panel = new TestAction();
frame.add(panel);
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menuBar.add(menu);
JMenuItem item = new JMenuItem(new NewAction(panel, frame));
menu.add(item);
frame.setJMenuBar(menuBar);
frame.pack();
frame.setVisible(true);
}
});
}
}
Passing a reference of yourself (A) to an other object (B) tends to happen quite frequently in GUI code. You could use an context object, which you pass to all classes and which contains references to relevant references and might hold some global information. In simple cases, "main program class" is used as context and passed around.
Depending on what classes you use, this might also be useful: Component#getParent().
im struggling again, with doing a program in java that converts the temperature from celsius to fahrenhiet, but it must be done in a GUI so that the user may enter in a number for celsius and click a botton to convert it. ive been modeling it off of a example in my book however in the book it shows it working with out having a static main(), but my IDE gave me an error saying that it was needed, so ive added a static main() and ive tried calling the tempwindow() to see if that would work but still nothing and even if i comment out the call it doesnt give me a error but nothing happens.
im hopping someone can help show me what im doing wrong and how i should go about this.
import javax.swing.JOptionPane;
import javax.swing.*;
import java.awt.event.*;
public class tempcon extends JFrame
{
private JPanel panel;
private JLabel messageLabel;
private JTextField tempC;
// private JRadioButton tempF;
// private ButtonGroup radioButtonGroup;
private JButton calcButton;
private final int WINDOW_WIDTH = 400;
private final int WINDOW_HEIGHT = 100;
public tempwindow()
{
setTitle("Temurture convertion");
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buildPanel();
add(panel);
setVisible(true);
}
private void buildPanel()
{
messageLabel = new JLabel("enter tempurture in celsius");
tempC = new JTextField(10);
calcButton = new JButton("convert");
calcButton.addActionListener(new CalcButtonListener());
panel = new JPanel();
panel.add(messageLabel);
panel.add(tempC);
panel.add(calcButton);
}
private class CalcButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String input;
double temp;
input = tempC.getText();
temp = Double.parseDouble(input) * 1.8 + 32;
JOptionPane.showMessageDialog(null, "that is " + temp + "degrees fehrenhiet");
}
}
public static void main(String[] args)
{
tempwindow();
}
}
You are doing a few things wrong:
Your constructor can't have a different name from your class name
You need to instantiate the object to call the constructor, rather instantiating an object does call the constructor but you can't just access it like a method.
You should use the Java naming conventions for class names.
The class:
public class TempCon extends JFrame
{
// Variable declarations
public TempCon() // Constructor should match the Class name
{
}
}
The main class:
public static void main(String[] args)
{
TempCon converter = new TempCon();
}
public static void main(String[] args)
{
tempcon myTempWindowInstance = new tempcon();
myTempWindowInstance.tempwindow();
}
You never initialize a tempcon. Your constructor must have the same name as the class, so I recommend the following changes instead:
Replace public tempwindow() with public tempcon() to correct the constructor.
public tempcon()
{
setTitle("Temurture convertion");
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buildPanel();
add(panel);
setVisible(true);
}
create an instance of tempcon using new, which calls the constructor:
public static void main(String[] args)
{
tempcon myTempWindowInstance = new tempcon();
}
please write return type your function like.
public void tempwindow()
create object of class and call method.
public static void main(String[] args)
{
tempcon t=new tempcon();
t.tempwindow();
}
and learn java object java object oriented programming.
I wanted to change text in a JTextField by using actionlistener on a button.
there is a radiobutton group and Sort.SWITCH changes its value according to radiobutton selected.
So when sort button is pressed the text in Output field must change from "Output" to "Some text"..
but the error is that Output field cannot be accessed from innerclass. Plz tell me the proper way to do that. thanks..
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Sort extends JFrame
{
...
}
class q2 extends Sort
{
public static void main(String[] args)
{
...
JTextField Output = new JTextField(50);
Output.setText("Output");
ResultPanel.add(Output);
SortButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent a)
{
if (Sort.SWITCH == 1)
{
Output.setText("Some Text");
}
else if ...
...
} });
}}
To access your variable from inside the anonymous class, define the variable as a field (instead of a local variable), or as final:
public static void main(String[] args){
//...
final JTextField Output = new JTextField(50);
Anonymous inner-classes may only access fields or final variables from the defining class.
Define Output as a class field:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Sort extends JFrame
{
...
}
class q2 extends Sort
{
public JTextField Output;
public static void main(String[] args)
{
...
Output = new JTextField(50);
Output.setText("Output");
ResultPanel.add(Output);
SortButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent a)
{
if (Sort.SWITCH == 1)
{
Output.setText("Some Text");
}
else if ...
...
} });
}
}