Here I have this code below which reverses a text.
TextFrame Class the main frame of my GUI
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
public class TextFrame extends JFrame implements ActionListener{
private Controls theControls;
private ReverseText theReverseText;
private InputOutputPanel theInputOutputPanel;
public TextFrame(){
this.getContentPane().setLayout(new BorderLayout());
theInputOutputPanel = new InputOutputPanel();
theReverseText = new ReverseText(this);
theControls = new Controls(theReverseText);
this.getContentPane().add(theInputOutputPanel, BorderLayout.NORTH);
this.getContentPane().add(theControls, BorderLayout.SOUTH);
this.pack();
this.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent ae) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public Controls getControls(){
return this.theControls;
}
public InputOutputPanel getInputOutPanel(){
return this.theInputOutputPanel;
}
public static void main(String[] args) {
// All we need to do is create the frame, as the constructor does everything required.
TextFrame theFrame = new TextFrame();
// theFrame.setSize(150, 150);
// theFrame.setVisible(true);
}
}
InputOutPut Class Panel which handles the input and output
import java.awt.GridLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class InputOutputPanel extends JPanel {
private JTextField input;
private JTextField output;
private JTextField situation;
public InputOutputPanel() {
this.setLayout(new GridLayout(2, 2));
this.add(new JLabel("header"));
this.add(situation = new JTextField("Situation"));
this.add(input = new JTextField("input text here"));
this.add(output = new JTextField());
}
public void setSituation(String sit){
situation.setText(sit);
}
public void setOutPut(String s){
output.setText(s);
}
public String getInput(){
return input.getText();
}
}
Controls class
import javax.swing.JButton;
import javax.swing.JPanel;
public class Controls extends JPanel {
private ReverseText reverseText; //the Event handler
private TextFrame theTextFrame; // the main frame to display the text
public Controls(ReverseText reverseText){
this.reverseText = reverseText;
reverseText = new ReverseText(theTextFrame);
JButton reversetheTextButton;
this.add(reversetheTextButton = new JButton("Text-Reverse"));
reversetheTextButton.addActionListener(reverseText);
}
}
ReverseText Class which is my event handler
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import java.awt.event.ActionListener;
public class ReverseText implements ActionListener {
private TextFrame theTextFrame;
private InputOutputPanel inputOutPanel;
public ReverseText(TextFrame theTextFrame) {
this.theTextFrame = theTextFrame;
}
#Override
public void actionPerformed(ActionEvent event) {
String buttonAction = event.getActionCommand();
// trying to use the mainframe to get other components
inputOutPanel = theTextFrame.getInputOutPanel(); // but this line complaining about null pointer error
String input = inputOutPanel.getInput();
if (buttonAction.equals("Text-Reverse"))
System.out.println("yes");
inputOutPanel.setSituation(buttonAction);
//Reverse The Text and send it to the Output
String reversedText = new StringBuffer(input).reverse().toString();
//
inputOutPanel.setOutPut(reversedText);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
}
I want to use the mainframe in my event handler class to call these components butthis is not working.
I have get and set methods in my main Frame called TextFrame.
My question is how do I use my event handler class using the main frame cato take input from the GUI and reverse this input.
You never set the Controls TextFrame field with any TextFrame instance. You need to pass it into the Controls constructor via a parameter, just as you do the model.
public class Controls extends JPanel {
private ReverseText reverseText; //the Event handler
private TextFrame theTextFrame; // the main frame to display the text
// **** note changes to constructor
public Controls(ReverseText reverseText, TextFrame theTextFrame){
this.reverseText = reverseText;
this.theTextFrame = textFrame; // ***** added
reverseText = new ReverseText(theTextFrame);
Then change:
theControls = new Controls(theReverseText, this); // **** note change
after new JButton(...), call setActionCommand on the button. Otherwise you just set the label, and the listener won't get an ActionCommand of the button even when the listener is fired.
Related
I am working on a school assignment. We have 10 buttons, lets say first 10 letters of alpahabet. For exmaple when you click the 'A' button, character 'A' gets added to jLabel.
I know I could write new function for every button, but is there any better way? Like I pass the letter by argument and use only 1 function? Or is somehow possible to detect what button called my event handler and add letter according to that?
Yes, you can use actionCommand. Here you have examples doing that. How to use Buttons.
Example:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ButtonExample {
private JPanel panel;
private JLabel label;
public ButtonExample(){
panel = new JPanel();
label = new JLabel(" ");
ActionListener listener = new MyActionListener();
JButton buttonA = new JButton("Press me A");
buttonA.setActionCommand("A");
buttonA.addActionListener(listener);
JButton buttonB = new JButton("Press me B");
buttonB.setActionCommand("B");
buttonB.addActionListener(listener);
JButton buttonC = new JButton("Press me C");
buttonC.setActionCommand("C");
buttonC.addActionListener(listener);
panel.add(buttonA);
panel.add(buttonB);
panel.add(buttonC);
}
private class MyActionListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
String text = (label.getText() == null || label.getText().isEmpty() )?"":label.getText();
label.setText(text+e.getActionCommand());
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Textfield example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationByPlatform(Boolean.TRUE);
ButtonExample buttonExample =new ButtonExample();
frame.add(buttonExample.panel,BorderLayout.CENTER);
frame.add(buttonExample.label,BorderLayout.NORTH);
//Display the window.
frame.pack();
frame.setVisible(Boolean.TRUE);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
You can do like
Yourlabel.setText(yourbutton.getText());
It will place your button name say A to your desired label!
This is just a hint you can get an idea.
I have two classes mainpanel.java and subpanel.java. The subpanel.class contains a checkbox and some labels. I want to change the setSelected() and setText() of these components when i click some buttons in the mainpanel.java .
I have created a method in subpanel.java which i call from mainpanel.java and pass the boolean values.
public void schedulerchange(boolean check){
System.out.println("checked"+check);
scheduleenabler.setEnabled(check);
scheduleenabler.setSelected(check);
scheduleinfo.setText("Scheduler in On");
//subpanel21.updateUI();
}
When i call this function from mainpanel.java the function is called but the values don't change unless i make jcheckbox and jlabel static. But from what i learned we should not use static components unless very necessary.
Is there some other way to change the components?
If I have understood your question then I think you want to write a separate ActionListener class and perform action there which will enable or disable the JCheckBox in the UI-class. The below code shows that. Pass your checkbox reference to that PerformAction class and make it enabled or disabled by clicking on the button.
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MainClass {
MainClass() {
JFrame jfrm = new JFrame("JTable Demo");
jfrm.setLayout(new FlowLayout());
jfrm.setSize(460, 180);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JCheckBox check = null;
// Get the Panel from the subclass;
JPanel panel = new CheckBox().getCheckBoxPanel();
// From the compoenents present in the panel get the CheckBox compoenent.
for(int i = 0; i < panel.getComponentCount(); i++) {
if(panel.getComponent(i) instanceof JCheckBox) {
check = (JCheckBox) panel.getComponent(i);
}
}
JButton button = new JButton("Click");
// Pass the CheckBox Compoenent to the ActionListener.
button.addActionListener(new PerformAction(check));
jfrm.add(button);
jfrm.add(panel);
jfrm.setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MainClass();
}
});
}
}
class PerformAction implements ActionListener {
JCheckBox check = null;
public PerformAction(JCheckBox checkBox) {
check = checkBox;
}
#Override
public void actionPerformed(ActionEvent e) {
boolean checkStatus = check.isSelected();
if(checkStatus == true) {
check.setEnabled(false);
check.setSelected(false);
} else {
check.setEnabled(true);
check.setSelected(true);
}
}
}
class CheckBox {
public JPanel getCheckBoxPanel() {
JPanel checkPanel = new JPanel();
JCheckBox check = new JCheckBox();
checkPanel.add(new JLabel("CheckBox"));
checkPanel.add(check);
return checkPanel;
}
}
This is not an appropriate use of updateUI(), which "Resets the UI property to a value from the current look and feel." Using revalidate(), as suggested in a comment, would be helpful only if components are added to, or removed from, the enclosing Container. Instead, invoke repaint() directly on the sub-panel instance. For greater flexibility, use the observer pettern suggested here.
Addendum: This example use Action to encapsulate the button's behavior. Because the checkbox's selected state is a bound property, the component is repainted automatically, but you can invoke repaint() explicitly if needed.
Addendum: Update to pass a reference as a parameter.
Addendum: In this variation, the parameter is a reference to the exported Action.
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** #see https://stackoverflow.com/a/14412516/230513 */
public class Example {
private void display() {
JFrame f = new JFrame("Example");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridLayout(0, 1));
JPanel panel = new JPanel();
final JCheckBox check = new JCheckBox("Check");
Action checkAction = new AbstractAction("Update") {
#Override
public void actionPerformed(ActionEvent e) {
check.setSelected(!check.isSelected());
}
};
panel.add(check);
f.add(panel);
f.add(new SubPanel(checkAction));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static class SubPanel extends JPanel {
public SubPanel(final Action action) {
this.add(new JButton(action));
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example().display();
}
});
}
}
I am trying to implement a Document Listener in my program. So far every time the user types in a new word, I am getting the whole text and saving it. What I want to do is to get only the new word/words typed in and process them. Can you give me suggestions how I can do that?
How about document at http://docs.oracle.com/javase/tutorial/uiswing/events/documentlistener.html ?
Basically, the parameter DocumentEvent from insertUpdate event contains the text. You will have to retrieve the texts from the object e.
My suggestion is to try out some code and we'll see how much you know about DocumentListener, ok?
Below is proposed code similar to yours above:
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
//public class DocumentListener { // Fix: not a good name for the class since it is part of JVM
public class DocumentEventDemo extends JFrame { // easier than extends JPanel
JPanel txtPanel, centerPanel;
GridLayout grid;
JTextField txtField;
JTextArea txtArea;
JFrame frame;
JComponent newContentPane;
FlowLayout flow;
public DocumentEventDemo() {
txtArea = new JTextArea();
txtArea.getDocument().addDocumentListener(new MyDocumentListener());
txtArea.getDocument().putProperty("txtArea", "MyDocumentListener");
// txtField = new JTextField(10); // 10 chars max
// txtField.setText("12345");
centerPanel = new JPanel();
grid = new GridLayout(2,1,1,1);
txtPanel = new JPanel();
flow = new FlowLayout(FlowLayout.CENTER);
txtPanel.setLayout(flow);
//Adding control GUI fields to the only panel
// txtPanel.add(txtArea);
// txtPanel.add(txtField);
// Forming the center view with GUI controls
centerPanel.setLayout(grid);
// centerPanel.add(txtPanel);
centerPanel.add(txtArea);
// Add Panels to the Frame
getContentPane().add(centerPanel,"Center");
this.setSize(500,200);
this.validate();
this.setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// newContentPane = getRootPane();
// newContentPane.setOpaque(true);
// frame.setContentPane(newContentPane);
}
//MyEditor editor = new MyEditor(); // what is MyEditor?
//javax.swing.event.DocumentListener mydocumentListener = new javax.swing.event.DocumentListener()
// Make a class to define the inherited abstract methods, which are also events.
class MyDocumentListener implements DocumentListener {
String[] word=new String[50];
String text;
int i=0;
int y;
int l;
int len;
public void changedUpdate(DocumentEvent documentEvent) {
System.out.println("The text has been changed.");
}
public void insertUpdate(DocumentEvent documentEvent) {
try {
GetWord(documentEvent);
} catch (BadLocationException ex) {
Logger.getLogger(DocumentListener.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void removeUpdate(DocumentEvent documentEvent) {
System.out.println("A character has been removed!");
}
private void GetWord(DocumentEvent documentEvent) throws BadLocationException {
//get the type of event
DocumentEvent.EventType type = documentEvent.getType();
//check what is the event, hence what is the user doing
if (type.equals(DocumentEvent.EventType.INSERT)) {
Document source = documentEvent.getDocument();
y=documentEvent.getOffset();
l=documentEvent.getLength();
len=source.getLength();
text = source.getText(y,l);
if(text.equals(" "))
{
for (int z=0;z<len;z++)
{
System.out.print(word[z]);
}
System.out.println("\n");
Arrays.fill(word,null);
i=0;
}
word[i]=text;
i++;
} else {
System.out.println("A character has been removed!");
}
}
}; // DocumentListener class instantiation
// editor. editArea.getDocument().addDocumentListener(mydocumentListener);
public static void main(String args[]){
new DocumentEventDemo();
}
} // TOP class
Notes:
My most outer class extends JFrame, which creates the window & listeners the easy way, I think.
DocumentEventDemo is a constructor that creates the UI controls and looks.
I created a class that implements DocumentListener. This way I can override the abstract events.
My main function is on the bottom inside the class DocumentEventDemo, like yours actually.
I do not see the code for class MyEditor. Therefore I replaced that with JTextArea, behaves like an editor.
Your code GetWord seems to be working well. Congratulations!
Your technique of using System.out.println is not working since the app is windows GUI application instead of console, which works well with System.out.
Obviously, you still have work to do with the Listener functions for changed and remove.
Have fun!
Tommy Kwee
Working in Java: I have a JFrame class, and separate classes for my two JPanels that are added to the JFrame. One of the JPanel classes has some buttons in it, which can interact with each other(when I click on one button, it can disable another button). However, I can't figure out how to get the button to call a method in the other JPanel (written in a separate class).
So, my program look like this:
JFrame
Jpanel1
Jpanel2 - This class has my buttons in it, I'm trying to get them to interact with the JPanel1 object.
Any tips appreciated, thanks!
One way to do this is to pass an instance of (to use your terminology) Jpanel1 into Jpanel2. This doesn't have to be done in the constructor, you can have a setConnectedPanel(JPanel) method, for example.
Here's some code that demonstrates what you want to do:
MyFrame.java
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class MyFrame extends JFrame {
public MyFrame() {
ReactionPanel rp = new ReactionPanel();
ActionPanel ap = new ActionPanel(rp);
setLayout(new GridLayout(2, 1));
add(ap);
add(rp);
pack();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MyFrame();
}
});
}
}
ActionPanel.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class ActionPanel extends JPanel implements ActionListener {
private ReactionPanel rp;
private JButton button;
public ActionPanel(ReactionPanel rp) {
this.rp = rp;
button = new JButton("Click");
button.addActionListener(this);
this.add(button);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(button)) {
rp.react();
}
}
}
ReactionPanel.java
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ReactionPanel extends JPanel {
private JLabel label;
public ReactionPanel() {
label = new JLabel("PING");
this.add(label);
}
public void react() {
if(label.getText().equals("PING")) {
label.setText("PONG");
} else {
label.setText("PING");
}
}
}
As you can see, I tend to override all of my JFrames/JPanels when I write Swing GUIs as I find it easier and more flexible but YMMV.
I'm new to java coming from C# so I'm not familiar with java best practices.
I have a main class that opens a JFrame to get several input strings from a user. When the user clicks submit the GUI should close and the main class continue processing using the input.
This is the main class:
public class Main {
FInput fInput;
public void main(String[] args) {
if(args.length==0)
{
fInput = new FInput();
fInput.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fInput.pack();
fInput.setVisible(true);
}
else
startProcess(args);
}
public void startProcess(String[] args) {
// Do stuff
}
The main class will use this frame to get input from the user:
public class FInput extends JFrame{
private JTextField txtSourceDirectory;
private JTextField txtTargetDirectory;
private JTextField txtDefectNumber;
private JTextField txtSliceTokens;
private JButton btnStart;
public FInput() {
// Initialize text fields and button
JButton.addActionListener(something);
}
}
In all the examples I could find, the listener would be a FMain itself. However in this case I want Main to listen and use the input in method startProcess.
Would having Main implement ActionListener, and passing it to FMain constructor is the way to go?
Yes, that is the right idea. You must do two things in order to be able to do that, though:
Put this at the beginning of the FInput class:
Main m = new Main(this);
Then, put these lines somewhere in the Main class...
FInput gui;
public Main(FInput in) { gui = in; }
Now you can refer to any component in the FInput class from the Main class by doing something like this.
gui.someComponent ...
To set up listeners just write someComponent.addItemListener(m); or something of the sort.
Hope this helps!
#Yoav In response to your latest comment...
You don't have to separate the listening class from the GUI class; you can combine the two into one class...
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame implements ActionListener {
private JTextField txtSourceDirectory;
private JTextField txtTargetDirectory;
private JTextField txtDefectNumber;
private JTextField txtSliceTokens;
private JButton btnStart;
public Main() {
txtSourceDirectory = new JTextField(40); //change this to the amount of characters you need
txtTargetDirectory = new JTextField(40);
txtDefectNumber = new JTextField(40);
txtSliceTokens = new JTextField(40);
btnStart = new JButton("Start");
add(txtSourceDirectory);
add(txtTargetDirectory);
add(txtDefectNumber);
add(txtSliceTokens);
add(btnStart);
btnStart.addActionListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
//do stuff
}
static void startProcess(String[] ARGS) {
//do stuff
}
public static void main(String[] args) {
if (args.length == 0) {
Main frame = new Main();
} else {
startProcess(args);
}
}
}
Also consider using JOptionPane, shown here, in your Main class. You can customize the appearance, including button text, as shown in How to Make Dialogs.
First main method in java always must be public static void. Below is example how this can be done.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* Main class is frame but also implements ActionListener interface.
*/
public class Main extends JFrame implements ActionListener {
private JButton btnStart;
private static Main frame;
public Main() {
JPanel panel = new JPanel();
btnStart = new JButton("Press me");
// Add action listener. Listener could be any class that implements
// ActionListener
btnStart.addActionListener(this);
// This means add button btnStart to panel
panel.add(btnStart);
// This means add panel to frame
this.add(panel);
}
// main method in java always must be public, static and void. You forgot to
// put static.
public static void main(String[] args) {
if (args.length == 0) {
frame = new Main();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
} else
frame.startProcess(args);
}
public void startProcess(String[] args) {
// TODO
}
#Override
public void actionPerformed(ActionEvent arg0) {
// Here you put your code that is executed every time you press button.
// For example you just want to show message.
JOptionPane.showMessageDialog(this, "You pressed Button.");
}
}
But it is much better to have special class. For example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class ButtonListener implements ActionListener {
JFrame parent;
public ButtonListener(JFrame parent) {
this.parent = parent;
}
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(parent, "You pressed Button");
}
}
And in the main class you just add action listener to button:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* Main class is frame but also implements ActionListener interface.
*/
public class Main extends JFrame {
private JButton btnStart;
private static Main frame;
public Main() {
JPanel panel = new JPanel();
btnStart = new JButton("Press me");
ButtonListener listener = new ButtonListener(this);
// Add action listener. Listener could be any class that implements
// ActionListener
btnStart.addActionListener(listener);
// This means add button btnStart to panel
panel.add(btnStart);
// This means add panel to frame
this.add(panel);
}
// main method in java always must be public, static and void. You forgot to
// put static.
public static void main(String[] args) {
if (args.length == 0) {
frame = new Main();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
} else
frame.startProcess(args);
}
public void startProcess(String[] args) {
// TODO
}
}