JavaFX 按钮递增和递减事件无法正常工作
JavaFX Button Increment and Decrement Event Not Working Correctly
我正在开发一个针织应用程序,它可以计算行数并以图案显示一行。
我目前遇到的问题是计数器以及它如何遍历数字。我需要一个计数器来循环遍历 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);
}
}
你的问题与 AtomicIntegers 有关,我知道的很多。
我不太擅长 AtomicIntegers,但是您可以做的一种替换是将其替换为在您的 class 中定义的普通整数。
然后向您的 int 添加一个 setter 方法以更新其 val。然后一切正常
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 开始。
您的代码有 2 个问题
- 假设您正在使用
AtomicInteger
从多个线程进行更新(因为这是此 class 的目的;您似乎没有这样做)您没有这样做原子操作,即其他线程可以修改您读取值和写入值之间的值。
- (实际问题:)您在修改值之前更新了 GUI,即您将始终看到上次修改的结果,而不是当前修改的结果。使用更新后的值赋值给
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));
});
我正在开发一个针织应用程序,它可以计算行数并以图案显示一行。
我目前遇到的问题是计数器以及它如何遍历数字。我需要一个计数器来循环遍历 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);
}
}
你的问题与 AtomicIntegers 有关,我知道的很多。 我不太擅长 AtomicIntegers,但是您可以做的一种替换是将其替换为在您的 class 中定义的普通整数。 然后向您的 int 添加一个 setter 方法以更新其 val。然后一切正常
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 开始。
您的代码有 2 个问题
- 假设您正在使用
AtomicInteger
从多个线程进行更新(因为这是此 class 的目的;您似乎没有这样做)您没有这样做原子操作,即其他线程可以修改您读取值和写入值之间的值。 - (实际问题:)您在修改值之前更新了 GUI,即您将始终看到上次修改的结果,而不是当前修改的结果。使用更新后的值赋值给
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));
});