Making objects for each button - java

I need to make objects for my buttons in my typing tutor.
I have made a class:
public class KeyLabel extends JLabel {
public KeyLabel(String name) {
setText(name);
}
this is my subclass
my superclass is the keyboard class
and I need to make objects for each button on my keyboard for my typing tutor, so the a is a label its the keyboard
but I don't know how to do this?

I don't know why are you extending JLabel if you are to create Buttons. Extending JLabel will create a JLabel which will be wasted as in your code. More relavent code would be like
public class KeyLabel {
public KeyLabel(String name) {
JButton buttonOK = new JButton("OK"); //creates OK button
}
}
Moreover, i think you should look here, for details.

In most cases, you'll want to use inheritance (i.e. subclass JButton). For instance,
public abstract JKeyboardButton extends JButton{
public JKeyboardButton(final String key){
super(key);
// include other stuff, if necessary
}
// include other methods common to all JKeyboardButton instances
}
And then for each concrete button, you'll want to subclass JKeyboardButton, like so
public final class JKeyboardAButton extends JKeyboardButton{
public JKeyboardAButton(){
super("a");
}
// override/implement other methods..
}
And then in order to obtain a keyboard key of, let's say a, all you have to do is create an instance of JKeyboardAButton, like so
final JKeyboardButton aButton = new JKeyboardAButton();
And then obviously you'll have to create a class for each key and throw all these instances into a Keyboard class. But I'll leave the "heavier" coding to you.
Also, please note that the final modifier is not required, but rather is a personal preference of mine (i.e. to prevent subclassing and to ensure that a variable (even local ones) are only assigned once).

Related

How do you add new functions to pre-existing java components?

To explain what I mean by this question I will use code examples below. Imagine you have this function.
private void fadeButton(JButton b, int timeToFade) {
//Fade code goes here
}
How would you implement this as a function which could be run like
JButton b = new JButton("Press Me");
b.fadeButton(20000);
Where fadeButton now looks like
private void fadeButton(int timeToFade) {
//Fade code goes here
}
Because the function is declared on the button itself.
Typically you create a derived class:
public JFadableButton extends JButton
This will contain the method private void fadeButton(int timeToFade).
Short answer is: you don't.
Longer answer:
You can't do that in Java directly (adding methods to a class outside of the source code of that class). That might be different in other languages, like Kotlin offers "something" like that.
In java, you have to make detours, for example by turning to the decorator pattern.
And just for the record: I didn't mention the simple "you can extend that class" because I read your question as "how do I add methods to JButton directly". But of course, creating your own class that extends JButton allows you to add methods; but of course, they only exist on objects of your derived class.
You could extend JButton with a new class, thus inheriting JButton's methods and adding the ability to add your own code:
public class FadingButton extends JButton {
//Constructors go here
private void fadeButton(int timeToFade) {
//Fade code goes here
}
}
You could also decorate the JButton with another class:
public class JButtonDecorator {
private JButton btn;
//Constructor here
private void fadeButton(int timeToFade) {
//Fade code goes here, hiding the held button
}
//getter and setter method for button
}
Or, if you want lots of different ways to affect your UI, you can make a utility class, similar to above:
//You could use a factory pattern to make this a singleton instead of having static methods
public abstract class UIUtils {
private UIUtils{} //Don't instantiate this class
public static void fadeComponent(JComponent toFade) {
//Fade code goes here
}
//Other static utility methods
}
Edit: Making use of these patterns. The extended class is self-explanatory and an example of simple inheritance, so it's just a matter of JButton btn = new FadingButton(); for example. Here are the others:
To use the decorator, instantiate it at the same scope as the button you're using now. For example:
JButton myButton = new JButton();
//Customize button and add to UI
JButtonDecorator jbDec = new JButtonDecorator(myButton);
jbDec.fadeButton(20000);
Although the button is a field of the decorator, it will otherwise behave normally in your UI. The decorator just wraps the class with useful methods such as the fadeButton method.
To use the utility class, there are two ways. One is two make an abstract class with static methods (as above), some consider it bad form but it's good for simple programs:
UIUtils.fadeComponent(myButton); //It's just that simple!
//The UIUtils class itself is never instantiated.
//All the methods are static, so no instances are needed.
Or if you want a more advanced method, make your utility class a singleton. This changes the utility class to this:
public class UIUtils {
UIUtils singleton;
private UIUtils{} //Don't instantiate this class publicly
public static UIUtils getInstance() {
if(singleton==null) //This is the first time the method is called
singleton = new UIUtils();
return singleton; //Return the one instance of UIUtils
}
public void fadeComponent(JComponent toFade) {
//Fade code goes here
}
//Other utility methods
}
Then you would declare your UIUtils object at class level to use across your UI:
UIUtils uiUtil = UIUtils.getInstance();
And somewhere in your code:
uiUtil.fadeComponent(myButton);
This pattern is more efficient with memory and is more object-oriented, but I don't personally find it very suitable for utility classes.
You can create a new class which extends JButton, and then add any method that could help you achieve what you want. But that's an exemple, there is many ways to achieve this.
Ps, don't set this method as private if you want to use it somewhere else than inside your class.
This is the simplest way I think think of. You have already got it. But just use this method:
private void fadeButton(int timeToFade) {
//Fade code goes here
}
This is assuming you already have the code for the fade, do you? I think this one is the one you should use. You don't need the button to be a parameter. When you want to call the method to fade the button, just put it in the ActionListener. So after you have the ActionListener for the button, do the following: btnName.fadeButton(timeToFade);
Here is how to code the ActionListener:
btnHome.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
}

Java, enum with constructor

I'm refactoring some legacy system written in Java, and I came across a problem with an enum constructor.
I have an enum class like this (just an example):
public enum Signal{
ON(new InButton()),
OFF(new OutButton())
private final Button button;
Signal(Button button) {
this.button = button;
}
}
InButton and OutButton extends the Button interface.
The enum values are accessed for the first time using Signal.Values() method.
(Also, in one of the Button method, I have a code that uses the enum, such as activateButton(Signal.ON))
While refactoring the code, I wanted to create a new constructor for Button that express it dependency, such as Button(String input).
The problem is that I don't know how to pass the new parameters to the enum button field.
What is the right way to deal with this situation?
Is this enum should be used at all?
Clarification after Jean Logeart question: InButton and OutButton also have a constructor with a String arguments.
I'd rather avoid it to be initialize to null because than it could create other problems.
Basically this question is how to mimic a=f(x) using java syntax. Most of the time I can do:
y = new x(); a = new f(y);
a = new f(new x());
a = new f(null); a.getF().setX(new x());
In this case I can't do it.
I suggest not having the enums know about the buttons at all. Just have them enumerate the possible signals, and put the job of mapping signal->button somewhere else:
Function<Signal, Button> signalToButton = ...
That will also make it easier to inject different buttons for testing; for instance, you can inject a mocked Button that confirms that it was our wasn't pressed.
As far as using that mapping in your code: you can "install" a mapping to some static field, or, better yet, provide it as a constructor argument to any code that needs it. Dependency injection is very helpful for the latter option, but that may be a bigger change.
Two main options.
First one, InButton and OutButton also have a constructor with a String argument in which case you need to provide a String when instanciating:
public class InButton extends Button {
public InButton(String s) {
super(s);
}
}
// ...
public enum Signal{
ON(new InButton("in"))
// ...
}
Second option, InButton and OutButton are instanciated with a specific String in which case no refactoring is necessary in the enum:
public class InButton extends Button {
public InButton() {
super("in"); // default value
}
}
// ...
public enum Signal{
ON(new InButton()) // same as before
// ...
}

Access a public non-static object from another separate class [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am trying to create my own Font Chooser class in another separate class from the file where I have my main class (a JFrame application), and I would like to access to the textArea object of the main JFrame, in order to modify its font properties, but I am not able to do it, because the textArea is a non-static object.
To solve this problem, I have thought to make the separate class ("Font Chooser") an inner class. In this the only solution?
EDIT
The Font Chooser object is instantiated after the creation of the main Frame, in fact the instantiation is done by the main JFrame class, and apparently I cannot access to the main JFrame public members.
Thanks.
My main recommendation: don't ignore OOP practices to solve your problem, such as by using public fields and such. Don't have another class directly manipulate the state of your JTextArea which should be private anyway. Instead, give the class that holds the JTextArea a public setFont method that other classes can call on valid instances of the containing class.
public class MyGui {
private JTextArea textarea = .....;
public void setTextAreaFont(Font font) {
textarea.setFont(font);
}
So for an object to call this method, all it needs is a valid reference to the MyGui class, with valid being the key term here. This may require that you pass the reference into the object that needs it by a setter method or a constructor parameter. There is no need to use an inner class here, none at all.
And of course, the JTextArea field should never be static as that would throw all OOP to the wind, making it very difficult maintaining, enhancing or testing your code.
Edit
You now state:
The "Font Chooser" object is instantiated after the creation of the main Frame, in fact the instantiation is done by the main JFrame class, and apparently I cannot access to the main JFrame public members.
Then what is stopping you from passing the GUI class into your font chooser on its creation?
MyFontChooser myFontChooser = new MyFontChooser(this); // ???
Again, please tell the details of your problem.
class MyFontChooser {
private MyGui myGui;
public MyFontChooser(MyGui myGui) {
this.myGui = myGui;
}
// some event caused method
public void changeFont() {
myGui.setTextAreaFont(someFont);
}
What you need is to have a reference to the JFrame you want to modify. I'm assuming your code looks something like this:
class MyFrame extends JFrame{
public JTextArea textArea = new JTextArea();
public MyFrame(){
super();
FontChooser fc = new FontChooser();
fc.applyFont();
}
}
class FontChooser{
public void applyFont(){
Font f;
//code to set font values
MyFrame.textArea.setFont(f);//Won't work, because textArea isn't static
}
}
What you need is something like this
class MyFrame extends JFrame{
public JTextArea textArea = new JTextArea();
public MyFrame(){
super();
fc.applyFont(textArea)
}
}
class FontChooser{
public void applyFont(JTextArea textArea){//Notice the added parameter
Font f;
//code to set font values
textArea.setFont(f);//Will work, because we have an instance of the object we want to modify.
}
}
Obviously this needs to be modified for your code, but that's the idea. You need to pass a reference to the Object you want to modify.

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()

How can I have two classes share the same variable definitions

What I really need is to be able to declare regular variables in an interface and implement that interface in two classes that I would not have to have to re-declare these in each class (ie class.data.variables instead of class.variables). Is there any way that I could achieve the same goal differently?
To give more detail. Essentially, I have created a small drawing program that drops JLabels on a JPanel that is on a JScrollPane. Because I have a specific design for these JLabels (ie they are not just for drawing they represent airline objects for this application), I have a class that extends JLabel and adds my application specific variables to it. Ultimately, I read and write an XML file with these variables so they can load and save their designs. Since I can not use this extended class for my XML definitions because it screams about the parent class even though I told it to have NONE as the accessor (I read there is a bug), I have to create an identical class and copy values back and forth for saving and loading. Not too much of a problem except when I add a variable to the JLabel extended class and forget to add it to the XML mimic class and subsequent copy routines.
So, it would be great if I could make one class (say CellDataRecord.java) that held the extra data declarations and have that class be used in both places (the JLabel extension and the XML data) without having to have something like XML.data.CellDataRecordXXX.
You can do that with inheritance or using an interface, where the variable is set as a constant in the parent class. Since you are extending a JLabel, you should implement the interface on both classes:
public interface MyInterface {
int someint = 9;
}
public class MyClass1 extends JLabel implements MyInterface {
//this class has access to `someint`
}
public class MyClass2 extends JLabel implements MyInterface {
// also has access to `someint`
}
Edit
Since you want to be able to change the same variable from different classes, you have to ensure you aren't changing copies and are changing the same variable, so you should use a volatile keyword on the variable to indicate to java that all threads should check the value before it updates it.
Now you'll need to have a separate class so that instances can be made from other classes to get the value. You have to use the static keyword to ensure that one copy is kept for all class instances.
public class MyVariableWrapper {
public static volatile int some_var = 9;
public void updateSomeVar(int newvar) {
some_var = newvar;
}
public int getSomeVar() { return some_var; }
}
Now the other two classes just do this:
public class MyClass1 extends JLabel {
MyVariableWrapper myVariableWrapper;
MyClass1() {
super();
myVariableWrapper = new MyVariableWrapper();
// now I have access to `some_var`
}
}
public class MyClass2 extends JLabel {
MyVariableWrapper myVariableWrapper;
MyClass2() {
super();
myVariableWrapper = new MyVariableWrapper();
// now I have access to the same `some_var` as MyClass1
}
// this is a wrapper method for your convenience
// since you don't like the excess code when accessing the variable
public int getSomeVar() {
return myVariableWrapper.some_var;
// or myVariableWrapper.getSomeVar();
}
public void setSomeVar(int newvar) {
myVariableWrapper.some_var = newvar;
// or myVariableWrapper.setSomeVar(newvar);
}
}
Now you can do this:
MyClass2 myClass2 = new MyClass2();
System.out.println(""+myClass2.getSomeVar());
I'm not sure I 100% grasp your problem but from the first few lines of your description, instead of implementing an interface, you could define an abstract class and have your classes extend it. That way, you'll be able to define attributes in the abstract class and these will be common to all subclasses.

Categories