I'm very new to Java and I'm setting myself the challenge on writing a Caesar shift cipher decoder. I'm basically trying to clear a JTextArea from another class. I have two classes, a GUI class called CrackerGUI and a shift class. The JtextArea is in the GUI class along with the following method:
public void setPlainTextBox(String text)
{
plainTextBox.setText(text);
}
The GUI class also has a clear button with the following:
private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {
Shift classShift = new Shift();
classShift.btnClear();
}
Lastly i have the method in the shift class to clear the JTextArea.
public class Shift extends CrackerGUI {
public void btnClear()
{
CrackerGUI gui = new CrackerGUI();
gui.setPlainText(" ");
System.out.println("testing");
}
}
The testing text is printing out to console but the JTextArea wont clear. I'm not sure as to why :). I am sure it's a very simple mistake but it has me baffled. Any help would be appreciated.
Thank you in advance.
You're misusing inheritance to solve a problem that doesn't involve inheritance. Don't have Shift extend CrackerGUI and don't create a new CrackerGUI object inside of the btnClear() method since neither CrackerGUi is the one that's displayed. Instead have Shift hold a reference to the displayed CrackerGUI object and have it call a public method of this object.
e.g.,
public class Shift {
private CrackerGUI gui;
// pass in a reference to the displayed CrackerGUI object
public Shift(CrackerGUI gui) {
this.gui = gui;
}
public void btnClear() {
//CrackerGUI gui = new CrackerGUI();
gui.setPlainText(" ");
System.out.println("testing");
}
}
You also should probably not be creating new Shift objects in your GUI's actionPerformed methods, but rather use only one Shift object that is a class field.
The btnClear method clears the text area of a new CrackerGUI instance. It's like if you wanted to clear a drawing on a sheet of paper by taking a new blank sheet and clearing it. The original sheet of paper will keep its drawing.
You need to pass the gui instance to your Shift:
public class Shift {
private CrackerGUI gui;
public Shift(CrackerGUI gui) {
this.gui = gui;
}
public void btnClear() {
this.gui.setPlainText(" ");
}
}
and in the CrackerGUI class :
private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {
Shift classShift = new Shift(this);
classShift.btnClear();
}
Assuming CrackerGUI is your GUI, you should have the following instead:
public class CrackerGUI {
public void setPlainTextBox(String text)
{
plainTextBox.setText(text);
}
public void btnClear()
{
setPlainTextBox("");
System.out.println("testing");
}
}
One last thing, never make your GUI elements public! You should ask the GUI to clear itself and leave that knowledge of clearing elements hidden inside it.
You could try using static methods, as you would end up creating a new gui, then displaying that one, in stead of the current one already displayed.
This would require the parent class to be static too, which may cause errors in some of your methods, just a heads up.
Or else, you could create your own setText method:
void setText(JTextField t, String s){
t.setText(s);
}
that may enable you to directly edit components in the current GUI.
Related
What I want to achieve is very simple.
I have 2 classes. "SpeedingTicket" & "SpeedingTicket GUI".
Inside my GUI I have 1 textbox name txtSpeedLimit & a button.
Inside my SpeedingTicket class I have a variable "int speedingTicket".
Inside my SpeedingTicket class I also have a get & set method for "speedingTicket".
I know how to get and set text using JTextFields, but I want to be able to:
receive input from the "txtSpeedLimit", and store that value into the "txtSpeedLimit" instance variable in the "SpeedTicket" class. I can then check for validation etc when I come to adding the vehicle speed.
Maybe this isn't the most efficient way of dealing with this program. Maybe I should scrap the instance variables in SpeedingTicket, and deal with it all in the GUI.
Any advice would be hugely appreciated.
Basically what I'm trying to do is this:
class confirmHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
String val = txtSpeedLimit.getText();
int realNum = speed.getSpeedLimit() = txtSpeedLimit; < but obviously that doesn't work, but I want the textbox link to the variable.
EDIT: If we take away the GUI, all I want my program to do is the following:
Speed Limit: 50 < enterd via textfield
Speed: 60 < entered via textfield
if the speed is blah blah (ive already coded this).. then output a result to one of my labels.
I achieved this without making a GUI and making it only console based, but instead of the user typing it via the console, I want it to be typed via textfields.
THe values that are entered into the textfields should be stored in the two variables (speed and speedlimit) that are in the SpeedingTicket class.
You can update a value in:
public class SpeedingTicket {
int speedingTicket;
public SpeedingTicket() {
speedingTicket = 500;
}
public int getSpeedingTicket() {
return speedingTicket;
}
}
by:
public class SpeedingTicketGUI extends JPanel{
SpeedingTicket st;
SpeedingTicketGUI() {
st = new SpeedingTicket();
setLayout(new FlowLayout(FlowLayout.LEFT));
JTextField txtField = new JTextField(10);
txtField.setText(""+st.getSpeedingTicket());
add(txtField);
JButton btn = new JButton("Update");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setSpeedingTicket(txtField.getText());
}
});
add(btn);
}
private void setSpeedingTicket(String text) {
try {
int speedTicket = Integer.parseInt(text);
st.setSpeedingTicket(speedTicket);
System.out.println("Speeding ticket set to " +st.getSpeedingTicket());
} catch (NumberFormatException ex) {
System.out.println("Invalid value " +text);
ex.printStackTrace();
}
}
public static void main(String[] args){
JFrame frame = new JFrame("Speeding Ticket");
frame.setSize(400,100);
frame.add(new SpeedingTicketGUI());
frame.setVisible(true);
}
}
You don't need to store values in JText or any GUI componenets...
Use global static variables. For example:
public static int speed_limit;
You can access this variable from ANY method,class, etc.
There are multiple ways to do it.
You can detect textfield changes by using a DocumentListener or if you want (not recommended) by a KeyListener.
The Listener could be implemented directly by your gui class or by your other class. If you want more abstraction you could implement the DocumentListener by your gui class and create a method
public void addSpeedChangeListener(SpeedChangeListener scl) {
this.speedChangeListeners.add(scl);
}
Your SpeedChangeListener could be very simple:
public interface SpeedChangeListener {
public void speedChanged(int value);
}
Then your second class implements the SpeedChangeListener and calls addSpeedChangeListener(this) on your gui class. Inside the gui class, your document listener calls speedChanged(val) for every listener registered.
EDIT
You can also use the Button and call the speedChanged on every listener inside the actionPerformed method of the ActionListener.
I think it would be easier to use a JOptionDialog which pop ups when the button is clicked. That way you can easily get input and also validate the input straight away.
I'm new to Java and I've hit a brick wall. I want to access GUI components (that have been created in one class) from another class. I am creating a new GUI class from one class, like so;
GUI gui = new GUI();
and I can access the components in that class, but when I go to a different class I cant. I really just need to access the JTextAreas to update their content. Could someone point me in the right direction please, any help is greatly appreciated.
GUI Class:
public class GUI {
JFrame frame = new JFrame("Server");
...
JTextArea textAreaClients = new JTextArea(20, 1);
JTextArea textAreaEvents = new JTextArea(8, 1);
public GUI()
{
frame.setLayout(new FlowLayout(FlowLayout.LEADING, 5, 3));
...
frame.setVisible(true);
}
}
First respect encapsulation rules. Make your fields private. Next you want to have getters for the fields you need to access.
public class GUI {
private JTextField field = new JTextField();
public GUI() {
// pass this instance of GUI to other class
SomeListener listener = new SomeListener(GUI.this);
}
public JTextField getTextField() {
return field;
}
}
Then you'll want to pass your GUI to whatever class needs to access the text field. Say an ActionListener class. Use constructor injection (or "pass reference") for the passing of the GUI class. When you do this, the GUI being referenced in the SomeListener is the same one, and you don't ever create a new one (which will not reference the same instance you need).
public class SomeListener implements ActionListener {
private GUI gui;
private JTextField field;
public SomeListener(GUI gui) {
this.gui = gui;
this.field = gui.getTextField();
}
}
Though the above may work, it may be unnecesary. First think about what exactly it is you want to do with the text field. If some some action that can be performed in the GUI class, but you just need to access something in the class to perform it, you could just implement an interface with a method that needs to perform something. Something like this
public interface Performable {
public void someMethod();
}
public class GUI implements Performable {
private JTextField field = ..
public GUI() {
SomeListener listener = new SomeListener(GUI.this);
}
#Override
public void someMethod() {
field.setText("Hello");
}
}
public class SomeListener implements ActionListener {
private Performable perf;
public SomeListener(Performable perf) {
this.perf = perf;
}
#Override
public void actionPerformed(ActionEvent e) {
perf.someMethod();
}
}
Several approaches are possible:
The identifier gui is a reference to your GUI instance. You can pass gui to whatever class needs it, as long as you respect the event dispatch thread. Add public accessor methods to GUI as required.
Declarations such as JTextArea textAreaClients have package-private accessibility. They can be referenced form other classes in the same package.
Arrange for your text areas to receive events from another class using a PropertyChangeListener, as shown here.
The best option to access that text areas is creating a get method for them. Something like this:
public JTextArea getTextAreaClients(){
return this.textAreaClients;
}
And the same for the other one.So to access it from another class:
GUI gui = new GUI();
gui.getTextAreaClients();
Anyway you will need a reference for the gui object at any class in which you want to use it, or a reference of an object from the class in which you create it.
EDIT ---------------------------------------
To get the text area from GUI to Server you could do something like this inside of Create-Server.
GUI gui = new GUI();
Server server = new Server();
server.setTextAreaClients(gui.getTextAreaClients());
For this you should include a JTextArea field inside of Server and the setTextAreaClients method that will look like this:
JTextArea clients;
public void setTextAreaClients(JTextArea clients){
this.clients = clients;
}
So in this way you will have a reference to the JTextArea from gui.
here i add a simple solution hope it works good,
Form A
controls
Textfield : txtusername
FormB fb = new FormB();
fb.loginreset(txtusername); //only textfield name no other attributes
Form B
to access FormA's control
public void ResetTextbox(JTextField jf)
{
jf.setText(null); // or you can set or get any text
}
There is actually no need to use a class that implements ActionListener.
It works without, what might be easier to implement:
public class SomeActionListener {
private Gui gui;
private JButton button1;
public SomeActionListener(Gui gui){
this.gui = gui;
this.button1 = gui.getButton();
this.button1.addActionListener(l -> System.out.println("one"));
}
}
and then, like others have elaborated before me in this topic:
public class GUI {
private JButton button = new JButton();
public GUI() {
// pass this instance of GUI to other class
SomeActionListener listener = new SomeActionListener(GUI.this);
}
public JButton getButton() {
return button;
}
}
I can't .setText(...) for a JTextField outside of the class that creates the gui. I'm very confused and I feel like there is something basic I am missing. I need some help here.
Here is what I am doing:
In a class (called MainClass) I create an instance of a class that creates my gui
TestText gui = new TestText();
with a constructor that sets the default settings (a JTextField and a button with a listener). Then I call the a setter that I wrote, where I pass it a string that is to set the text of the JTextField:
gui.setText("new");
But "new" doesn't show up on the gui.
I know my setter works from within the class because if I make a call to the setter from the button that I created in gui then the changes show up on the gui.
The part that really confuses me is this: If I call my getter just before my setter, then it returns the old value. Then if I call the getter again after I call the setter then it returns the new value, while the gui continues to show the old value. I thought that maybe it just isn't repainting the gui so I tried all kinds of permutations of .invalidate(), .validate(), .update() and .repaint(), all from the MainClass and from inside the setter. But none did anything.
Is it possible that I somehow have 2 different instances of the gui and I'm only editing one of them?
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestText {
private JTextField textField;
private JButton button;
private JPanel frame;
JFrame jFrame;
public void setText(String text) {
textField.setText(text);
}
public String getText() {
return textField.getText();
}
public TestText() {
this.textField.setText("98.6");
this.jFrame = new JFrame("TestText");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setText("new (button)");
}
});
}
public void setData(TestText data) {
data.setText("new (setData)");
}
public void getData(TestText data) {
}
public boolean isModified(TestText data) {
return false;
}
public void createGui(String[] args) {
jFrame.setContentPane(new TestText().frame);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.pack();
jFrame.setVisible(true);
}
}
and then here's the main class that I'm trying to create the gui from:
public class MainClass {
public static void main(String[] args) {
TestText gui = new TestText();
gui.createGui(null);
System.out.println(gui.getText());
gui.setData(gui);
System.out.println(gui.getText());
gui.setText("new (MainClass)");
System.out.println(gui.getText());
}
}
It looks like you're missing the reference to the text field I think...
gui.referenceToTextField.setText("new word");
EDIT: Very nice SSCCE! However, there are several problems (not in the order provided, necessarily).
You are overriding the setText() method. Don't do this unless you want the method to do something different—why you would want to do this I have no idea.
You aren't even using the args array in the createGui() method. You can create methods without specifying any parameters/arguments.
The getData() method is, right now, useless (If I were you, given what you're trying to accomplish, I would remove the method entirely). I'm assuming, from the apt method name (another good thing to do), that you want to retrieve the data from the text field. Put this line inside the method (and change the word void to String) and you should be set!
return textField.getText();
Truthfully, this shouldn't even run due to a NullPointerException. You aren't initializing any of the components other than the JFrame. You need to do things like textField = new JTextField(20).
Even if you could run this, the button wouldn't work at all because the button hasn't been told that it does anything. To do this call button.addActionListener() with the name of the listening class as the argument. If the GUI and listening classes happen to be in one class together (like I will show you in a minute), the argument is simply this.
You aren't adding any components to the frame. For every component you wish to put into your frame, you must call add(Component cmpt).
Having said this, I think I'm just going to try to recreate what you're trying to do here into one class. You don't really need two separate classes unless the listening portion is excessively long.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestText extends JFrame implements ActionListener {
JTextField textField = new JTextField(20);
JButton set = new JButton("Set Text");
JButton get = new JButton("Get Text");
public TestText() {
super();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(textField);
set.addActionListener(this); //this tells the program that the button actually triggers an event
add(set);
get.addActionListener(this);
add(get);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() == set) {
textField.setText(JOptionPane.showInputDialog(null, "Enter a new word for the text field:"));
} else {
System.out.println(textField.getText());
}
}
public static void main(String[] args) {
TestText tt = new TestText();
}
}
After doing some reading I think it is due to my code not accessing the Event Dispatch Thread like #camickr suggested. Here is some documentation that helped me solve my problem.
I'm just starting to work with Java Swing again and I have the same problem as last time.
I want to write a program which reads some user input, executes an algorithm and displays the result. The program has to work with two different user interfaces (console and GUI with Java Swing).
Currently I have a packet of classes with the algorithm (i can just pass in the user input and fetch the result), a class which contains the main class, a class for the console interface and a class for the GUI (which extends from JFrame).
Some code:
public class Algorithm {
//a lot of code
}
public class MainClass {
public static void main(...) {
Algorithm algorithm = new Algorithm();
//use either console or GUI and read user input
algorithm.execute(user input);
algorithm.getResult();
//display result on console/GUI
}
}
public class GUI extends JFrame implements ActionListener {
}
My Problem is that I don't know how to pass the user input (text, scalers and radio buttons, button) from the GUI to the algorithm and how to display the result on the GUI.
Do I have to pass an instance of Algorithm to the GUI and call the methods of Algorithm from GUI?
Or is it possible to implement the ActionsListener in MainClass (where I have an instance of Algorithm)? If I choose this way of implementation, how can i pass the result of the Algorithm back to the GUI?
Or should i change the whole implementation? :D
Short answer: Don't (at least not to the Main class).
Long answer: There is a pattern called Model-View-Controller (MVC) which explains how to get data from the user, do something with it and display it again. This link (and the whole site in general) is a good point to start: http://martinfowler.com/eaaDev/uiArchs.html
Applied to your code sample:
public class Algorithm {
//a lot of code
}
public class MainClass {
public static void main(...) {
Algorithm algorithm = new Algorithm();
GUI g = new GUI(algorithm );
}
}
public class GUI extends JFrame implements ActionListener {
private Algorithm algo;
public GUI(Algorithm a) { this.algo = a; }
}
Algorithm plays the role of the model here and GUI is a combination of controller and view.
Since you have the Algorithm nicely encapsulated in its own class then it should be easy to instantiate on object of type Algorithm in response to a button click on your GUI and execute the algorithm there. The main method shoul donly decide if the GUI is necessary and start it up.
So if you have a button called calculate on your GUI then:
calculate.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//get the user input from the JFrame
Algorithm algorithm = new Algorithm();
algorithm.execute(user input);
algorithm.getResult();
//display results on the JFrame
}
});
Getting input from a JTextField and so on is as simple as
mytextfield.getText();
and to write some value into a JLabel to display is:
mylabel.setText("Some Text");
You can use the Observer Pattern. In this case algorithm is the java.util.Observer and Gui is the java.util.Observable.
I'm using netbeans to program something with a user interface...
I hava a main class that named "NewJFrame.java"(A) and one more class
that named "NewClass.java"(B). Class A is extended to class B like this:
public class NewClass extends NewJFrame{
...
}
Contents of ClassA are public static like this:
public static javax.swing.JTextField TextBox1;
I also has a button in classA .So when I click the button, it will call a function
from the classB and that function needs to edit TextBox1's text...
Here is whats going on when I click the button:
private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String Str1;
NewClass nc = new NewClass();
Str1=nc.call();
}
Here is the funcion in ClassB:
public String call()
{
String Str;
Str = TextBox1.getText();
TextBox1.setText(Str + "1"); //This part isn't work.
JOptionPane.showConfirmDialog(null,Str,"22222222",JOptionPane.PLAIN_MESSAGE);
return Str;
}
So I can read the text of TextBox1 and show it in a messagebox but cannot edit his text.
If I put this code in main class it works perfectly but in another class it doesn't work.
Can someone help me to reslove this problem?
(I'm using netbeans 6.9.1)
I Just Trying to use some another class to add my code because I dont want all the codes stay in same file this is not usefull... Come on someone needs to know how to do that you can't be writing all the codes in a *.java file right?
The problem you are facing has nothing to do with NetBeans IDE,
you will face the same problem with any IDE for this code.
One way of achieving this is by aggregating the NewJFrame class in the NewClass
instead of extending it:
Let me exlplain with some code:
public class NewClass {
private NewJFrame frame = null;
public NewClass(NewJFrame frame) {
this.frame = frame;
}
public String call()
{
String text;
text = frame.TextBox1.getText();
frame.TextBox1.setText(text + "1"); //This will work now.
JOptionPane.showConfirmDialog(null,text,"22222222",JOptionPane.PLAIN_MESSAGE);
return text;
}
}
Here we will receive a reference to the calling JFrame class and will use fields
defined in that class.
private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String Str1;
NewClass nc = new NewClass(this); // see the parameter we are passing here
Str1=nc.call();
}
When we create an object of class NewClass we will pass the reference of the
currently calling NewJFrame object
This will work check it.
Now coming to why your code is not working. When NewClass is extending NewJFrame
and when you create a new object of NewClass class it contains a separate
copy of the NewJFrame which is different from the calling NewJFrame reference hence
the field is getting set in another JFrame and not what you wanted.
with regards
Tushar Joshi, Nagpur
AFAIK Netbeans prevents you from editing by hand GUI's and behaves diferrently depending on strange issues like the one you have... but it was months ago, I dont know if current version sucks that much yet.
I really don't understand why you are forcing yourself to use a new class for this? Even if you NEED to, I don't understand why NewClass extends NewJFrame since you are only creating an instance to call a method that has nothing to do with GUI.
I think creating NewClass isn't necessary. Writing all the code in one class isn't bad by itself. This really depends on MANY factors: how much is "all the code"? Does it make sense to separate responsibilities? Etc, etc...
So make the JTextField and JButton NOT static and NOT public, and simply do everything in there:
private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String str = TextBox1.getText();
TextBox1.setText(str + "1"); //This part isn't work.
JOptionPane.showConfirmDialog(null,Str,"22222222",JOptionPane.PLAIN_MESSAGE);
}
P.S.: variable names are start in lowercase: String str, not String Str.
I Found a solution. I'm throwing the contents whereever I'll use. Here is an Example:
Main class:
private void formWindowOpened(WindowEvent evt) {
Tab1Codes tc1 = new Tab1Codes();
if(!tc1.LockAll(TabMenu1))
System.exit(1);
tc1.dispose();
}
Another class where I added some of my codes:
public boolean LockAll(javax.swing.JTabbedPane TabMenu){
try
{
TabMenu.setEnabledAt(1, false);
TabMenu.setEnabledAt(2, false);
TabMenu.setEnabledAt(3, false);
TabMenu.setEnabledAt(4, false);
}catch(Exception e)
{
JOptionPane.showConfirmDialog(null, "I can't Lock the tabs!",
"Locking tabs...",
JOptionPane.PLAIN_MESSAGE,
JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
So, I can edit the contents in another class but it's little useless to send every content I want to read and edit.
If someone knows any short way please write here.