Событие увеличения и уменьшения кнопки JavaFX не работает правильно

Я работаю над приложением для вязания, которое подсчитывает ряды и отображает ряд в узоре.

Проблема, с которой я сейчас сталкиваюсь, связана со счетчиком и тем, как он перебирает числа. Мне нужен счетчик, чтобы перебирать строки 0-3, а затем сбрасывать себя на три, и у меня есть приращение.

Однако, когда я работаю на стороне уменьшения, а затем нажимаю назад и вперед между двумя кнопками, счетчику требуется немного времени, чтобы добраться до того места, где он должен быть.

Например, когда счетчик равен 3, и я нажимаю кнопку минус, он возвращается к 0, а не к 2, как должно быть. Если я делал minusButton и переключался на plusButton, то счетчик возвращался к 0.

Я не уверен, где я ошибаюсь, но любая помощь очень ценится.

Вот мой код

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;


public class KnittingCounterApp extends Application{
    private String [] stitchNames = {"Blackberry Stitch","Pennant Sticht","Andalusian Stitch"};
    private String [] blackBerryRows = {"*(knit in the front, then back, then front again of the same stich, purl 3), repeat from * until end of the row"
                                       ,"*(purl 3 together, knit 3) repeat from * until the end of the row"
                                       ,"*(purl 3, knit in the front, then back, then front again of the same stitch), repeat from * until end of row"
                                       ,"*(knit 3, purl together 3), repeat until the end of the row"};
    private String [] pennantRows = {"knit"
                                    ,"purl 1, *(knit 1, purl 4) repeat from * until the last stitch, purl 1"
                                    ,"knit 1, *(knit 3, purl 2) repeat from * until the last stitch, knit 1"
                                    ,"knit 1, *(knit 3, purl 2) repeat from * until the last stitch, knit 1"};
    private String [] andalusianRows = {"knit"
                                       ,"purl"
                                       ,"knit 1, purl 1 repeast until the end of the row"
                                       ,"purl"};
    //int rowCounter = 0;

    //private String [] allRows = {blackBerryRows, pennantRows, andalusianRows};

    protected Text text = new Text();


    private ComboBox<String> stitchBox = new ComboBox<>();  

    @Override
    public void start(Stage primaryStage) {

        Label stitchLabel = new Label("Select Stich: ");
        RadioButton blackBerry = new RadioButton("Blackberry");
        RadioButton pennant = new RadioButton("Pennant");
        RadioButton andalusian = new RadioButton("Andalusian");
        blackBerry.setSelected(true);
        ToggleGroup stitchGroup = new ToggleGroup();
        blackBerry.setToggleGroup(stitchGroup);
        pennant.setToggleGroup(stitchGroup);
        andalusian.setToggleGroup(stitchGroup);
        VBox stitchBox = new VBox(stitchLabel, blackBerry, pennant,andalusian);
        stitchBox.setSpacing(10);

        Button plusButton = new Button("+");
        Button minusButton = new Button("-");
        HBox buttons = new HBox(20);
        buttons.getChildren().addAll(plusButton,minusButton);
        Label test = new Label();
        TextArea ta = new TextArea();
        AtomicInteger rowCounter = new AtomicInteger(0);
        plusButton.setOnAction(e->{ if(rowCounter.get() /3 == 1) {
                                        ta.setText(Integer.toString(rowCounter.get()));
                                        rowCounter.getAndSet(0);
                                    } else {
                                        ta.setText(Integer.toString(rowCounter.get()));
                                        rowCounter.updateAndGet(n->n+1);
                                    }
                                    });
        minusButton.setOnAction(e->{if(rowCounter.get() == 0) {
                                        ta.setText(Integer.toString(rowCounter.get()));
                                        rowCounter.getAndSet(3);
                                    } else {
                                        ta.setText(Integer.toString(rowCounter.get()));
                                        rowCounter.updateAndGet(n->n-1);
                                    }
                                   });
        VBox buttonBox = new VBox(10);
        buttonBox.getChildren().addAll(buttons,ta);

        BorderPane pane = new BorderPane();
        pane.setCenter(buttonBox);
        pane.setLeft(stitchBox);


        Scene scene = new Scene(pane, 550, 350);
        primaryStage.setTitle("Knit Baby Blanket Counter");
        primaryStage.setScene(scene);
        primaryStage.show();


    }


    public static void main(String[] args) {
        launch(args);

    }

}

person Perdue    schedule 30.11.2019    source источник


Ответы (2)


Есть 2 проблемы с вашим кодом

  1. Предполагая, что вы используете AtomicInteger для выполнения обновлений из нескольких потоков (поскольку это цель этого класса, вы, похоже, этого не делаете), вы не выполняете атомарные операции, т.е. другие потоки могут изменять значение между чтением значение и значение в зависимости от того, что оно пишется.
  2. (Реальная проблема:) Вы обновляете графический интерфейс перед изменением значения, т.е. вы всегда будете видеть результаты последней модификации, а не текущей. Используйте значение после обновления для назначения ta.text.

Следующий код устраняет обе проблемы, но для простоты я бы рекомендовал вместо этого просто сохранить значение в поле:

plusButton.setOnAction(e->{
    ta.setText(Integer.toString(rowCounter.updateAndGet(i -> i >= 3 ? 0 : i+1)));
});
minusButton.setOnAction(e->{
    ta.setText(Integer.toString(rowCounter.updateAndGet(i -> i <= 0 ? 3 : i-1)));
});

Альтернатива с полем:

private int rowCounter = 0;

...

plusButton.setOnAction(e -> {
    rowCounter = (rowCounter+1) % 4; // alternative using modulo here
    ta.setText(Integer.toString(rowCounter));
});
minusButton.setOnAction(e -> {
    rowCounter = (rowCounter + 3) % 4; // alternative using modulo
    ta.setText(Integer.toString(rowCounter));
});
person fabian    schedule 30.11.2019
comment
Спасибо! Ваше решение сработало для меня лучше всего. Очень ценю помощь! - person Perdue; 08.12.2019

Насколько я знаю, ваша проблема связана с AtomicIntegers. Я не очень хорошо разбираюсь в AtomicIntegers, но вы можете заменить его обычным целым числом, определенным в вашем классе. Затем добавьте метод установки в ваш int, чтобы обновить его значение. А дальше все нормально

private int rowC = 0;

        plusButton.setOnAction(actionEvent -> {
            if(rowC == 3){
                ta.setText("" +1);
                updateRow(1);
            }else{
                int n = rowC + 1;
                ta.setText(""+n);
                updateRow(n);
            }
        });
        minusButton.setOnAction(actionEvent -> {
            if(rowC == 1){
                ta.setText("" +3);
                updateRow(3);
            }else if(rowC == 0){ //Added this so that your count doesn't go to -1
                ta.setText("Please start stitching first");
            }else{
                int n = rowC - 1;
                ta.setText("" +n);
                updateRow(n);
            }
        });
    void updateRow(int n){
        rowC = n;
    }

Я проверил код, и он работает. Идет от 1-3 и 3-1.

person arcanium0611    schedule 30.11.2019