Java jbutton in another class - java

I'm trying to make a button in a class which removes something from a table. I have it working when it's not in a separate class. However, when I try and move the code to a new class and create an object of that class in my main method, the button doesn't work. I'm pretty new to using Swing, so any help will be much appreciated.
public abstract class RemoveButton extends frame implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
DefaultTableModel model = (DefaultTableModel) table.getModel();
if (table.getSelectedRow() == -1) {
if (table.getRowCount() == 0) {
Mess.setText("Table is empty");
} else {
Mess.setText("You need to select");
}
} else {
model.removeRow(table.getSelectedRow());
}
}
}
}
This class is the button which is supposed to remove a guest. I extended the frame, because that is where most of my variables are. From here, I am not so sure as of how to call this to my main method and get it working. All the imports have been added.

I'm going to guess here, which we're forced to do since the question as written presently is incomplete, but I suspect that you're misusing inheritance. I'm guessing that your main GUI is held by the frame class (which should be re-named to comply with Java standards so that it's first letter is upper case), and are doing this so that this class can call methods and access fields of the frame class. If so, then you're using inheritance for the wrong purpose since the "frame" instance held by RemoveButton is unique and completely different from the frame instance that is displayed.
Instead, you should pass into this class a reference to the actual displayed frame object, and then call methods on this object as needed.
e.g.,
// why abstract? I've removed that
// no longer extends frame
public class RemoveButton implements ActionListener {
// I've renamed your frame class to "MyFrame"
private MyFrame myFrame;
// constructor that allows you to pass in MyFrame reference
public RemoveButton(MyFrame myFrame) {
this.myFrame = myFrame; // assign to field
}
public void actionPerformed(ActionEvent evt) {
JTable table = myFrame.getTable(); // give MyFrame this method
DefaultTableModel model = (DefaultTableModel) table.getModel();
// .... etc
}
}
Cleaner would be to use a MVC design pattern, but that would require some more up-front work.

Related

Cannot change public variable type in a subclass

I need to make a subclass changing variable type.
My purpuse is to create a class that dynamically loads objects onto a form. This form can be a JFrame or JInternalFrame, so I want a class leading a property form that can be one of JFrame / JInternalFrame, so I can write methods and functions without duplicate code.
Something like
public class form {
public javax.swing.JFrame frm;
...... methods and functions.
public void init(String title)
{
frm = new JFrame(title);
}
}
and
class form_children extends form {
public javax.swing.JInternalFrame frm;
public void init(String title)
{
frm = new JInternalFrame(title);
}
}
so that when I use them I can do something like this
public form_to_create (String title, Boolean mdi_child)
{
if (mdi_child)
frm = new form_children();
else
frm = new form();
frm.init();
frm.dosomething -----> error for null object
}
but when I use an mdi_child, it gives me error for null object.
It seems that frm variable for super class is present, but frm for subclass is not.
Why?
I need to make a subclass changing variable type.
My purpose is create a class that dynamically loads objects onto a form. This form can be a JFrame or JInternalFrame, so I want a class leading a property Form that can be one of JFrame / JInternalFrame, so I can write methods and functions without duplicate code.
You are painting yourself in a corner by having your class extend JFrame, JInternalFrame or other top-level (or internal top-level) window, as this forces you to create and display these types of windws, 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, JInternalFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding.
Your child object has two "frm" properties. The JInternalFrame frm you added in its own definition and the Frame frm it inherited from its father.
Because of polymorphism in form_to_create you are accessing the frm from the superclass, which is not initialized, instead of the JInternalFrame one.
A solution would be to encapsulate the behaviour in methods.
public class Form {
JFrame frm;
public void init(String title){
frm = new JFrame(title);
}
public void doSomething(){
frm.doSomething();
}
}
public class Form_child{
JInternalFrame frm;
public void init(String title){
frm = new JInternalFrame(title);
}
public void doSomething(){
frm.doSomething();
}
}
And your form_to_create would look like this now:
public static void form_to_create(String title, Boolean mdi_child){
Form frm;
if (mdi_child) {
frm = new Form_child();
}else{
frm = new Form();
}
frm.init(title);
frm.doSomething();
}
By doing it this way, you are only exposing the behaviour through the doSomething() method, and the rest of the program doesn't care if a JFrame or a JInternalFrame is the one behind.
Even better, make an Interface that defines the common behaviour and have both form classes implement it. That way Form_child doesn't inherit a JFrame property it doesn't use.
Thanks.
I want to dynamically create my form, and view that as mdichild window or not child window.
Read an file from disk, analyze it and add panels, controls to my form, so decide if my form has to be a child in a jDesktopPanel as JInternalFrame or simply a JFrame without dependencies.
I thought Java was powerful... but I guess it is not possible.

How to add an anonymous instance off a class as an ActionListener

Im working on a lab that requires me to make a JFrame with 2 inner classes. One that entends JPanel, has a text area and a jbutton. And another that implements action listener. How do i add an anonymouse instance of the second class to my JButton that is already in an inner class. Here is the brief to get a better understanding.
here is the code i have written so far. I can get the Frame to appear, but the JPanel doesnt appear, nor does the JButtons or JTextArea.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class FormFrame extends JFrame
{
public static void main(String[] args)
{
JFrame frame = new FormFrame();
frame.setLocationRelativeTo(null);
}
public FormFrame()
{
Container contentPane = getContentPane();
RegisterPanel p = new RegisterPanel();
p.button.addActionListener(new SubmitResponder());
//
// Here is where im lost...
//
contentPane.add(p);
setSize(300, 200);
setVisible(true);
}
class RegisterPanel extends JPanel
{
JPanel panel = new JPanel();
JTextField text = new JTextField();
JButton button = new JButton("Submit");
}
class SubmitResponder implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()== RegisterPanel.button) //Asks me to make button static here
{
//Shows "No enclosing instance of the type FormFrame.RegisterPanel is accessible in scope"
RegisterPanel.this.text.setText("Submit Complete");
}
}
}
}
Any help with this would be much appreciated
You could pass the RegisterPanel instance to the action listener:
class SubmitResponder implements ActionListener {
private final RegisterPanel rp;
public SubmitResponder(RegisterPanel rp) {
this.rp = rp;
}
#Override
public void actionPerformed(ActionEvent e) {
rp.text.setText("Submit Complete");
}
}
There's no need to check the source btw. The AL is only listening to 1 source.
RegisterPanel p = new RegisterPanel();
p.button.addActionListener(new SubmitResponder(p));
p.button.addActionListener(new SubmitResponder());
Here the SubmitResponder is already an anonymous instance, quite literally, because it has no name.
Your error about "no enclosing instance" is unrelated. Since SubmitResponder is not an inner class of RegisterPanel (it's a sibling) it doesn't belong to an instance of RegisterPanel and so it cannot logically refer to RegisterPanel.this. How would it know which instance that is? There might be many, or even zero, depending on how many the parent FormFrame decides to create. It so happens that there's only one, but that's not the point. On the other hand if you said FormFrame.this there would be no doubt what that meant no matter the code did, unless RegisterPanel stopped being an inner class or it became static. Does that make sense?
To do what you want, the SubmitResponder needs to talk to RegisterPanel via a method in FormFrame. Incidentally you don't actually need to say FormFrame.this.doSomething() unless SubmitResponder also has a method called doSomething.
The instructions tell you that the RegisterPanel should be a field in the FormFrame class, which you haven't done. Something like this:
public class FormFrame extends JFrame
{
RegisterPanel panel;
...
public FormFrame()
{
panel = new RegisterPanel();
...
}
...
class SubmitResponder implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == panel.button)
{
panel.text.setText(...);
}
}
}
}
Now you can access panel from inside the SubmitResponder class.
As a side note, the instructions are using some terminology in an ambiguous and incorrect way:
"Anonymous instance" is not an official term with a precise meaning.
Using official definitions, "class field" would imply the static modifier. Given the context of the assignment, I doubt that's correct. It should probably have said "instance field".

ActionEvent confusion

I'm very new to Java and I'm confused about the ActionEvent class.
I was under the impression that to use a class you had to create a new object for example:
SomeClass aClass = new SomeClass();
But in this piece of code:
private class theHandler implements ActionListener{
public void actionPerformed(ActionEvent event){
Event.getSource()
// etc...
}
}
How come you don't need to:
ActionEvent event = new ActionEvent();
Event become an instance of the ActionEvent class without having explicitly tell it.
I'm sorry of this is a dumb question, I'm teaching my self Java, and this is thoroughly confusing to me.
ActionEvent is created somewhere, but it's just not being created explicitly by you. Rather, it's being created in the JButton's code (actually the code is in the AbstractButton class, a parent class for JButton) for notifying all ActionListeners that listener are attached to it. You can view the source file to see the details if you desire.
When you use implements in Java, what you are doing is using an interface. Interfaces require certain methods to be implemented in your code and offer a way to ensure new classes that implement a certain interface have methods that can be called.
Thus, in your example:
private class theHandler implements ActionListener{
public void actionPerformed(ActionEvent event){
event.getSource()
// etc...
}
}
The ActionListener interface is being implemented by theHandler and therefore the method, actionPerformed(ActionEvent event) is required to be implemented by your class. There is no explicit ActionEvent event = new ActionEvent(); being created here because the ActionEvent is actually being passed through as a parameter to actionPerformed and is otherwise being created somewhere else.
Specifically for your example, you can also do the following instead of using the implements keyword on your class:
public class theHandler {
public theHandler() {
JButton button = new JButton();
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// do some stuff here
}
});
}
}
It's really quite simple, there is a thing called static methods. These are methods you can use from a class without making objects of them.
Like the Math class and all it's functions fx. a static method could look like this:
public class HiClass {
public static String sayHi() {
return "Hi!";
}
}
You would then use it in some context like this:
System.out.println( HiClass.sayHi() );
This would print out the string the method returns in your console.
You might ask "why wouldnt I just make all my methods in my classes static then?" there are many reasons, main one I can think of is that when you program you always try to restrcit responsibilities to classes that makes sense, so that the code is more manageable and easier to alter as the program grows.
This is not specific to the context your mentioning though, but it seemed to me your real question is how you can use methods without creating an object?
Hope it answers your question?

Separate my ActionListener from my GUI class, doesn't work properly

This is how my code looked in the beginning: https://gist.github.com/anonymous/8270001
Now I removed the ActionListener to a separate class: https://gist.github.com/anonymous/8257038
The program should give me a little UI, but it just keeps running without any UI popup or errors.
Someone told me this:
In your GUI class constructor, you are creating a new nupuVajutus object, but since nupuVajutus extends the GUI class, when you create a nupuVajutus, you are also inherently calling the GUI class constructor by default, thus creating an infinite loop
If this is really the problem, then I have to say I am not that good and could use some help getting this program working with the classes separated.
You have indeed already been given the answer, although what you have is not an infinite loop, but infinite recursion, which will eventually cause a StackOverflowError.
Here's what happens:
new GUI() calls new nupuVajutus(). This creates a new nupuVajutus object by calling its constructor. Because nupuVajutus extends GUI, this means a nupuVajutus object is a GUI object with additional functionality. Therefore, because it is a GUI object, a GUI constructor needs to be called. The nupuVajutus constructor does not explicitly call a super constructor, so it implicitly calls the GUI() (no argument) constructor before executing. In this new call to the GUI() constructor, another new nupuVajutus() call is encountered, and so on, ad infinitum...
It seems to me you need to do some more research around Object Oriented Programming, in particular the topics of sub-classing, inheritance, object instances, and encapsulation. There are plenty of resources available to help you.
After you extracted your ActionListener into a separate file, you should not have changed it to extend GUI. That extends the class (which is like a blueprint) not an instance (which is like a something built using that blueprint) - remember: you can create multiple instances of a class.
Previously, the "nupuVajutus" ActionListener was an inner class, so it had access to all of the enclosing class' fields and methods. Now that it is no longer an inner class, it needs to be passed a reference to the GUI instance so that it can access its methods. Something like this:
public class NupuVajutus implements ActionListener {
private final GUI gui;
public NupuVajutus(GUI gui) {
this.gui = gui;
}
public void actionPerformed(ActionEvent e) {
// The GUI instance can now be accessed through the gui field, for example:
gui.something();
// ...
}
}
And in the GUI() constructor:
NupuVajutus nV = new NupuVajutus(this);
To be honest, though, there is nothing wrong with keeping your ActionListener as an inner class. If you're never going to use that class outside of the GUI class, then it is probably preferable for it to remain as an inner class.
What you are doing it extending the GUI class. This Does Not make then share the Same Fields Say you have a field field in your GUI class
public class GUI {
String field = "Hello";
}
Just because your Listener class extends GUI doesn't mean they will share the exact same field object. I think that's what you think is supposed to occur
public class Listener extends GUI implements ActionListener {
public void actionPerformed(ActionEvent e) {
field = "World";
}
}
The above does nothing the field in GUI. If you were to do this, you would need to access in a static way like line GUI.field = "World";. The above is also what causes in an infinite loop, as you need to instantiate the Listener in the GUI class. This is not really good practice or design.
One option would to use some sort of MVC pattern.
Another option would be to pass the values you need, to a constructor in your Listener class, and instantiate it in your GUI class with those values.
Run this example to see what I'm talking about. I have a MyListener class that I pass a Jlabel to, the same JLabel in the GUI class
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class FieldTest {
private JLabel label = new JLabel(" ");
private JButton button = new JButton("Set Text");
public FieldTest() {
MyListener listener = new MyListener(label);
button.addActionListener(listener);
JFrame frame = new JFrame();
frame.add(label, BorderLayout.CENTER);
frame.add(button, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new FieldTest();
}
});
}
}
class MyListener implements ActionListener {
JLabel label;
public MyListener(JLabel label) {
this.label = label;
}
#Override
public void actionPerformed(ActionEvent arg0) {
label.setText("Hello, FieldTest!");
}
}

Clarification in reaching components, Java Swing

I’m relatively new to using the javax.swing and java.awt so bear with me if I express my problem awkwardly.
Let’s say I have a custom made class CustomClass that extends and creates a JPanel p. In the class I add a JButton b to p. Later in another program file I create an instance of my CustomClass called cp and want to be able to catch for example a click event from b using the “actionPerformed” method. My question is how do I “reach” (like the written path to) the JButton b from instance cp? (Assuming that all relevant class files are already associated)
Use getters and setters if i understood correctly. I,e your customPanel will have a public getButton() method which would return the JButton instance:
class CustomPanel extends JPanel {
JButton button=new JButton("Some button");
public JButton getMyButton() {
return button;
}
}
class Test {
CustomPanel cp=new CustomPanel();
void someMethod() {
JButton b= cp.getMyButton();
}
}
UPDATE
as per comment:
what if I have like 10 or 20 different components in my JPanel, is
there some way to reach them without having to make a lot of methods
Simply call getComponentCount on JPanel instance and than iterate using a for loop and getComponentAt(int i) this will allow you to get access to all components on JPanel:
CustomPanel cp=...;//this class extends jpanel
for(int i=0;i<cp.getComponentCount();i++) {
Component c=cp.getComponentAt(i);
if( c instanceof JButton) {
//do something
}
}
UPDATE 2
What if I have two or more objects that should be of the same class
but otherwise treated as separate objects, how can I tell them apart
using the loop that you've provided me
look at setName(String name) and getName of JButton this will allow you to assign the instance a unique name which can be gotten by getName(). Alternatively use setActionCommand(String name) and getActionCommand() to differentiate the buttons from another I prefer the latter.
Or you could even use their texts, via getText()

Categories