So I have a case like this:
I have a JFrame, let's call it frame1. There's a JButton named Submit in frame1.
Inside the frame1, there is a JPanel, call it panel1. There's a JTextField in that JPanel.
The frame1 and panel1 are two different Java files.
I want to do something like this:
When I user edit, delete or insert the JTextField, there's a DocumentListerner to check if the input match with a regex. If it matches, then the Submit button is enabled, otherwise the Submit button is disabled.
I already know how to implement the DocumentListener on JTextField1 with regex check. The thing I don't know how to do is to make the frame1 listen to the boolean outcome of that regex check, so the Submit button will be enabled/disabled.
Could anyone help please ?
One way to do this could be to have the JButton on the same class as the JTextField, for a simple GUI as the one you have this is doable.
But we know there are times that this isn't possible so another way that you could have this done up to Java 8 is using the Observer pattern, as shown in this example. After Java 9, Observer and Observable are deprecated so you should use PropertyChangeEvent and PropertyChangeListener from java.beans package1.
So, if you're not using Java 9 or higher and don't care about the caveats of Observer and Observable then you could have a sample code like this one:
EnableButtonInOtherClass
import java.awt.BorderLayout;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class EnableButtonInOtherClass implements Observer {
private JFrame frame;
private OtherClass pane;
private JButton button;
private ObservableField observableField;
public static void main(String[] args) {
SwingUtilities.invokeLater(new EnableButtonInOtherClass()::createAndShowGUI);
}
private void createAndShowGUI() {
frame = new JFrame(getClass().getSimpleName());
observableField = new ObservableField();
observableField.addObserver(this);
pane = new OtherClass(observableField);
button = new JButton("Click me!");
button.setEnabled(false);
frame.add(pane);
frame.add(button, BorderLayout.SOUTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
#Override
public void update(Observable o, Object arg) {
System.out.println("Text is a digit: " + arg);
button.setEnabled((boolean) arg);
}
}
OtherClass
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
#SuppressWarnings("serial")
public class OtherClass extends JPanel implements DocumentListener {
private JTextField field;
private ObservableField observableField;
public OtherClass(ObservableField observableField) {
field = new JTextField(10);
add(field);
this.observableField = observableField;
field.getDocument().addDocumentListener(this);
}
#Override
public void changedUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
}
#Override
public void insertUpdate(DocumentEvent e) {
updateState();
}
#Override
public void removeUpdate(DocumentEvent e) {
updateState();
}
private void updateState() {
String patternString = "[0-9]+";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(field.getText());
observableField.updateState(matcher.matches());
}
}
ObservableField
import java.util.Observable;
public class ObservableField extends Observable {
public void updateState(boolean state) {
setChanged();
notifyObservers(state);
}
}
The above example makes use of the ObservableField class to handle the Observable class, that has an update method that notifies the observers (EnableButtonInOtherClass) that there has been a change every time you type into the JTextField on OtherClass and based on the matcher.matches() value determines if the JButton should be enabled or not.
But again, for a simple UI as the one you have it's easier to move the JButton to the same file and / or on JButton's ActionListener evaluate what's inside the JTextField rather than enable / disable the JButton.
Here are some screenshots of how the program looks like.
1Taken from this answer
Related
my question is: how do I get the object of my CustomPanel, so that I am able to access its fields (because in my real programm I have some more fields in there) and also am able to delete it from my ArrayList?
I don't know how I have to implement an ActionListener in the Class Window, to somehow get the Object in my Arraylist, which containes the button that got pressed.
Also I am wondering if I am somehow able to implement an ActionListener in the Class CustomPanel which can influence the behaviour of the Object which is an instance of my Class Window.
I have kind of the following code:
public class Window extends JFrame{
ArrayList<CustomPanel> aLCustomPanel = new ArrayList();
JPanel jp = new JPanel();
public Window() {
for(int i=0;i<5;i++){
aLCustomPanel.add(new CustomPanel());
//here I could put the code from the 1 edit - see below
jp.add(aLCustomPanel.get(i));
}
this.add(jp);
}
public static void main(String args[]){
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Window().setVisible(true);
}
});
}
}
class CustomPanel extends JPanel {
private JButton button;
public CustomPanel(){
button = new JButton("button");
this.add(button);
}
public JButton getButton(){
return this.button;
}
}
my Code is much longer and weirder, so I tried to extract the (for this question) importing things.
Thanks for any help in advance!
edit:
for example: I would like to delete the object from the ArrayList, of which the button got pressed.
//imagine this comment in above code
aLCustomPanel.get(aLCustomPanel.size()-1).getButton().addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button_IwantToDeleteYou(e); //here I want to remove the panel, containing the button that got pressed from the above ArrayList, which is located in Class Window
}
});
edit2:
added a missing bracket and fixed some mistakes, code should be ok now.
Your code contained a few "gaps", i.e. missing code, which I filled in, as follows:
Added calls to [JFrame] methods setDefaultCloseOperation() and pack() and setLocationByPlatform(). I suggest you refer to the javadoc for those methods in order to understand what they do.
I set a layout manager for jp class member variable in your Window class.
Yes, you need to register an ActionListener with the JButton in class CustomPanel and that listener should reside in your Window class - the one that extends JFrame.
Here is my rewrite of your code. Note that I changed the name of class Window to CusPanel so as to distinguish between your class and java.awt.Window class. Not that it makes a difference, I just prefer not to use names of classes from the JDK.
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class CusPanel extends JFrame implements ActionListener {
private static final int COUNT = 5;
private ArrayList<CustomPanel> aLCustomPanel = new ArrayList<>();
private JPanel jp = new JPanel(new GridLayout(0, COUNT));
public CusPanel() {
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
for (int i = 0; i < COUNT; i++) {
aLCustomPanel.add(new CustomPanel(this));
// here I could put the code from the 1 edit - see below
jp.add(aLCustomPanel.get(i));
}
this.add(jp);
pack();
setLocationByPlatform(true);
}
public void actionPerformed(ActionEvent actionEvent) {
Object source = actionEvent.getSource();
if (source instanceof JButton) {
JButton button = (JButton) source;
Container parent = button.getParent();
jp.remove(parent);
jp.invalidate();
jp.repaint();
pack();
// aLCustomPanel.remove(parent); <- optional
}
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new CusPanel().setVisible(true);
}
});
}
}
class CustomPanel extends JPanel {
private JButton button;
public CustomPanel(ActionListener parent) {
button = new JButton("button");
button.addActionListener(parent);
this.add(button);
}
public JButton getButton() {
return this.button;
}
}
Note that after removing a CustomPanel, the GUI components need to be laid out again and the JFrame should also be resized accordingly. Hence in the actionPerformed() method, I call invalidate(), then repaint() and then pack(). I also think that if you remove a CustomPanel from the GUI, you should also remove it from the ArrayList, but hey, I still don't understand why you want to do this although I obviously don't know the whole story behind you wanting to do this in the first place.
Of-course, since each button (and each CustomPanel) looks exactly the same, you can't really know which button was removed. Again, I assume you see the big picture whereas I don't.
So I'm making a simple program that jumps from panel to panel and am using an actionlistener Button to make the jump. What kind of method or operation do I use to jump from panel to panel?
I tried to use setVisible(true); under the action listener, but I get just a blanks screen. Tried using setContentPane(differentPanel); but that doesn't work.
ackage Com.conebind.Characters;
import Com.conebind.Tech.TechA16;
import Com.conebind.Overviews.OverviewA16;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Char_A16 extends JFrame {
private JButton combosButton16;
private JButton techButton16;
private JButton overviewButton16;
private JLabel Image16;
private JPanel panel16;
private JPanel panelOverviewA16;
public Char_A16() {
overviewButton16.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
OverviewA16 overview16 = new OverviewA16();
overview16.setVisible(true);
overview16.pack();
overview16.setContentPane(new Char_A16().panelOverviewA16);
}
});
techButton16.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Todo
}
});
}
private void createUIComponents(){
Image16 = new JLabel(new ImageIcon("Android 16.png"));
}
public static void main (String[] args){
JFrame frame = new JFrame("Android 16");
frame.setContentPane(new Char_A16().panel16);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);}
}
The setContentPane(OverviewA16) doesn't work because there's not an object that defines the panel.
Please check this demo project showing how to use CardLayout with IntelliJ IDEA GUI Designer.
The main form has a method that switches between 2 forms displayed inside it:
public void showPanel(String id) {
final CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, id);
}
Both forms are added to the card layout during the main form initialization:
FormOne one = new FormOne();
one.setParentForm(this);
cardPanel.add(one.getPanel(), FORM_ONE);
FormTwo two = new FormTwo();
two.setParentForm(this);
cardPanel.add(two.getPanel(), FORM_TWO);
final CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, FORM_ONE);
A reference to the main parent form is passed to these 2 forms using setParentForm() method so that FormOne and FormTwo classes can access the showPanel() method of the MainForm.
In a more basic case you may have a button or some other control that switches the forms
located directly on the MainForm, then you may not need passing the main form reference to the subforms, but it can be still useful depending on your app logic.
I have a jframe that includes JButton.I have six buttons in this frame, but I don't know how to define action listener for this buttons.please help to solve this problem.
First you have to import the package java.awt.event.* to enable events. After the class name you have to add implements ActionListener so that the class can handle events. When you have created the buttons you have to add an actionlistener to each button. Since you haven't showed which code you use I make an example with a simple program that counts votes, if the user clicks the yesButton the votes are increased with 1 and if the user clicks the noButton the votes are decreased with 1.
Here is the code to add an ActionListener to each button:
yesButton.addActionListener(this);
noButton.addActionListener(this);
Then write the following code to handle the events:
public void actionPerformed(ActionEvent e) {
JButton src = (JButton) e.getSource();
if(src.getActionCommand().equals("Yes")) {
yesCount++;
} else {
noCount++;
}
label.setText("Difference: " + (yesCount - noCount));
}
If you have 6 buttons you need to have an if statement and then 5 "else if" statements instead of only an if and an else statement.
Have a look at the Java tutorials on how to use ActionListeners:
https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
Here's a simple example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Hello extends JPanel implements ActionListener {
JButton button;
public Hello() {
super(new BorderLayout());
button = new JButton("Say Hello");
button.setPreferredSize(new Dimension(180, 80));
add(button, BorderLayout.CENTER);
button.addActionListener(this); // This is how you add the listener
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(ActionEvent e) {
System.out.println("Hello world!");
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("Hello");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new Hello();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
buttons have a method called addActionListener, use that for adding the action listener that you can implement for the click...
Example:
dummyButton = new JButton("Click Me!"); // construct a JButton
add(dummyButton); // add the button to the JFrame
dummyButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(" TODO Auto-generated method stub");
}
});
It's really simple.
I suppose you have an instance of your button, right? Let's say that instance is called myButton.
You can just add an action listener by calling addActionListener:
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Do whatever you like here
}
});
Protip: next time you don't know what method to call, just type the instance name and .. Then, your IDE will show you all the methods you can call, unless you are not using an IDE. If that is the case, download one.
Hey I have a panel class in which there are two panels, one of the panels have text field. I want to perform an action when it gets focused.
The panel is added on the main frame.
Use FocusListener, here is simple example:
import java.awt.BorderLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class TestFrame extends JFrame{
public TestFrame(){
init();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
private void init() {
JTextField f1 = new JTextField(5);
f1.addFocusListener(getFocusListener());
add(f1,BorderLayout.SOUTH);
add(new JTextField(5),BorderLayout.NORTH);
}
private FocusListener getFocusListener() {
return new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
super.focusGained(e);
System.out.println("action");
}
};
}
public static void main(String... s){
new TestFrame();
}
}
Also JFrame has getFocusOwner() method.
Use the api
JFrame.getFocusOwner()
This will return a reference to the component with focus
You ca also check....
KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner()
To the modification, just add a FocusListener to your respective Component, and implement the interface to your particular acitons.
There are visual clue that helps to know which component has the focus, such as an active cursor in a text field. To work with the FocusListener Interface and in order to listen’s the keyboards gaining or losing focus, the listener object created from class is need to registered with a component using the component’s addFocusListener() method. The two important method focusGained(FocusEvent e) and void focusLost(FocusEvent e) which helps to find which component is focused.
To know more about What is FocusListener Interface and How it Works.
How with minimum code uglification can I write a debugging hook in a Swing program that would tell me which component in the hierarchy is actually handling each KeyStroke or mouse click and performing the action mapped to it in the component's action map? We are writing a complicated GUI and it would be very useful to know this information.
Put in a custom event dispatcher:
http://tips4java.wordpress.com/2009/09/06/global-event-dispatching/
Also look up AWTEvent.getID(), MouseEvent, KeyEvent in the API docs.
This is how the software I work on monitors mouse and keyboard to see if the user is busy working, and locks the window if they're not.
Using AspectJ to weave a logging aspect into your code base can be done. Below is an example of advice on a joinpoint within execution of any objects with the method actionPerformed(ActionEvent) you have in your code base. Similar constructions can be used to advise other Listeners.
Below is the aspect to advise button presses and other components having ActionListeners. It simply outputs the class name of the source of the action and the signature of the actionPerformed method.
import java.awt.event.ActionEvent;
import org.aspectj.lang.Signature;
public aspect Logger {
before(ActionEvent e) : execution(* *.actionPerformed(ActionEvent)) && args(e) {
Signature sig = thisJoinPoint.getSignature();
System.out.println(e.getSource().getClass() + " lead to " + sig);
}
}
A test class which produces two buttons of different classes (in file StackTraceExample.java):
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
class MyButton extends JButton {
public MyButton(String string) {
super(string);
}
}
class MyOtherButton extends JButton {
public MyOtherButton(String string) {
super(string);
}
}
class ButtonStackDisplay implements ActionListener {
private final JTextArea stackTraceText;
ButtonStackDisplay(JTextArea textArea) {
this.stackTraceText = textArea;
}
public void actionPerformed(ActionEvent e) {
String endl = System.getProperty("line.separator");
StringBuilder b = new StringBuilder();
// you can see the source of the event
b.append(e.getSource()).append(endl).append(endl);
// the stack trace shows that events don't propagate through the components
// originating them, but instead processed in a different thread
for (StackTraceElement se : new Throwable().getStackTrace()) {
b.append(se.toString());
b.append(endl);
}
stackTraceText.setText(b.toString());
}
}
public class StackTraceExample {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLayout(new BorderLayout());
JPanel top = new JPanel();
JButton button = new MyButton("Stack Trace");
top.setLayout(new GridLayout(2, 1));
top.add(button);
JButton otherButton = new MyOtherButton("Stack Trace");
top.add(otherButton);
f.getContentPane().add(top, BorderLayout.NORTH);
JTextArea stackTraceText = new JTextArea();
f.add(stackTraceText, BorderLayout.CENTER);
ButtonStackDisplay bsd = new ButtonStackDisplay(stackTraceText);
button.addActionListener(bsd);
otherButton.addActionListener(bsd);
f.setSize(400, 400);
f.setLocationRelativeTo(null);
f.setVisible(true);
f.toFront();
}
});
}
}