I am doing an application, and I need to create 10 TextFields and save value in a XML file that i have. (I know how to save it in XML)
The issue I have is I want to save it all (in a XML) automatically without repeating the code like 10 times for each variable.
I am trying reflect.Field library to do it (Not accomplished) but i don't know if it's the best solution.
public TextField Tf_TestI1;
public TextField Tf_TestF1;
public TextField Tf_TestI2;
public TextField Tf_TestF2;
public TextField Tf_TestI3;
public TextField Tf_TestF3;
public TextField Tf_TestI4;
public TextField Tf_TestF4;
public TextField Tf_TestI5;
public TextField Tf_TestF5;
//Pair them and save it in XML
private void stuffVariables(){
String nameField1= "Tf_TestI";
String nameField2= "Tf_TestF";
Field[] fields = Controller.class.getFields();
for (int i = 0; i <fields.length ; i++) {
if (fields[i].getName().startsWith(nameField1)){
for (int j = 0; j < fields.length ; j++) {
if (fields[j].getName().equals(nameField2+fields[i].getName().substring(fields[i].getName().length()-1))){
System.out.println("EQUALS : "+fields[i].getName() + " = "+ fields[j].getName());
try {
//System.out.println("1: "+fields[i].getValue);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
I am trying to get the pair of Test Initial and Final to finally save it in XML like this...
<TESTS>
<TEST>
<INITIAL>AD</INITIAL>
<FINAL>AVB</FINAL>
</TEST>
<TEST>
<INITIAL>AQEW</INITIAL>
<FINAL>AVFE</FINAL>
</TEST>
<!-- ... MORE TEST -->
<TESTS>
This is not the way you want to do it. As a general rule of thumb, if you feel the need to use reflection, you're doing it wrong.
It looks like you have an arbitrary number of pairs of TextField objects. So that's the first port of call - create a separate class to house those pairs of TextField:
class TextFieldPair {
private TextField initialVal;
private TextField finalVal;
public TextFieldPair(TextField initialVal, TextField finalVal) {
this.initialVal = initialVal;
this.finalVal = finalVal;
}
public TextField getInitialVal() {
return initialVal;
}
public TextField getFinalVal() {
return finalVal;
}
}
...you then want an arbitrary number of these objects. Every time you have an arbitrary number of objects you'll want to use a collection of some sort, such as a list, so we can then loop through them like so:
public class Main {
private List<TextFieldPair> list = new ArrayList<>();
//...Other code that adds textfield objects to the above list
private void stuffVariables() {
for(TextFieldPair pair : list) {
System.out.println("Initial value: " + pair.getInitialVal().getText());
System.out.println("Initial value: " + pair.getFinalVal().getText());
}
}
}
You'll then have all the values printed out from each of those TextField objects, and you can manipulate them (such as outputting XML instead) as you see fit.
My main objective was to make it easy when I add more TextFields...
Using HashMap I only have to add a Key to his Value.
Using numbers in the Key made it more easy in my case.
//[...]
Map<String, TextField> map; //Global variable
//I just have to add the new TextFields to the HashMap
private void mapSaveRangs() {
map = new HashMap<>();
map.put("rangInitial1", tfrangInitial1);
map.put("rangFinal1", tfrangFinal1);
map.put("rangInitial2", tfrangInitial2);
map.put("rangFinal2", tfrangFinal2);
map.put("rangInitial3", tfrangInitial3);
map.put("rangFinal3", tfrangFinal3);
map.put("rangInitial4", tfrangInitial4);
map.put("rangFinal4", tfrangFinal4);
map.put("rangInitial5", tfrangInitial5);
map.put("rangFinal5", tfrangFinal5);
}
private void rangsInPairsXML(Element peeRangs) {
String sKeyrInitial = "rangInitial";
String sValuerInitial;
String sKeyrFinal = "rangFinal";
String sValuerFinal;
//Making sure that we have pair of 2
if (map.size() % 2 == 0) {
//map half size loop
for (int numRang = 1; numRang <= map.size() / 2; numRang++) {
sValuerInitial = map.get(sKeyrInitial + numRang).getText();
sValuerFinal = map.get(sKeyrFinal + numRang).getText();
//Verifying values and saving it in peeRang (XML Element)
if (!(sValuerInitial.equals("") || sValuerFinal.equals(""))) {
Element eRang = new Element("RANG");
eRang.addContent(new Element("INITIAL").addContent(sValuerInitial));
eRang.addContent(new Element("FINAL").addContent(sValuerFinal));
peeRangs.addContent(eRang);
}
}
} else {
System.out.println("ERROR!!");
//[...]
}
}
Related
So im developing a javafx gui that it should return all the valid values found in an ArrayList input range, but instead it's functionality its only valid for the latest value added,
so it's only returning the latest entry on the button click, i leave an example picture of the gui
as i hope this would help to clarify:
so if i add 2 different registration, 2 makes and 2 model and try and get the button search by regNo it only works with the latest entry not the previous one;
I leave the code for the setOnAction Method for the button
public void searchByReg(javafx.event.ActionEvent e) {
// clear the text field from the previous message
txtOutput.clear();
// get the car from the user through the car reg
String carReg = txtReg.getText();
// method to check if the field its empty
for (int i = 0; i < cars.size(); i++) {
if (carReg.equalsIgnoreCase(cars.get(i).getRegNo())) {
txtOutput.setText("You have selected \n" + cars.get(i));
carFound = true;
} else {
txtOutput.setText("That car is not in our Database");
}
}
}
Thank you for your help in Advance!!!
Try this, looks like you override text every time until last valid number.
txtOutput.setText("You have selected");
for (int i = 0; i < cars.size(); i++) {
if (carReg.equalsIgnoreCase(cars.get(i).getRegNo())) {
txtOutput.append("\n" + cars.get(i));
carFound = true;
}
}
if(!carFound) {
txtOutput.setText("That car is not in our Database");
}
This is not a JavaFX issue, but just a muddled-up search loop.
There's better ways to do this since Java 8. The following is much simpler and easier to read and debug:
public class LookupSample {
record Car(String name, String regNo) {
}
public static void main(String[] args) {
List<Car> cars = List.of(new Car("Mazda", "123"), new Car("Ford", "123"), new Car("Dodge", "789"));
String carReg = "123";
String result = cars.stream().filter(car -> car.regNo().equals(carReg)).map(Car::name).collect(Collectors.joining("\n\t ", "You have selected:\n\t", ""));
System.out.println(result);
boolean carFound = cars.stream().anyMatch(car -> car.regNo().equals(carReg));
System.out.println("Car Found? " + carFound);
}
}
I am trying to get an arraylist of objects from another class to display it an modify it (delete object in ArrayList) so the original ArrayList has to be modified also...I have tried the method below whitout success.
Class Atribute
private int number; //user imput
Methods
public String DisplayObj() {
String result;
FormularioPedido form = new FormularioPedido(); //instance of the other class so I can access the arrayList
ArrayList<Pedido> lista = form.getListaPedido();
number -= 1;
Pedido pedido = lista.get(number);
result = pedido.getTamanio() + pedido.getIngredientesToString()
+ pedido.getBebida() + pedido.getExtra() + pedido.getCelular();
return result;
}
public void deleteObj() {
FormularioPedido form = new FormularioPedido();
List<Pedido> lista = form.getListaPedido();
number -= 1;
lista.remove(number);
}
You need to store the lista as a Class attribut.
That way the list you are displaying will be the same as the one you are deleting from.
At the moment it's 2 separates lists and everytime you call the display method you recreate one.
private int number; //user imput
private FormularioPedido form = new FormularioPedido();
public String DisplayObj() {
String result;
ArrayList<Pedido> lista = form.getListaPedido();
number -= 1;
Pedido pedido = lista.get(number);
result = pedido.getTamanio() + pedido.getIngredientesToString()
+ pedido.getBebida() + pedido.getExtra() + pedido.getCelular();
return result;
}
public void deleteObj() {
List<Pedido> lista = form.getListaPedido();
number -= 1;
lista.remove(number);
}
Of course you would need to check for the list size before doing delete or display as to avoid exception.
Everytime you write new FormularioPedido(), you create a new list (returned when you call to the form.getListaPedido()). You should think a little more about your class design. For example, the list could be a class attribute and you could opperate over the same list instance.
I'm looking for a way to dynamically add columns to a vaadin table.
I tried this:
private Button createAddColumnButton() {
Button addProductButton = new Button("Add column");
addProductButton.addClickListener(new ClickListener() {
public void buttonClick(ClickEvent event) {
count = count++;
table.addGeneratedColumn("Column "+count, new ColumnGenerator() {
#Override
public Object generateCell(final Table source, Object itemId, Object columnId) {
String x = "some stuff";
return x;
}
});
}
});
return addProductButton;
}
This button allowed me dynamically add a column, however only one column before I recieved an error saying I cannot have two columns with the same id. How can I change the ID so it is unique & add lots of columns?
TL;DR
Simple change your code to:
count = count + 1;
Explenation
That's beacause assigment
count = count++;
does not work in the way you expect. Take a look at the following code:
public class HelloStackOverflow {
public static void main(String[] args) {
int count = 0;
count = count++;
System.out.println(count);
}
}
This prints on standard output 0. You will even get warning (The assignment to variable count has no effect) if you change your code to:
count = ++count;
You can find even better explanation here.
Here I have a GUI window and it basically ask the user to select a JRadioButton and type something in a JTextField, then choose confirm/cancel.
It is a project which we have to make a UML-to-Java text file. User would enter class information and choose a UML relationship, and this programme have to print out the Java clsas text on a JTextField. Just like when you create a new class in eclipse.
what I want to do is make a boolean[] to store an array of booleans, when user selects JRadioButton_A it'll store true and when user select JRadioButton_B it'll store false.And also I want the things typed in JTextField to be checked by a checkName(), if the method returns false, the string will be stored in an ArrayList.
Below is my code - there's some problems in getName() method and the boolean[] for storing true and false. When user needs to input name again, it would save the discarded sting/boolean into the array. (Sorry for my bad english!) Is there any better way to make this programme? I feel like I am complicating things and there should be a simpler way to make it.
Here's the UI stuffs asking user to enter class information. User have to select public/private and then type in class name and JTextField
private class Handler implements ActionListener{
public void actionPerformed(ActionEvent event){
String name = inputClassName.getText();
classObject.addName(name);
while (classObject.checkName(name) == true){
JOptionPane.showMessageDialog(null, "Class name invalid. " +
"\nEntered name should not contain java keywords or equal to other existing names. " +
"\nPlease try again."); // doesn't work
name = inputClassName.getText();
classObject.addName(name);
}// end if
JOptionPane.showMessageDialog(null, "Class saved."); // doesn't work
name = inputClassName.getText();
classObject.addName(name);
}// end actionPerformed()
}// end Handler class
private class Handler2 implements ActionListener{
public void actionPerformed(ActionEvent event){
boolean b = true;
b = classObject.setPP();
}
}
private class Handler3 implements ActionListener{
public void actionPerformed(ActionEvent event){
boolean b = false;
b = classObject.setPP();
}
}
Here's the methods for storing the inputs to the ArrayList and boolean[]
Scanner input = new Scanner(System.in);
JavaKeywords keyObject = new JavaKeywords();
private ArrayList<String> className = new ArrayList<String>();
private String name = new String();
private int size = className.size();
private Boolean[] bArray = new Boolean[size];
public boolean checkName(String name){
boolean check = true;
for (int i=0; i<=size; i++){
if (keyObject.containsKeyword(className.get(i)) || name.equals(className.get(i))){
boolean o = false;
check = o;
}// end if
}// end for
return check;
}// end checkName
public boolean setPP(){
boolean b = true;
return b;
}
public void addPP(Boolean[] bArray){
this.bArray = bArray;
for (int i=0; i>=size; i++){
bArray[i] = setPP();
}
}// add a Array of boolean. for className[i], its class type = item[i] in bArray.
// public = true, private = false
public String getPublicPrivate(){
String p = "";
for (int i =0; i<=size; i++){
if(bArray[i]=true)
p = "public";
else
p = "private";
}
return p;
}
Solved
Solution: store the string className and boolean isPrivate in a class and make the class into an ArrayList can save me from all the trouble. But then i faced anther problem, that is the checkName() doesn't work after I changed my code.
here is the ActionListener
private class Handler implements ActionListener{
public void actionPerformed(ActionEvent event){
VirtualClass virtualObject = new VirtualClass();
classObject.addClass(virtualObject);
String name = inputClassName.getText();
virtualObject.className = name;
if (classObject.checkName(name) == false){
JOptionPane.showMessageDialog(null, "Class name invalid. " +
"\nEntered name should not contain java keywords or equal to other existing names. " +
"\nPlease try again."); // Always return "invalid" message
} else {
JOptionPane.showMessageDialog(null, "Class saved.");
name = inputClassName.getText();
virtualObject.className = name;
}
if (event.getSource() == publicButton) {
virtualObject.isPrivate = false;
} else if (event.getSource() == privateButton) {
virtualObject.isPrivate = true;
}
}// end actionPerformed()
and here is the checkName() method
public boolean checkName(String name){
boolean check = true;
for (int i=0; i<=size; i++){
if (keyObject.containsKeyword(classes.get(i).className) || name.equals(classes.get(i).className)){
boolean o = false;
check = o;
}// end if
}// end for
return check;
}// end checkName
For containsKeyword() in checkName() I've used a JavaKeywords class from How to check if the class name is valid? by #MrLore.
Probably what I would do is create a simple class to represent your fields so you don't have to use multiple lists at all.
public class VirtualClass {
public boolean isPrivate;
public String className = "Object";
}
ArrayList<VirtualClass> classes = new ArrayList<VirtualClass>(0);
public void addClass(VirtualClass clazz) {
classes.add(clazz);
}
Otherwise you will have to create a second list of some kind to hold the public/private. You will just have to change them in parallel.
// in actionPerformed
ClassObject.VirtualClass clazz = new ClassObject.VirtualClass();
clazz.isPrivate = rbPrivate.isSelected();
clazz.className = tfClassName.getText();
classObject.addClass(clazz);
And just ignore the listening on the radio buttons since you technically do not need their states until you go to add the class to the list.
To access the fields later you just need to
for (VirtualClass clazz : classes) {
System.out.println((clazz.isPrivate ? "private" : "public") + " " + clazz.className);
}
// or something like
for (int i = 0; i < classes.size(); i++) {
System.out.println(classes.get(i).className + ":");
if (classes.get(i).isPrivate) {
System.out.println(" private");
} else {
System.out.println(" public");
}
}
I'm not entirely convinced by your over all approach. What I think "should"/"could" happen is, the user enters all the information you ask, they hit "accept", you valid the information that the user has entered and if it is correct, you create a new object representing the results of this input as you need.
I would, personally, avoid using an array of booleans, or at least, expose them differently. The main problem I have with it is keeping it all straight in my head, what does the element at 0 actually mean?
Instead, I would provide getter/setters on the ClassName class that allowed me to set/get particular properties. You could, of course, keep the values in an array internally, but anyone using the class wouldn't need to know how you store these values.
The problem with your check name Handler is the fact you are blocking the Event Dispatching Thread with your while-loop
This will stop you program from responding to user input (and painting itself)
while (classObject.checkName(name) == true){
JOptionPane.showMessageDialog(null, "Class name invalid. " +
"\nEntered name should not contain java keywords or equal to other existing names. " +
"\nPlease try again."); // doesn't work
name = inputClassName.getText();
classObject.addName(name);
}// end if
Swing is a single threaded framework, meaning that all interactions and changes to the UI are expected to be executed within the context of the EDT. Equally, anything that blocks or stops this thread from processing the Event Queue, will stop it from responding to new events, including repaint requests, making your program hang
Instead, you should simply check the name within a if-else statement. If it's valid, create the new ClassName object, if it's not, display a message and let the method exit.
Check out Concurrency in Swing for more details
I have a list that is poulated via a local text file. I have the following code that simple prints the selected item/items when the button is click.
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
int[] selection = jList3.getSelectedIndices();
// selection.toString();
for (int i = 0; i < selection.length; i++){
Object selString = jList3.getModel().getElementAt(selection[i]);
System.out.println(selString);
}
}
Instead of printing the item I would like each button click on each object to be recorded somehow. I have no idea what kind of component, method etc to implement. Any guidance is appreciated.
My end result will be something similar to this.
System.out.println(SelString has been clicked X amount of times);
Use a hash map with your objects (selString) as keys, and a counter as value. Something like:
private Map<Object, Integer> buttonMap = new HashMap<Object, Integer>
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
Integer counter = null;
int[] selection = jList3.getSelectedIndices();
for (int i = 0; i < selection.length; i++){
Object selString = jList3.getModel().getElementAt(selection[i]);
counter = buttonMap.get(selString);
if(counter == null) {
buttonMap.put(selString, new Integer(0));
}
buttonMap.put(selString, new Integer(counter.intValue() + 1));
System.out.println(selString + " has been clicked " + buttonMap.get(selString) + " times.");
}
}
You can use PropertyChangeSupport to notify each time jList items are clicked, besides you should create a listener to receive events notification (through propertyChangeSupport.addPropertyChangeListener).
Once there, you can get the event properties such as the property name and property's new value which will be selected item on jList3 in this case, for counting how many times some item was clicked, you could use a HashMap, setting the key as the item index of jList and the associated value how many time the item has been clicked:
PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
HashMap<Integer, Integer> clickCounter = new HashMap<Integer, Integer>();
public NewJFrame() {
initComponents();
propertyChangeSupport.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("selectedIndex")) {
System.out.println("Selected index: " + evt.getNewValue());
System.out.println("Selected text: " + jList3.getModel().getElementAt(evt.getNewValue()));
if (clickCounter.containsKey((Integer) evt.getNewValue())) {
clickCounter.put((Integer) evt.getNewValue(), clickCounter.get((Integer) evt.getNewValue()) + 1);
} else {
clickCounter.put((Integer) evt.getNewValue(), 1);
}
}
}
});
}
private void jList1MouseClicked(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
propertyChangeSupport.firePropertyChange("selectedIndex", -1, jList3.getSelectedIndex());
}
At any time you can retrive how many times certian item was clicked accessing clickCounter
I would suggest using an inner class which holds whatever object you are currently putting into the JList and adding a counter member variable as well as overriding the toString().
class MyListItem
{
int selectionCount;
Object listItem; //may consider generics here, but left them out cause they can be tricky
public MyListItem(Object item)
{
selectionCount=0;
listItem=item;
}
public void incrementSelectionCount()
{
selectionCount++;
}
public String toString()
{
return listItem.toString() + " has been clicked " + selectionCount + " times.");
}
}
Then in your action listener
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt)
{
int[] selection = jList3.getSelectedIndices();
for (int selectedIndex : selection)
{
Object selString = jList3.getModel().getElementAt(selectedIndex);
if(selString instanceOf MyListItem)
{
MyListItem selItem = (MyListItem) selString;
selItem.incrementSelectionCount();
System.out.println(selString);
}
}
}
This should save time on look ups, boxing, etc. Also, this helps keep things sane as the project grows since MyListItem can be grown to deal with all types of actions you may want in the future in case you want different things to happen for things other than button presses. The basic idea here is that the MyListItem should keep track of everything you are interested in tracking so you don't need multiple lists and even worse, to remember to add an item to both a JList and a HashMap or any other data structure. This way it's either on every data structure it needs to be or not at all.