Show object members inside JScrollPane - java

I have a list of objects using the default list model, like so:
public static DefaultListModel<Loan> loans = new DefaultListModel<Loan>();
My Swing application looks like this:
When the Add button is clicked, it creates a Loan object and adds that object to the DefaultListModel, like so:
addLoan.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Loan loan = Calculator.createLoan(
Double.parseDouble(loanAmount.getText()),
Double.parseDouble(interestRate.getText()),
Double.parseDouble(term.getText())
);
Calculator.addALoan(loan);
}
});
With my code now, the objects actually appear in the JScrollPane fine. You can see below:
JList loanList = new JList(Calculator.loans);
loans = new javax.swing.JScrollPane(loanList);
The above code happens in my init method. This is what I see on the frontend:
I want to tab it out and show each of the members inside that box (scroll pane). A Loan object consists of amount, interest rate and term. I tried something similar to (How to dd an object to the JList and show member of the object on the list interface to the user?) but I am confused on how the renderer in the accepted answer shows up.

You are seeing the result of Swing’s default behavior. Swing is calling toString() on each Loan object.
You can override that method to return something suitable for display:
public class Loan {
// (property methods)
#Override
public String toString() {
return String.format("%12s %6s %,.1f years",
NumberFormat.getCurrencyInstance().format(
getAmount()),
NumberFormat.getPercentInstance().format(
getInterestRate() / 100),
getTerm());
}
}
Since JList uses a proportional width font on most platforms, the values from the loan objects probably won’t line up with each other. To address that, remove your JList, remove your list model, and instead subclass AbstractTableModel and use a JTable as camickr suggested.

Related

Accessing text in the GWT TextBox from ChangeEvent

I'm dynamically generating a form based on data received from an RPC call into a FormFieldData object which has details about the field to be rendered such as, Field Name, expected length and type of input, if the field is a required field or not and valid input Regex in some cases etc.
I'd like to be able to perform validation on the field depending on above attributes.
Here's an example:
private void renderTextField(FormFieldData field){
FormGroup formGroup = new FormGroup();
FormLabel formLabel = new FormLabel();
if(field.isRequired()){
formLabel.setText(field.getName()+"*");
}else{
formLabel.setText(field.getName());
}
formGroup.add(formLabel);
TextBox textBox = new TextBox();
textBox.addChangeHandler(new ChangeHandler(){
#Overrride
public void onChange(ChangeEvent event){
//TODO - find a way to get the text entered in TextBox
// and perform validation on it
//and set the TextBox Style to "Validation-error"
}
});
formGroup.add(textBox);
form.add(formGroup);
}
There're similar methods to render dropdowns, Numeric fields, radio button fields etc. which would need similar validation.
The problem is I can't access the text from the TextBox inside the onChange method without declaring it final, which I can't do because I might be rendering multiple text fields. I don't know much about ChangeEvent and if there's a way to get the text from the that.
I'd really appreciate any pointers to a way to do this in real time as the data is entered into the form, other than having to iterate through the fields and their corresponding FormFieldData object when the form is submitted.
First off, you can make the variable final, no problem.
If you don't want to do that for whatever reason, you can get the TextBox from the event like this:
textBox.addValueChangeHandler(new ValueChangeHandler(){
#Overrride
public void onValueChange(ChangeEvent event){
TextBox box = (TextBox) event.getSource();
// Do whatever you need to here
}
});
You are probably also looking for ValueChangeHandler instead of ChangeHandler.

get access to each dynamically added jComponent

Before I already asked question and could get value from dynamically added jTextFields and jComboBoxes using this answer for my question.
Now in my subPanel I have 3 jComboBoxes and 4 jTextFields.
To get value of jComponent I am using this code:
Component[] children = jPanel1.getComponents();
// iterate over all subPanels...
for (Component sp : children) {
if (sp instanceof subPanel) {
Component[] spChildren = ((subPanel)sp).getComponents();
// now iterate over all JTextFields...
for (Component spChild : spChildren) {
if (spChild instanceof JTextField) {
String text = ((JTextField)spChild).getText();
System.out.println(text);
}
}
}
}
I would like to ask is it possible to access to each jComboBoxes and jTextFields separately, i.e. can I manipulate each jComponent and set them different values? How can I achieve this?
Thank you in advance.
I would like to ask is it possible to access to each jComboBoxes and jTextFields separately, i.e. can I manipulate each jComponent and set them different values? How can I achieve this?
Rather than traversing the Component hierarchy (which is fragile to Layout changes), you can keep references to your Components. The following example is a class that contains instance variables for the Child components:
public class ComponentWrapper extends JComponent{
private JComboBox combo;
private JTextArea textArea;
public ComponentWrapper(){
combo = new JComboBox();
textArea = new JTextArea();
add(combo);
add(textArea);
}
public Text getTextArea(){
return textArea;
}
public JComboBox getComboBox(){
return comboBox;
}
}
The above class extends JComponent, adds the components within the constructor, and can be added to another Container elsewhere. Note the above class is just an example for how to do this, and may need to be further adapted depending upon your requirements. Usage:
ComponentWrapper wrapper = new ComponentWrapper ();
add(wrapper);
revalidate();//if adding 'dynamically'
//later, when you want to get the text
String text = wrapper.getTextArea().getText();
Since both of those classes (JComboBox and JTextField) extend JComponent you can make an ArrayList and add them to it. i.e.
ArrayList<JComponent> components = new ArrayList<JComponent>();
JComboBox pie = new JComboBox();
components.add(pie)
//pie is now stored in components as a JComponent
When you need to reference pie you can call:
JComboBox pie = (JComboBox) components.get(0);
This can be done with any JComponent and to reference it you just simply cast it on it's way out. This method, however, can lead to some confusion. So you should either remember the order you add them, or add them in a very specific way (i.e TextFields first, then ComboBoxes).

Want to convert java struts 2 static code into dynamic

I have been assign to one struts2 project and its one of jsp contains more than 100 radio buttons and they have handled in statically not dynamically. As jsp contains 100 radio buttons so I am able to see the below list of radio buttons catches in actions with their getter and setter
List selectRadioList001
List selectRadioList002
List selectRadioList003
List selectRadioList004
etc
List selectRadioList100
I want to add these radio button in a list dynamically iterating through 1 to 100 something like below but when I try to access the variable like "searchBoxSelectRadioList"+i then it is pretending like a simple string. I want it to be like a List as shown above.
public class SelectRadioListPOJO {
private List<TicketDesignUtil> selectRadioList;
public List<TicketDesignUtil> getSelectRadioList() {
return selectRadioList;
}
public void setSelectRadioList(List<TicketDesignUtil> selectRadioList) {
this.selectRadioList = selectRadioList;
}
}
Action code:
List<SelectRadioListPOJO> selectRadioListPOJOList = new ArrayList<>();
SelectRadioListPOJO selectRadioListPOJO;
for (int i = 1; i <= 100; i++) {
selectRadioListPOJO = new SelectRadioListPOJO();
selectRadioListPOJO.setSelectRadioList("searchBoxSelectRadioList"+i);// ERROR
selectRadioListPOJOList.add(selectRadioListPOJO);
}
It's not clear what you're asking.
You can't pass arbitrary values to methods; setSelectRadioList takes a list of TicketDesignUtil.
If your action doesn't have getters and setters for all of those radio buttons then you should resort to accessing the request parameters directly, for example, via ParameterAware.
You would then access the radio button parameters by name from the injected parameter map.
Notes:
It's not "pretending" to be a simple string, it is a simple string, because... well, because it is.
Your for loop is wrong; I corrected it in your question to avoid others commenting on it. The POJO should be added to the POJOList inside the loop.
Naming is funky; just call it selectRadioListPojos. Better yet, name it something domain-specific: variables should be semantically meaningful, not just a description of the class(es) involved.
These shouldn't be static in the first place, but a map or array.

Java: change a variable depending on dynamically generated text field name?

I have an ArrayList of TrainingClass objects with a variable "priority".
I am making a settings frame, where for each element currently in the ArrayList I make a TextField where the user sets priority.
This is how it is generated
for (TrainingClass tclass : mTrainingClasses) {
//Loop the ArrayList
JTextField txtPriority = new JTextField(3);
txtPriority.setBounds(10,10,100,20);
txtPriority.setText("" + tclass.getPriority());
getContentPane().add(txtPriority);
}
Now I would add a change listener, but...
Once I know which field has been changed, how can I access the proper element of the ArrayList mTrainingClasses?
In php, for example, I would simply make something like:
$mTrainingClasses->$changed_field->setPriority($new_value);
But, as far as I understand, I can’t do this in Java. So, how should I proceed?
Do I need to manually set the field name and listener for each element? I’m sure there is some other solution, but I have no idea at this point.
(I know I could use an ArrayList for the fields as well, such as
txtPriority.add(new JTextField(3));
But in this case, how do I know which index corresponds to the field that has been changed?
)
Have a list of Text Fields
List<JTextField> textFields = new ArrayList<JTextField>();
Change the loop like the following where you add all text fields to above list
for (TrainingClass tclass : mTrainingClasses) {
//Loop the ArrayList
JTextField txtPriority = new JTextField(3);
txtPriority.setBounds(10,10,100,20);
txtPriority.setText("" + tclass.getPriority());
getContentPane().add(txtPriority);
textFields.add(txtPriority);
}
In your listener you can do the following
mTrainingClasses.get(textFields.indexOf((JtextField) event.getSource()));
The above will return the TrainingClass which got changed.
There are several options:
Pass the TrainingClass element to the listener which you attach to the textfield. This will require to attach the listener in your for loop where you have access to both the TrainingClass and JTextField variable
Use a Map as suggested by #Ted Hopp
Use a List as you already suggested. Trick is to store an index in the JTextField so that afterwards you know which JTextField corresponds to which element in the List. You can use JComponent#putClientProperty and JComponent#getClientProperty for this.
You can use those JComponent#putClientProperty and JComponent#getClientProperty methods to store the TrainingClass variable directly
In your loop, you can populate a Map<JTextField, TrainingClass>. Then you can use that to look up the element from the changed field.
Map<JTextField, TrainingClass> fieldMap = new HashMap<>();
for (TrainingClass tclass : mTrainingClasses) {
//Loop the ArrayList
JTextField txtPriority = new JTextField(3);
txtPriority.setBounds(10,10,100,20);
txtPriority.setText("" + tclass.getPriority());
getContentPane().add(txtPriority);
map.put(txtPriority, tclass);
}
Alternatively, you can subclass JTextField and declare a data field that you can then reference directly in event handling.
You need some kind of mapping between the JTextField and the TrainingClass. Either make text field a property of your class or make a map that maps the two.
Map<TrainingClass, JTextField> myMap= new HashMap<TrainingClass, JTextField>();
for (TrainingClass tclass : mTrainingClasses) {
//Loop the ArrayList
JTextField txtPriority = new JTextField(3);
txtPriority.setBounds(10,10,100,20);
txtPriority.setText("" + tclass.getPriority());
getContentPane().add(txtPriority);
// map the textField to the training class
myMap.put(txtPriority, tclass);
}
When the field changes inside the listener method, you'd simply call:
public void eventListenerMethod(InputEvent e) {
JTextField fieldThatGeneratedEvent= e.getSource();
TrainingClass tClass= myMap.get(fieldThatGeneratedEvent);
}

Adding a database ID to an Eclipse Combo

I'm working on a Java application in Eclipse that pulls data out of a MySQL database. I'm populating a combo box with data. So far I can get the value of a field to show up but I can't figure out how to store the database row's unique ID value. One suggestion I found was to create a custom class that could store both the display value and the id value. However, this doesn't appear to work with the Eclipse widget combo object. This is what I have
import org.eclipse.swt.widgets.Combo;
class myClass {
public static void createCombo(ResultSet rs) {
Combo c = new Combo();
while(rs.next()) {
int id = rs.getInt("id");
int display = rs.getString("display");
comboitem ci = new comboitem(id,display);
c.add(ci);
}
}
}
class comboitem {
private int _id;
private String _display;
public comboitem(int id, String display) {
this._id = id;
this._display = display;
}
public int getID(){
return _id;
}
public String toString(){
return _display;
}
}
The above errors at c.add(ci). It's expecting a string, not an object. Is there a way to do this?
No idea but, I've always felt it was a bad move anyway.
Create a collection/list of comboitems, populate the widget from comboitem.display.
Index in the combo is index in your collection.
Means you can unit test lots of things without a UI or with simple mock, and it keeps you away from desktop specific implementations in your data models.
The combo widget displays an array of String's, so simply concatenate the two values if you want to display them both. I am not sure what your end goal is from your question. If it is to select the appropriate comboitem based on the combo selection, then store the comboitems in a Map and use the combo values as the keys.
Another approach is to use a jface ComboViewer which allows you to set the input to a complex object, provide a label provider and more complex controls around the Combo widget.
You should also look up some information on java coding conventions and not access your database directly from the UI unless this is a very simple application.
You can find some examples on using most SWT widgets here.

Categories

Resources