Java getter not working? - java

Ok so i have a comboBox, and a JTextField, whenever i chose the quantity, it would be displayed on the textfield. I have another class, which will retrieve the whatever inside the textfield, but the order class doesn't retrieve the information from catalogue class.
class Catalogue extends JPanel {
String[] h1Quantity = {"0","1","2","3","4","5","6","7","8","9","10"};
h1CBox = new JComboBox <String> (h1Quantity);
h1CBox.setSelectedIndex(0);
h1CBox.addActionListener (new Listener());
h1CBox.setPreferredSize ( new Dimension (50,30));
JLabel noBooks = new JLabel ("Quantity");
booksF = new JTextField(8);
public class Listener implements ActionListener {
public void actionPerformed (ActionEvent event) {
int total = h1CBox.getSelectedIndex();
booksF.setText(Integer.toString(total));
}
}
public String booksFText() {
return booksF.getText();
}
}
class Order extends JPanel {
Catalogue catalogue ;
public Order (Catalogue catalogue)
{
this.catalogue = catalogue;
JPanel panel = new JPanel ();
String text2= catalogue.booksFText();
textArea1 = new JTextArea (text2, 20, 35);
add(textArea1);
add(panel);
}
}
I'm new to java so please keep it simple. thanks alot.

You have 2 constructors in the Order class and catalogue is only set in the first one. Set this in the second contructor as well and the NPE should go away (although hard to know for sure without the stacktrace!)

Always try to post complete code. and stack trace too.
See your order class.
class Order extends JPanel {
public Order (Catalogue catalogue)
{
add(textArea);
}
}
If you use the second constructor , then the class variable catalogue will not be given memory. Thus NULL POINTER EXCEPTION . The code inside the second constructor has been moved to the first one.
The other reason may be that the variable being passed in order constructor is not defined properly. Should be done something like this.
Catalogue catalogue = new Catalogue();
Order order = new Order(catalogue);
See Updated Catalogue class.
class Catalogue extends JPanel {
String[] h1Quantity = {"0","1","2","3","4","5","6","7","8","9","10"};
JComboBox<String> h1CBox ; //Assuming you forgot to define it.
JLabel noBooks ;
JTextField booksF ;
//Define a new constructor
public Catalogue () {
//set jlabel
noBooks = new JLabel ("Quantity");
//set combobox
h1CBox = new JComboBox <String> (h1Quantity);
h1CBox.setSelectedIndex(0);
h1CBox.addActionListener (new Listener());
h1CBox.setPreferredSize ( new Dimension (50,30));
//set textfield
booksF = new JTextField(8);
//add UI items to your panel class
add(h1CBox); //combobox
add(noBooks); // label
add(booksF); // textfield
}
public class Listener implements ActionListener {
public void actionPerformed (ActionEvent event) {
int total = h1CBox.getSelectedIndex();
booksF.setText(Integer.toString(total));
}
}
public String booksFText() {
return booksF.getText();
}
}
Always define your UI like this . Of course , there are better ways . Thus code looks clean and you understand things. Learn to put comments to remind you what you tried to do somewhere.
The MAIN Class
public class Main {
static JTextArea textArea = new JTextArea(40,40);
static class Order extends JPanel{
public Order(){
add(textArea);
}
}
static class Catalogue extends JPanel{
....
private ActionListener listener = new ActionListener(){
public void actionPerformed(ActionEvent event){
textArea.setText(h1CBox.getSelectedIndex()+"");
}
};
}
public static void main(String args[]){
//Construct a frame and add panels and you are good to go.
}
}
One last suggestion, if you plan on NOT changing the data of textarea yourself , use textfield or label instead of textarea. Sometimes the text inside textarea is set , but user is unable to see because of improper bounds . So , to be sure just replace the textarea with label or textfield. Cheers :)

Related

JComboBox actionListener doesn't function

I have a class that has 4 private attributes, and through a JComboBox selection, I want to modify them through calling a procedure. However, it seems like even though the JComboBox appears with the selection, the attributes that are shown don't change.
public class PanneauVehicule extends JPanel {
private String[] vehicules;
private int majCarburant;
private int majPassager;
public class PanneauVehicule extends JPanel {
//Main constructor
public PanneauVehicule(){
//Creates a JPanel
super();
//Sets layout as BorderLayout
setLayout(new BorderLayout());
initListeVehicule();
initLabels();
}
public void initListeVehicule(){
vehicules = new String[] {Constantes.CS100 , Constantes.CS300 ,
Constantes.GREYHOUND102D3 , Constantes.GREYHOUNDG4500 ,
Constantes.TGVATLANTIQUE , Constantes.TGVDUPLEX};
final JComboBox<String> vehiculesList = new JComboBox<>(vehicules);
//Keep in mind the comboBox does appear with the right selections
add(vehiculesList,BorderLayout.NORTH);
//Here's where it doesnt work.
vehiculesList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
majInfo(2,4);
}
});
}
public void majInfo(int test1, int test2){
this.majCarburant = test2;
this.majPassager = test1;
}
public void initLabels(){
JPanel panneauBas = new JPanel();
panneauBas.setLayout(new GridLayout(2,1,5,5));
JLabel labelCarburant = new JLabel();
labelCarburant.setText("Type de caburant: " + this.majCarburant);
JLabel labelPassagers = new JLabel();
labelPassagers.setText("Nb de passagers: " + this.majPassager);
panneauBas.add(labelPassagers);
panneauBas.add(labelCarburant);
add(panneauBas, BorderLayout.SOUTH);
panneauBas.setBackground(Color.WHITE);
}
After that, I use another procedure that will make majCarburant and majPassager appear on screen. However their values are shown as default (0). I can make their values change manually without using an ActionListener, but the task at hand requires me to use one.
I've been trying ways to just simply change the values through actionListener directly,
You don't invoke an ActionListener directly. Once an ActionListener has been added to the combo box, you can invoke:
setSelectedItem(...) or
setSelectedIndex(...)
on the combo box and the combo box will invoke the ActionListener.
I found the solution after a few more hours of meddling. I just integrated the procedure that creates labels into initListeVehicule, and from there the ActionListener can access the labels to modify their texts.
public void initListeVehiculeInfos(){
vehicules = new String[] {Constantes.CS100 , Constantes.CS300 ,
Constantes.GREYHOUND102D3 , Constantes.GREYHOUNDG4500 ,
Constantes.TGVATLANTIQUE , Constantes.TGVDUPLEX};
final JComboBox<String> vehiculesList = new JComboBox<>(vehicules);
add(vehiculesList,BorderLayout.NORTH);
JPanel panneauBas = panelGenerator();
//these setTexts serve as default values before doing your first selection
final JLabel carb = labelGenerator();
carb.setText("Carburant: Kérosène");
final JLabel passager = labelGenerator();
passager.setText("Nb Passager: 110");
vehiculesList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
InterfaceVehicules info = FabriqueVehicule.obtenirVehicule(vehiculesList.getSelectedIndex());
carb.setText("Carburant: " + info.tabNomTypeCarburant[info.getTypeCarburant()] );
passager.setText("Nb Passagers: " + info.getNbPassagersMax());
}
});
panneauBas.add(carb);
panneauBas.add(passager);
add(panneauBas, BorderLayout.SOUTH);
}

Add listener to JPanel

I have a custom class CustomField that extends JPanel. As I often have to reuse the same pattern, my custom class is made of 2 JLabels and 2 JComboBox.
It's quite simple; the first JComboBox has ON/OFF choices and the second JComboBox is only visible if the first is set to "ON". I can manage this part.
The part that I however don't know who to design it well is that CustomField instances are in another class that is the main JFrame and in this JFrame, some parts will be visible only if the JComboBox from the CustomField class is set to "ON". I thought about using a MouseAdapter, but I don't know it is good practice.
Here is my CustomField class:
public class CustomField extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
JLabel text, portText;
JComboBox<String> testCB, option;
public CustomField(String text, String opt, String tst) {
this.text = new JLabel(text);
String[] onOffOpt= {"OFF", "ON"};
this.option = new JComboBox<String>(onOffOpt);
this.option.setSelectedItem(opt);
this.option.addItemListener(new ItemListener(){
#Override
public void itemStateChanged(ItemEvent ie) {
portText.setVisible(option.getSelectedIndex() == 1);
testCB.setVisible(option.getSelectedIndex() == 1);
}
});
this.portText = new JLabel("Test:");
String[] testChoices = {"Test", "Test2"};
this.testCB = new JComboBox<String>(testChoices);
this.testCB.setSelectedItem(tst);
this.setLayout(new FlowLayout());
add(this.text);
add(this.option);
add(this.portText);
add(this.testCB);
}
}
And here is the main JFrame:
public class Main {
CustomField cf = new CustomField("test", "ON, "Test2");
public static void main(String s[]) {
JFrame frame = new JFrame("Application");
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
panel.add(cf);
JLabel labelTest = new JLabel("Label that should be visible or not");
panel.add(labelTest);
frame.add(panel);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Basically, I want that the labelTest visibily changes according to the CustomField settings. In the way that it is made, I can not put the labelTest in the CustomField class.
Is there a clean way to do what I want? Should I redesign the actual thing and put all the fields in the same class?
Thanks!
First, you want to expose the combobox's state with a method in CustomField:
public boolean isOn() {
return testCB.getSelectedIndex() == 1;
}
You can get an idea for how listening for state is done by looking at the method signatures in the documentation for various Swing components, which use the standard JavaBean listener pattern: You’ll want to add three public methods, and one protected method:
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
public void removeChangeListener(ChangeListener listener) {
listenerList.remove(ChangeListener.class, listener);
}
public ChangeListener[] getChangeListeners() {
return listenerList.getListeners(ChangeListener.class);
}
protected void fireChangeListeners() {
ChangeEvent event = new ChangeEvent(this);
for (ChangeListener listener : getChangeListeners()) {
listener.stateChanged(event);
}
}
(The listenerList field is inherited from JComponent.)
Now, you can simply add a call to fireChangeListeners(); whenever you detect that the user has changed the value of the On/Off combobox—that is, you’ll want to call it in your ItemListener.
As you can probably guess, your Main class can now call cf.addChangeListener, and inside that listener adjust the visibility of your label based on the value returned by cf.isOn().
You can learn a lot more by reading these.

Can't access JtextField Values in second JPanel

I am trying since 1 hour but I can't access my jtextField from JPanel to Jpanel1.
I am working on a course project in which I have to show the name of the log in user in the JPanel using jlabel but I can't access the jTextField in JPanel from jpanel1.
I make my JTextField1 public Static using this Answer but still unable to catch the values
I am using this code to fetch the values from JPanel in JPanel1. What I am doing is creating a object of JPanel in JPanel1 and then try to fetch the value.
LoginPanel s = new LoginPanel();
String sc=s.jTextField1.getText();
this.jLabel3.setText(sc);
Don't make a variable static for this purpose as you're breaking OOPs rules for no good reason.
Don't create a completely new object if you want to get the state of another object of the same type, since the two objects will be completely different instances.
If you need to have one object query the state of another (here the state being the text held within the JTextField), then give the the object with the JTextField a public getter field that will return the text in its JTextField and have the first object call this method when needed.
The first object will of course need a valid reference to the displayed object with the text field. How this is done will depend on the structure of your program, something we have no idea of at the moment.
Often the problem is when to obtain the text, since if you try to obtain the text before the user has had a chance to enter anything, then your code won't work. To avoid this, this is usually done in an event listener, and again the details will depend on the structure of your program and on code not shown.
Sometimes the timing is achieved by displaying the 2nd JPanel within a modal dialog window such as a JDialog or JOptionPane. This method is used most often when trying to get log on information from a user.
For better and more specific help, please make your question more informative. Show actual code, not an image of code. How much code? best would be if you could create and show us a minimal code example program.
For example, using a JOptionPane to display one JPanel and obtain text in a modal fashion:
import java.awt.Component;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class TwoPanels extends JPanel {
private MyPanel1 panel1 = new MyPanel1();
private MyPanel2 panel2 = new MyPanel2();
public TwoPanels() {
add(panel2);
add(new JButton(new AbstractAction("Get Name") {
#Override
public void actionPerformed(ActionEvent arg0) {
Component parent = TwoPanels.this;
String title = "Enter Name";
int messageType = JOptionPane.PLAIN_MESSAGE;
int optionType = JOptionPane.OK_CANCEL_OPTION;
int result = JOptionPane.showConfirmDialog(parent, panel1, title, optionType, messageType);
if (result == JOptionPane.OK_OPTION) {
String name = panel1.getNameText();
panel2.setNameText(name);
}
}
}));
}
private static void createAndShowGui() {
TwoPanels mainPanel = new TwoPanels();
JFrame frame = new JFrame("TwoPanels");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyPanel1 extends JPanel {
private JTextField nameField = new JTextField(10);
public MyPanel1() {
add(new JLabel("Name:"));
add(nameField);
}
public String getNameText() {
return nameField.getText();
}
}
class MyPanel2 extends JPanel {
private JTextField nameField = new JTextField(10);
public MyPanel2() {
nameField.setFocusable(false);
nameField.setEditable(false);
add(new JLabel("Name:"));
add(nameField);
}
public void setNameText(String text) {
nameField.setText(text);
}
}

Variable sized array of JTextFields and other widgets

public class Creator extends JFrame {
JLabel[] pos;
JTextField[] monInitFi;
JPanel panel, statusP, inputP;
JTextField numMonsFi;
JButton goB, initRollB;
int numMons;
public Creator() {
panel = new JPanel();
createInputP();
panel.add(inputP);
add(panel);
}
//The Input board
public JPanel createInputP() {
inputP = new JPanel();
numMonsFi = new JTextField(3);
inputP.add(numMonsFi);
goB = new JButton("Go");
goB.addActionListener(new goBListener());
inputP.add(goB);
return inputP;
}
//Creates the initiative input board.
public JPanel createStatusP() {
statusP = new JPanel();
monInitFi = new JTextField[numMons];
for (int i = 0; i < numMons; i++) {
monInitFi[i] = new JTextField(3);
statusP.add(monInitFi[i]);
}
initRollB = new JButton("Roll");
statusP.add(initRollB);
return statusP;
}
//The button listener, should update numMons, and create and add the initiative panel.
public class goBListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
numMons = Integer.parseInt(numMonsFi.getText());
createStatusP();
panel.add(statusP);
}
}
public static void main(String[] args) {
Creator c = new Creator();
c.setVisible(true);
c.setSize(1000, 600);
c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
c.setTitle("D&D 4e Encounter Tracker");
}
}
So this is only a sample of what I'm trying to do, but I cant even get the basics to work. When I run this the statusP(JPanel) does not show up, and I'm not sure if it's because its not running, or because it won't work.
I've tried putting the createStatusP() method in the GUI constructor but only the JButton will appear as if the for loop doesn't run.
Any help would be much appreciated.
In your goBListener's actionPerformed method, you should be calling panel.revalidate() to force the panel to be relaid out which will trigger a repaint, after you have added the statusP panel.
You should also try and follow Java naming conventions, the goBListener should start with an uppercase, GoBListener, it will make it easier for others to read (but will also make it easier for you to read other peoples code)
Instead of arrays, you might consider using some of List, this is a personal thing, but List is generally more flexible. Take a look at Collections for more details
This is because you call createInputP() as it's a procedure , but it's not ! it's a function it will return something that is in this case inputP panel ! so what's actually happening is overridable method call in constructor ! so the solution is add final keyword before createInputP() method !!
// final keyword after public keyword!
public final JPanel createInputP(){ ..... }
And modify goBListener like below :
public class goBListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
numMons = Integer.parseInt(numMonsFi.getText());
panel.revalidate();
panel.add(createStatusP());
}
}
Dang !! That's it !!

How can I inform the class which have an instance of a GUI builder class, when the JButton ActionEvent performed

Ok, here is my problem. Class B is a class that build a GUI ,which has a textField and button. class A has an instance of class B.Now I enter some value in the textfield, when I click the button, in class A I want to print out the value I just enter in the textfield, how can I achieve that?
Code below may better explain what I want to achieve:
public class A
{
B myB = new B();
(when the JButton was clicked,
how can I get the new textfield value here?)
}
public class B
{
JLabel myLabel;
JButton myButton;
public B()
{
getContentPane().setLayout(null);
myLabel = new JLabel();
myLabel.setLocation(0,0);
myLabel.setSize(100,30);
myLabel.setBackground( new Color(-6710887) );
myLabel.setText("");
getContentPane().add(myLabel);
myButton = new JButton();
myButton.setLocation(0,50);
myButton.setSize(100,30);
myButton.setBackground( new Color(-16737895) );
myButton.setText("Submit");
getContentPane().add(myButton);
myButton.addActionListener(this);
setSize(400,400);
setVisible(true);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e)
{
(how can I pass this "myLabel.getText()" value to class A when
this action performed?)
}
}
Can anybody help me finish this little program? Thanks in advance!
You need to expose the value in text field with a method in class B. Then class A can call that method. What it actually sounds like though is that class A (or something else) should be a ActionListener for your button.
However, a bigger problem is that you don't have a text field you just have a label in class B. This code is a good reason why you shouldn't use a GUI builder, especially when learning Swing.
Some reading:
http://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html
http://docs.oracle.com/javase/tutorial/uiswing/events/
I often make an "App" class that ties all my GUI-builder-built components together. Any GUI builder worth anything lets you add getters to the generated source code. Add some getters to the GUI-built components to retrieve key elements of the GUI, then let the App class use the getters to interact with the components as necessary. This won't win any MVC/MVVM/MVP design awards, but it gets the job done, which ought to count for something.
public class App {
private B _b;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
App app = new App();
app.run();
}
});
}
void run() {
_b = new B();
_b.getMainButton().addActionListener(new MainButtonListener());
_b.setVisible(true);
}
private void handleMainButtonClicked() {
String mainText = _b.getMainTextArea().getText();
System.out.println("Button clicked; main text = " + mainText);
}
public class MainButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
handleMainButtonClicked();
}
}
}
public class B extends JFrame {
private JPanel _contentPane;
private JTextArea _jTextArea;
private JButton _jButton;
public B() {
initComponents();
}
private void initComponents() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
_contentPane = new JPanel();
setContentPane(_contentPane);
_jTextArea = new JTextArea();
_contentPane.add(_jTextArea, BorderLayout.CENTER);
_jButton = new JButton("My Button");
_contentPane.add(_jButton, BorderLayout.SOUTH);
}
public JButton getMainButton() {
return _jButton;
}
public JTextComponent getMainTextArea() {
return _jTextArea;
}
}

Categories

Resources