I got an application in the make here and working on a basket.
This is the button (everytime a product gets added it gets a X delete button):
for(int i=0;i < products.size(); i++){
btnDeleteproduct = new JButton("X");
btnDeleteproduct.setBounds(380, verticalPosition + i * productOffset, 20, 20);
btnDeleteproduct.setFont(WinkelApplication.FONT_10_BOLD);
btnDeleteproduct.setName("" + i);
btnDeleteproduct.addActionListener(this);
this.add(btnDeleteproduct);
}
productamount is to set up the label aantal with the amount of products:
productamount = (int) WinkelApplication.getBasket().getProductAmount(productdelete);
if (event.getSource() == btnDeleteproduct) {
productamount--;
lblamount.setText("" + productamount);
WinkelApplication.getInstance().showPanel(new view.Payment());
if (productamount < 1) {
WinkelApplication.getBasket().deleteProduct(productdelete);
}
}
Now the last batch is the deleteProduct method:
public void deleteProduct(Product product) {
// check if product is allready added to the basket
if (products.containsKey(product)) {
products.remove(product);
WinkelApplication.getInstance().showPanel(new view.Payment());
}
if(products.size() == 0){
WinkelApplication.getInstance().showPanel(new view.CategoryList());
}
}
Ok I have got two problems with this. 1) The label doesn't respond to setText in the button so it doesn't change if i put it in a other button it does change. 2) if I add more than 1 products i can only delete products from bottom to top, so it only reacts to the last button made and then the following and so on.
Hope anyone can help!
For point two:
for(int i=0;i < products.size(); i++){
btnDeleteproduct = new JButton("X");
btnDeleteproduct.setBounds(380, verticalPosition + i * productOffset, 20, 20);
btnDeleteproduct.setFont(WinkelApplication.FONT_10_BOLD);
btnDeleteproduct.setName("" + i);
btnDeleteproduct.addActionListener(this);
this.add(btnDeleteproduct);
}
When creating the delete buttons, you only keep the btnDeleteproduct reference. As you overwrite it in each iteration, you only keep the last one for the
if (event.getSource() == btnDeleteproduct) {
check in your listener.
Solution: Create a listener class that holds the key of the product that you want to delete. Instantitate a different object for each button, and add it as a listener instead of using a single listener for all of them.
Related
I have one button in place. For each number a user sets in a text field, the appropriate number of buttons adds to the ui. But for every change of number i want all the buttonAdded to be removed, but not the first one, that is already in place. How do i do that? It didn't work when i tried it like in the exmaple:
final int number = Integer.parseInt(this.textField.getValue());
if(number > 1) {
for(int i = 1; i < number; i++) {
final XdevButton buttonAdded = new XdevButton("Button " + i);
this.verticalLayout.removeComponent(buttonAdded);
this.verticalLayout.addComponent(buttonAdded);
}
}
Is there a way to create new buttons with a defined component name in my loop?
Something like this:XdevButton button + i = new XdevButton()?
Edit:(Tried it with a list) - doesn't work.
private void textField_valueChange(final Property.ValueChangeEvent event) {
final int number = Integer.parseInt(this.textField.getValue());
final List<XdevButton> addedButtons = new LinkedList<>();
for(final XdevButton btn : addedButtons) {
this.verticalLayout.removeComponent(btn);
}
addedButtons.clear();
if(number > 1) {
for(int i = 1; i < number; i++) {
final XdevButton buttonAdded = new XdevButton("Button " + i);
addedButtons.add(buttonAdded);
for(final XdevButton btn : addedButtons) {
this.verticalLayout.addComponent(btn);
}
}
}
}
What am i missing?
That indeed won't work, nor is it possible to name a button the way you are asking.
You have a few options, if you don't want to reuse the old buttons.
If the vertical layout only contains buttons, or if you know how many components there are before the buttons, you can remove them by index:
for(int i = 1; i < number; i++) {
this.verticalLayout.getElement().removeChild(i);
}
You can also create a list or other collection to keep track of the buttons, this way you can reuse them as well:
private List<Button> buttons = new LinkedList<>();
...
// Not enough buttons, need to add new ones
if (number > buttons.size()) {
for(int i = buttons.size(); i < number; i++) {
Button buttonAdded = new Button("Button " + i);
buttons.add(buttonAdded);
}
}
// Too many buttons, remove the extras
else if (buttons.size() > number) {
List<Button> buttonsToRemove = buttons.subList(number, buttons.size());
buttonsToRemove.forEach(verticalLayout::remove);
buttonsToRemove.clear();
}
I would create a separate layout holder for buttons to be removed/added and work with it. For testing purposes I've replaced your XdevButton with a general Vaadin Button class. This seems to work according to your specs:
#Route("customView")
public class CustomView extends VerticalLayout {
VerticalLayout buttonHolder=new VerticalLayout();
public CustomView (){
TextField tf=new TextField("Enter amount of buttons");
tf.addValueChangeListener(event->{
final int number = Integer.parseInt(event.getValue());
if(number > 1) {
buttonHolder.removeAll();
for(int i = 0; i < number; i++) {
final Button buttonAdded = new Button("Button " + i);
buttonHolder.add(buttonAdded);
}
}
});
Button alwaysInPlace=new Button("This button is never removed");
add(alwaysInPlace);
add(buttonHolder);
}
}
Example is created in V14, but should be similar in all other versions
I have the following code, that allows me to remove a row from the right Jtable with a click. It works fine for all the rows, except when there is only one row remaining. BTW, sorry for most names being in portuguese, its my native language. Here are the images showing before and after i click the final row in the table. It updates the total, but the row remains. For every other case, it works perfectly.
Screenshot:
private void jtbSelecionadosMouseClicked(java.awt.event.MouseEvent evt)
{
int x = jtbSelecionados.rowAtPoint(evt.getPoint());
if (x >= 0)
{
String nomeProduto = (String)jtbSelecionados.getModel().getValueAt(x, 0);
for (int i = 0; i < itensVenda.size();i++)
{
if (itensVenda.get(i).getNomeProduto().equals(nomeProduto))
{
if(itensVenda.get(i).getQtd() > 1)
{
valorTotal -= (itensVenda.get(i).getPreco() / itensVenda.get(i).getQtd());
double precototal = itensVenda.get(i).getPreco();
double unit = precototal / itensVenda.get(i).getQtd();
System.out.println("Unidade: "+unit+"\nTotal: "+precototal);
itensVenda.get(i).setPreco(itensVenda.get(i).getPreco() - (itensVenda.get(i).getPreco() / itensVenda.get(i).getQtd()));
itensVenda.get(i).setQtd(itensVenda.get(i).getQtd() - 1);
recarregarTabela();
}
else if(itensVenda.get(i).getQtd() <= 1)
{
valorTotal -= itensVenda.get(i).getPreco() / itensVenda.get(i).getQtd();
itensVenda.remove(i);
recarregarTabela();
}
}
}
}
function that resets the table with new information:
private void recarregarTabela()
{
if (itensVenda.size() == 0)
{
dtm.getDataVector().removeAllElements();
dtm.setRowCount(0);
lblTotal.setText("Total: R$" + String.valueOf(valorTotal));
}
else
{
dtm.getDataVector().removeAllElements();
dtm.setRowCount(0);
for (Item item : itensVenda)
{
Object[] vetor = new Object[3];
vetor[0] = item.getNomeProduto();
vetor[1] = item.getQtd();
vetor[2] = String.format("%.2f", item.getPreco());
System.out.println(item.getPreco());
dtm.addRow(vetor);
}
lblTotal.setText("Total: R$" + String.valueOf(valorTotal));
}
}
You dont have to rebuild whole model everytime a single row is deleted. As you already have index of clicked or selected row you can just remove it from model using removeRow(index) method. I suspect that dtm is a DefaultTableModel so just call dtm.removeRow(index) everytime you need to remove row from table
I am writing a program where users answer questions by clicking on JTable cells. If the question is answered correctly/incorrectly, the MouseListener changes the value of answeredResult. The program will keep running until there are no available questions (the available array list contains a list of Items, which is a class I created that contains strings event, year, and description, called by getEvent(), getYear(), and getDescription() methods respectively). However, for each question, I want to wait until a mouseClickedEvent is detected before executing the proceeding code (see below).
I know that adding another while loop for waiting is really bad. I've also seen
some answers suggesting to put whatever I want to do in the mouseClicked method, but I don't know how in my case, since I want to repeat it multiple times.
I think another problem is that the program is stuck in the while(available.size()!=0) loop. So it cant detect the mouse click.
Any suggestions on how to make this work?
ArrayList<Item> available = new ArrayList<Item>();
for(int i = 0; i < 5; i++){
available.add(new Item("Event " + i, "Year " + i, "Description " + i));
}
JTable table = new JTable(model);
table.addMouseListener(new java.awt.event.MouseAdapter() {
#Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
int row = table.rowAtPoint(evt.getPoint());
int col = table.columnAtPoint(evt.getPoint());
if (row >= 0 && col == 2 && canPlay) {
clickedYear = (String)data[row][col];
if(clickedYear.equals(answerYear)){
answeredResult = 1;
}else{
answeredResult = -1;
}
}
}
});
while(available.size()!=0){
promptPanel.removeAll();
answeredResult = 0; //0-unanswered 1-correct 2-incorrect
int random = (int)(Math.random()*(available.size()-1));
JLabel label = new JLabel(available.get(random).getEvent()+"\n");
promptPanel.add(label);
canPlay = true;
//wait for mouse clicked before proceeding to the next code
if(answeredResult == 1){
JLabel correct = new JLabel("Correct!");
promptPanel.add(correct);
}else if(answeredResult == -1){
JLabel wrong = new JLabel("Wrong.");
promptPanel.add(wrong);
}
revalidate();
repaint();
available.remove(random);
}
for (int b = 0; b < Hsize; b++) {
for (int c = 0; c < Lsize; c++) {
System.out.println(Hsize + Lsize);
Button[b][c] = new JButton("b:" + b + "c:" + c);
Button[b][c].setBounds(l, h, 40, 40);
Button[b][c].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(e.getSource());
}
});
}
}
The output if one of the buttons is pressed:
javax.swing.JButton[0 2,95,105,40x40,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource#53c0c322,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=D:/Users/Max/workspace/Battleship/images/Unbenannt.png,disabledIcon=D:/Users/Max/workspace/Battleship/images/Unbenannt.png,disabledSelectedIcon=D:/Users/Max/workspace/Battleship/images/Unbenannt.png,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=,defaultCapable=true]
How can I filter out only the {0 2, or anything different for example the b/c coordinate ?
Since you've attached the listener to the button, you know that the triggering object is a Button. You can cast it into a button and then use the get methods to access the information you need. Right now you're just printing everything about the object.
public void actionPerformed(ActionEvent e) {
Button b = (Button)e.getSource();
System.out.println(b.getAlignmnetX()); //get whatever you need
}
Button inherits from a bunch of classes, so you'll have to look up the documentation to figure out which get methods are available for you to use.
http://docs.oracle.com/javase/7/docs/api/java/awt/Button.html
I'm decently new to Java. I want the user to be able to input 4 different inputs separately by clicking submit. I'm using a for loop to count, but I do not know how to have the user input their answer multiple times. The for loops just repeats all at once. I'm using arrays to hold the user's answers. Here is part of my code. If you have questions or need more explanation I will def. explain more
private void Question1()
{
int count = 1;
QuestionsPanel.add(new JLabel(Q1.getQuestion()));
QuestionsPanel.add(new JLabel(Arrays.toString(mans1)));
AnswerField = new JTextField(10);
AnswerPanel.add(AnswerField);
Submit = new JButton("Submit");
AnswerPanel.add(Submit);
Submit.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if ((e.getSource() == Submit) && count == 0)
{
int value = Integer.parseInt(AnswerField.getText());
for (int i = 0; i < 4; i++)
{
if (value == -1) break;
ans[i] = value - 1;
AnswerField.setText("");
}
This doesn't work because you placed the loop in the ActionListener, which is executed once on button click.
What you should do is to keep a counter of the current answer somewhere
int count = 0;
public void actionPerformed(ActionEvent e) {
if ((e.getSource() == Submit) && count < 4) {
int value = Integer.parseInt(AnswerField.getText());
if (value == -1) break;
ans[count++] = value - 1;
AnswerField.setText("")
}
}
In this way the loop is implicitly managed by the actionlistener: everytime you press submit count is incremented by 1 and the correct answer is placed inside the array. Of course you should do something, like disabling the submit button, upon submitting the fourth answer.