I have this SOAP based webservice implemented in Java where the client has a list of checkboxes which after he selects will be stored in the DB.For example for a checkbox of Sex(maschio,femmina) he can select both of them or one of them i implemented it like this but the issue is that the array has fixed size in this case 2 so if the user selects only one of them sexarra[0] will contain it but sexarra[1] will be null so if i pass it to the server it can create problems and the other checkboxes are much larger in size is there any better way to handle this situation? Thank you all in advance your help is really appreciated! i should add that System.out are for testing only:
private void femminaActionPerformed(java.awt.event.ActionEvent evt) {
if (femmina.isSelected()) {
if (sexint == 0) {
sexint++;
sexarra[sexint] = femmina.getText();
} else {
sexarra[sexint] = femmina.getText();
}
}
System.out.println(sexarra[0]);
System.out.println(sexarra[1]);
}
private void maschioActionPerformed(java.awt.event.ActionEvent evt) {
if (maschio.isSelected()) {
if (sexint == 0) {
sexarra[sexint] = maschio.getText();
sexint++;
} else {
sexarra[sexint] = maschio.getText();
}
}
System.out.println(sexarra[0]);
System.out.println(sexarra[1]);
}
please read How to Use Buttons, Check Boxes, and Radio Buttons and if there are lots of checkboxes then you have to read How to Use the ButtonGroup Component, something about Action Listener, you can find examples here
You don't need any event handler.
If you do need to populate some arrays, only do it when you are submitting your data in the end. Each button knows its state; there is no need to redundantly store this info in another data structure each time a button is clicked.
In the end, when submitting the finalized data:
System.out.println(jButton1.getName() + ": " + jButton1.isSelected());
System.out.println(jButton2.getName() + ": " + jButton2.isSelected());\
...
Instead of printing out in your code, you just fill whatever data structure you are sending to the DB when you are ready to submit.
Also you should think about synchronization: you want one method that runs on the Swing EDT to fill your data structure, but some other method on another thread to send those to the DB. And somehow you must make sure the data is synchronized between the two threads.
Ok i resolved the problem i had, i introduced an integer sexint which gets updated whenever one of the checkboxes is selected thus determining the size of the array here is the code:
private void femminaActionPerformed(java.awt.event.ActionEvent evt) {
if(femmina.isSelected()){
if(sexint==0){
sexint++;
sexone=femmina.getText();
}
else if(sexint==1){
sexint++;
sextwo=femmina.getText();
}
else
sexint--;
System.out.println(sexint);
}
}
private void maschioActionPerformed(java.awt.event.ActionEvent evt) {
if(maschio.isSelected()){
if(sexint==0){
sexint++;
sexone=maschio.getText();
}
else if(sexint==1){
sexint++;
sextwo=maschio.getText();
}
else
sexint--;
System.out.println(sexint);
}
}
after which i take sexint and use it to instantiate the array sexarra
Thanks everybody for having taken their time in looking at my problem
Related
I'm trying to do a swing application which adds names to an ArrayList and then displays it in Jcombobox.I already did the window and everything but I can't seem to get the hang off detecting duplicate names.
I tried
btnnext.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
if(checkDuplicate(names)==true)
{
names.add(txtname.getText());
txtname.setText("");
}
else {
JOptionPane.showMessageDialog(null,"DUPLICATE! do not add");
}
}
});
public static boolean checkDuplicate(ArrayList<String> list) {
HashSet set = new HashSet();
for (int i = 0; i < list.size(); i++) {
boolean val = set.add(list.get(i));
if (val == false) {
return val;
}
}
return true;
}
It only says that I have duplicate when I already add it to the ArrayList and when I get the message I can't add anything else.
input example:
test
test
and then it stops accepting new Strings and only displays the message DUPLICATE! do not add
As I said in my comment:
This happens because you are basically creating a Set view of your ArrayList every time you call checkDuplicate rather than comparing the item you're trying to add with the existing list. In other words your checkDuplicate is written such that it only returns true when a duplicate already exists within the list. You need to compare the new item with the list instead. Step through your logic carefully either with a debugger or by manually writing down the values of your variables and you will see the problem.
You could simply change this line:
if(checkDuplicate(names)==true)
to this:
if(!names.contains(txtname.getText()))
You don't really need checkDuplicate since it's "reinventing the wheel" so to speak. ArrayList already provides a contains method that you can use to your advantage.
I have two questions about Java Convention. I try to make use od Robert C. Martin's "Clean Code".
Following case:
public void startProgressIfAllowed() {
try {
tryStartProgressIfAllowed();
} catch (Exception exception) {
// log error
}
}
private void tryStartProgressIfAllowed() {
if (isStartProgressAllowed()) {
stopProgressOnCurrentlyStartedTask();
startProgressOnThisTask();
}
}
private boolean isStartProgressAllowed() {
// Calls JOptionPane.showConfirmDialog with JOptionPane.YES_NO_OPTION.
// Created dialog contains checkbox indicating that saving currently started task is required.
// returns boolean depending on JOptionPane.YES_NO_OPTION clicked button
}
private void stopProgressOnCurrentlyStartedTask() {
// Saves currently started task depending on checkbox selecion property and stops currently started.
// What is the correct way to get checkbox selecion property?
}
Proposed solution:
public void tryStartProgressIfAllowed() {
if (tryToStopProgressOnStartedTaskIfNecessary()) {
startProgressOnThisTask();
}
}
private boolean tryToStopProgressOnStartedTaskIfNecessary() {
// Calls JOptionPane.showConfirmDialog with JOptionPane.YES_NO_OPTION.
// Created dialog contains checkbox indicating that saving currently started task is required.
// Depending on checkbox selecion property saves task.
// returns boolean depending on JOptionPane.YES_NO_OPTION clicked button
}
But this approach doesn't meet the "Command Query Separation" principle, because tryToStopProgressOnStartedTaskIfNecessary(...) method performs some logic and returns success/failure value.
I think this approach also doesn't meet the "One level of abstraction per function" principle, because I suppose "check" and "save" operations are on different levels of abstraction.
Is the method name correct to avoid disinformation? Maybe better name would be tryToStopProgressAndSaveStartedTaskIfNecessary(...)?
Is there any better solution for above problem?
What about the following:
public void tryStartProgressOnThisTaskIfAllowed() {
tryStopTaskInProgressIfAllowed()
if (!isTaskInProgress()) {
tryStartProgressOnThisTask();
}
}
private void tryStopTaskInProgressIfAllowed() {
if (!isTaskInProgress()) {
return;
}
TaskInProgressResult result = whatToDoWithTaskInProgress();
if (result == Result.KEEP) {
return;
} else if (result == Result.DROP)
tryDropTaskInProgress();
} else if (result == Result.SAVE) {
trySaveTaskInProgress();
}
}
About your points:
You now have two separate methods for C and Q
I think the two things whatToDoWithTaskInProgress and tryDropTaskInProgress are the same level of abstraction. If you'd inline the code of one or the other you were absolutely right of course.
I changed some of the method names according to my taste :) The only thing I still don't like is the part "OnThisTask" because this task is somewhat meaningless. Maybe it's only because the rest of the code is unknown maybe OnNextTask or OnNewTask are better.
The problem we were having is that we were thinking in UI terms YES/NO + checkbox value. But it is much better to think in business terms here. I identified three different outcomes that are of interest: KEEP, SAVE, DROP How the answer is obtained should not matter to the calling method.
This seems something to ask on CodeReview, see the drop down at the top left of the page.
An example of how such stateliness is realized in Java SE: the regex Matcher class.
String s = ...
Pattern pattern = Pattern.compile("...");
Matcher m = pattern.matcher(s);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, ... m.group(1) ...);
}
m.appendTail(sb);
with m.matches() and m.lookingAt as alternative circuits too.
In short state is held in a processing class on the actual data (String here).
I've created a static Input class, that basicly have a method that I can call, which is this:
public static boolean GetKeyDown(int keyCode) {
while(Keyboard.next()) {
Keyboard.enableRepeatEvents(false);
if (Keyboard.getEventKeyState()) {
if (Keyboard.getEventKey() == keyCode) {
return true;
} else {
return false;
}
}
}
return false;
}
And in my game update loop, I've wanted to use this, instead of having to make a single while-loop:
if(Input.GetKeyDown(KeyCode.S)) {
//Something happens
}
if(Input.GetKeyDown(KeyCode.R)) {
//Something happens
}
//etc..
But it seems that only the first one loaded, will work. In this case 'S'. Is there a way for me to do be able to use the others too?
That is because in your GetKeyDown() method, you call Keyboard.next(), when you call that method it removes the Event of the current key from Keyboard, the only gets refilled with Events, when you call Display.update();
NOTE: This method does not query the operating system for new events. To do that, Display.processMessages() (or Display.update()) must be called first.
Source: LWJGL Docs
You Could
Instead you can use the Keyboard.isKeyDown(int key) method, to achieve what you're trying to do.
Though it returns true/false depending on the following.
Returns: true if the key is down according to the last poll()
But that still doesn't quite fix the problem because it relies on the poll() method.
Fixing The Problem
You can fix the problem by creating some custom methods to use with the Keyboard class, as you already did, though as said the Keyboard Events only gets updated when you call the Display.update(); method.
You already got the right idea about which function to create, though you need to split them into, two different methods. You need a secondary method which you call once each time you want to update your keyboard.
public class MyKeyboard {
/*
* Remember that the index where we store the value,
* is the index of the key. Thereby one key might have
* an index of 400, then your array need to have at least
* the same size, to be able to store it.
*/
public static boolean[] keys = new boolean[100]; // 100 is the amount of keys to remember!
public static void update() {
while(Keyboard.next()) {
if (Keyboard.getEventKey() < keys.length) {
keys[Keyboard.getEventKey()] = Keyboard.getEventKeyState();
}
}
}
public static boolean isKeyDown(int key) {
if ((key > 0) && (key < keys.length)) {
return keys[key];
}
return false;
}
}
Remember to only call the MyKeyboard.update() method once per Display.update() I also renamed your GetKeyDown() method to isKeyDown(), because I think that sounds and describes it better, but you can rename it again in your project if you want to.
The above code was made within this answer, without the use of an IDE, etc. So if there's anything wrong with it I apologize, but just comment and I will fix it.
One problem that arises with this method is the lack of rechecking. Since Keyboard.next() only checks the inputs that have occurred in the current frame. A button which was once pressed will remain "pressed" until it is pressed again. I ran into this problem while trying to implement this solution. The answer to this new problem is here:
public static void update() {
for(int i = 0; i < keys.length; i++) {
keys[i] = false;
}
while(Keyboard.next()) {
keys[Keyboard.getEventKey()] = Keyboard.getEventKeyState();
}
}
You must clear the keypresses of the previous frame by setting everything to false.
I noticed I can use getName() as part of the trick.
What is java.awt.Component.getName() and setName() used for?
But I don't really have a clue where to start. What type of listener should I use (assuming the textfield / or box is currently blinking / selected)
This is my previous question, and thank you for the help guys.
How do I use requestFocus in a Java JFrame GUI?
I realize that for each component (Textfield) that I am creating, I have to insert a statement like requestFocus (or using transferFocus).
Is it possible to apply this policy to all the fields???
I have several textfields and ComboBox. The problem I hit is that I don't want to write methods for every single field / box.
For example, I write a method like this
private JTextField getFirstNameEntry() {
.... do something
}
because my instructor writes his program like this
private JPanel getJContentPane() {
jContentPane = new JPanel();
jContentPane.setLayout(new java.awt.FlowLayout(FlowLayout.LEADING));
jContentPane.add(makeLabel(" First Name *", 100, 20));
jContentPane.add(getFirstNameEntry(), null);
jContentPane.add(makeLabel(" Middle Initial", 100, 20));
jContentPane.add(getMiddleInitialEntry(), null);
// etc
return jContentPane;
However, to save redundancy (that was my motive at first), say I have a box, I can simply add the following code inside the method above: getJContentPane()
titleBox = new JComboBox(new String[]{"Mr.","Mrs.","Ms.","Dr.","Prof.","Rev."});
jContentPane.add(titleBox);
But doing this, I still need to create a method to do addItemListener
private void setComboBoxFocus() {
titleBox.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = titleBox.getSelectedItem().toString();
System.out.println(titleSelected);
titleBox.transferFocus();
}
}
});
}
However, this doesn't really save redundancy at all. If I have more than one ComboBox to be added, I would have to write another similar method. In fact, even in the case with one ComboBox (titleBox), I would still end up with writing a method for titleBox.
So my question is: is there a way to write a general method that can call focus to all (maybe one for ComboBox type)?
Thank you and sorry for the long post.
Why not take a JComboBox argument to your setComboBoxFocus() method, which allows you to set that listener to any JComboBox you may have? Like so:
private void setComboBoxFocus(JComboBox box) {
box.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = box.getSelectedItem().toString();
System.out.println(titleSelected);
box.transferFocus();
}
}
});
}
I'm trying to set a combobox in my GUI to print the the information about a student in a JLabel.
private void studentComboBoxMouseClicked(java.awt.event.MouseEvent evt) {
if combobox1="student1"{
println.jlabel."name:a";
println.jlabel.""age:12";
println.jlabel."course:english";
}
if combobox1="student2"{
println.jlabel."name:b";
println.jlabel.""age:11";
println.jlabel."course:maths";
}
if combobox1="student3"{
println.jlabel."name:c";
println.jlabel.""age:10";
println.jlabel."course:science";
}
}
You have to listen for itemstatechange on your combobox,
Upon selecting your student , fetch the selected item and operate on to display appropriate messages.
Have a look at this example
If it is a pseudocode, then it's correct. But in java the same code would be:
if ("student1".equals(combobox1)) {
jlabel.setText("name:a age:12 course:english");
} else if ("student2".equals(combobox1)) {
jlabel.setText(...);
} else if ("student3".equals(combobox1)) {
jlabel.setText(...);
}
Of course, it works if combobox1 is String, which holds the value of your combobox.
You are on the right track but you need to read more tutorials. Start with the one suggested by Babban Shikaari. Your code should be something similar to this:
if (combobox.getSelectedItem().equals("student1")){
jlabel.setText("Your new information");
}