如何访问 class' 范围之外的变量?
How can I access a variable that is out of a class' scope?
我正在尝试编写一个 JavaFX 数独程序,用户可以通过以下方式填充单元格:
- 单击九个按钮之一(对应于 1-9)
- 单击其中一个单元格
代码的工作方式是,当单击一个按钮时,对应于该按钮的 int 被分配给 selectedNum
。当单击 Cell 时,Cell 会将其文本分配给 selectedNum
。然而,这就是问题所在——在 Cell
构造函数中实现 setOnAction 函数。 Cell
无法访问 selectedNum
。当 selectedNum 是一个超出其 class 范围的变量时,我如何传递它?
单元格Class:
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
/**
* The Cell class inherits StackPane, representing one of the cells in Sudoku.
* @author rkuni
*
*/
public class Cell extends StackPane{
private Text text; //displays the number inside the cell
private Rectangle rect; //visual element for the cell
/**
* Default Constructor for Cell
*/
public Cell() {
text = new Text("");
text.setFont(Font.font(30));
rect = new Rectangle(50, 50);
rect.setStyle("-fx-fill: white; -fx-stroke: black; -fx-stroke-width: 1;");
this.getChildren().add(rect);
this.getChildren().add(text);
this.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
text.setText("" + 1); //when clicked, I want to set text to the number that is selected.
}
});
}
}
主要Class
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Font;
public class Main extends Application {
private int selectedNum = 0;
@Override
public void start(Stage primaryStage) {
try {
Group root = new Group();
Cell cell1 = new Cell();
cell1.setLayoutX(100);
cell1.setLayoutY(100);
root.getChildren().add(cell1);
Button numSelection[] = new Button[9];
for (int i = 0; i < 9; i++) {
final int j = i;
numSelection[i] = new Button("" + (i + 1));
numSelection[i].setLayoutY((i / 3) * 55 + 200);
numSelection[i].setLayoutX((i % 3) * 55 + 630);
numSelection[i].setMinHeight(50);
numSelection[i].setMinWidth(50);
numSelection[i].setFont(Font.font(20));
root.getChildren().add(numSelection[i]);
numSelection[i].setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
selectedNum = j + 1;
}
});
}
Scene scene = new Scene(root,900,500);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
可能的解决方案
一个潜在的解决方案是根本没有 Cell class,代码将起作用。问题不再存在,因为所有变量都在同一范围内。但是,我想保留 Cell class,因为它可以使代码更有条理。无论如何,它在这里:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
public class Main extends Application {
private int selectedNum; //will take the value of the last pressed button (1-9)
@Override
public void start(Stage primaryStage) {
try {
Group root = new Group();
//setting up a stackpane that will contain a rect and text, making for a "cell"
StackPane stack1 = new StackPane();
Text text1 = new Text("");
Rectangle rect1 = new Rectangle(50,50);
rect1.setStyle("-fx-fill: white; -fx-stroke: black; -fx-stroke-width: 1;");
stack1.getChildren().add(text1);
stack1.getChildren().add(rect1);
stack1.setLayoutX(100);
stack1.setLayoutY(100);
stack1.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
text1.setText("" + selectedNum); //when clicked, set text to the number that is selected.
}
});
//setting up the buttons that will designate which number will go into the cell.
Button numButtons[] = new Button[9];
for (int i = 0; i < 9; i++) {
final int j = i;
numButtons[i] = new Button("" + (i + 1));
numButtons[i].setLayoutY((i / 3) * 55 + 200);
numButtons[i].setLayoutX((i % 3) * 55 + 630);
numButtons[i].setMinHeight(50);
numButtons[i].setMinWidth(50);
numButtons[i].setFont(Font.font(20));
root.getChildren().add(numButtons[i]);
numButtons[i].setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
selectedNum = j + 1;
}
});
}
text1.toFront();
root.getChildren().add(stack1);
Scene scene = new Scene(root,900,500);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
我也考虑过重写函数以添加参数,但还没有成功。
像这样的事情的(或多或少)标准方法是使用 MVC 设计模式的某种变体。这里的关键是有一个单独的 class (“模型”)来保存数据;然后,您可以将 class 的单个实例传递给需要访问它的任何参与者。
public class Model {
private int currentlySelectedValue ;
// probably other properties here...
public void setCurrentlySelectedValue(int value) {
currentlySelectedValue = value ;
}
public int getCurrentlySelectedValue() {
return currentlySelectedValue ;
}
}
那么你可以这样做:
public class Cell extends StackPane{
private final Model model ;
private Text text; //displays the number inside the cell
private Rectangle rect; //visual element for the cell
/**
* Default Constructor for Cell
*/
public Cell(Model model) {
this.model = model ;
text = new Text("");
text.setFont(Font.font(30));
rect = new Rectangle(50, 50);
rect.setStyle("-fx-fill: white; -fx-stroke: black; -fx-stroke-width: 1;");
this.getChildren().add(rect);
this.getChildren().add(text);
this.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
text.setText("" + model.getCurrentlySelectedValue());
}
});
}
}
和
public class Main extends Application {
private int selectedNum = 0;
@Override
public void start(Stage primaryStage) {
Model model = new Model();
try {
Group root = new Group();
Cell cell1 = new Cell(model);
cell1.setLayoutX(100);
cell1.setLayoutY(100);
root.getChildren().add(cell1);
Button numSelection[] = new Button[9];
for (int i = 0; i < 9; i++) {
final int j = i + 1;
numSelection[i] = new Button("" + j);
numSelection[i].setLayoutY((i / 3) * 55 + 200);
numSelection[i].setLayoutX((i % 3) * 55 + 630);
numSelection[i].setMinHeight(50);
numSelection[i].setMinWidth(50);
numSelection[i].setFont(Font.font(20));
root.getChildren().add(numSelection[i]);
numSelection[i].setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
model.setCurrentlySelectedValue(j);
}
});
}
Scene scene = new Scene(root,900,500);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
请注意,如果您只需要一个值,则有一些“捷径”方法;例如您可以使用 IntegerProperty
而不是自定义模型 class。结构和概念确实是一样的。
我正在尝试编写一个 JavaFX 数独程序,用户可以通过以下方式填充单元格:
- 单击九个按钮之一(对应于 1-9)
- 单击其中一个单元格
代码的工作方式是,当单击一个按钮时,对应于该按钮的 int 被分配给 selectedNum
。当单击 Cell 时,Cell 会将其文本分配给 selectedNum
。然而,这就是问题所在——在 Cell
构造函数中实现 setOnAction 函数。 Cell
无法访问 selectedNum
。当 selectedNum 是一个超出其 class 范围的变量时,我如何传递它?
单元格Class:
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
/**
* The Cell class inherits StackPane, representing one of the cells in Sudoku.
* @author rkuni
*
*/
public class Cell extends StackPane{
private Text text; //displays the number inside the cell
private Rectangle rect; //visual element for the cell
/**
* Default Constructor for Cell
*/
public Cell() {
text = new Text("");
text.setFont(Font.font(30));
rect = new Rectangle(50, 50);
rect.setStyle("-fx-fill: white; -fx-stroke: black; -fx-stroke-width: 1;");
this.getChildren().add(rect);
this.getChildren().add(text);
this.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
text.setText("" + 1); //when clicked, I want to set text to the number that is selected.
}
});
}
}
主要Class
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Font;
public class Main extends Application {
private int selectedNum = 0;
@Override
public void start(Stage primaryStage) {
try {
Group root = new Group();
Cell cell1 = new Cell();
cell1.setLayoutX(100);
cell1.setLayoutY(100);
root.getChildren().add(cell1);
Button numSelection[] = new Button[9];
for (int i = 0; i < 9; i++) {
final int j = i;
numSelection[i] = new Button("" + (i + 1));
numSelection[i].setLayoutY((i / 3) * 55 + 200);
numSelection[i].setLayoutX((i % 3) * 55 + 630);
numSelection[i].setMinHeight(50);
numSelection[i].setMinWidth(50);
numSelection[i].setFont(Font.font(20));
root.getChildren().add(numSelection[i]);
numSelection[i].setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
selectedNum = j + 1;
}
});
}
Scene scene = new Scene(root,900,500);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
可能的解决方案
一个潜在的解决方案是根本没有 Cell class,代码将起作用。问题不再存在,因为所有变量都在同一范围内。但是,我想保留 Cell class,因为它可以使代码更有条理。无论如何,它在这里:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
public class Main extends Application {
private int selectedNum; //will take the value of the last pressed button (1-9)
@Override
public void start(Stage primaryStage) {
try {
Group root = new Group();
//setting up a stackpane that will contain a rect and text, making for a "cell"
StackPane stack1 = new StackPane();
Text text1 = new Text("");
Rectangle rect1 = new Rectangle(50,50);
rect1.setStyle("-fx-fill: white; -fx-stroke: black; -fx-stroke-width: 1;");
stack1.getChildren().add(text1);
stack1.getChildren().add(rect1);
stack1.setLayoutX(100);
stack1.setLayoutY(100);
stack1.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
text1.setText("" + selectedNum); //when clicked, set text to the number that is selected.
}
});
//setting up the buttons that will designate which number will go into the cell.
Button numButtons[] = new Button[9];
for (int i = 0; i < 9; i++) {
final int j = i;
numButtons[i] = new Button("" + (i + 1));
numButtons[i].setLayoutY((i / 3) * 55 + 200);
numButtons[i].setLayoutX((i % 3) * 55 + 630);
numButtons[i].setMinHeight(50);
numButtons[i].setMinWidth(50);
numButtons[i].setFont(Font.font(20));
root.getChildren().add(numButtons[i]);
numButtons[i].setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
selectedNum = j + 1;
}
});
}
text1.toFront();
root.getChildren().add(stack1);
Scene scene = new Scene(root,900,500);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
我也考虑过重写函数以添加参数,但还没有成功。
像这样的事情的(或多或少)标准方法是使用 MVC 设计模式的某种变体。这里的关键是有一个单独的 class (“模型”)来保存数据;然后,您可以将 class 的单个实例传递给需要访问它的任何参与者。
public class Model {
private int currentlySelectedValue ;
// probably other properties here...
public void setCurrentlySelectedValue(int value) {
currentlySelectedValue = value ;
}
public int getCurrentlySelectedValue() {
return currentlySelectedValue ;
}
}
那么你可以这样做:
public class Cell extends StackPane{
private final Model model ;
private Text text; //displays the number inside the cell
private Rectangle rect; //visual element for the cell
/**
* Default Constructor for Cell
*/
public Cell(Model model) {
this.model = model ;
text = new Text("");
text.setFont(Font.font(30));
rect = new Rectangle(50, 50);
rect.setStyle("-fx-fill: white; -fx-stroke: black; -fx-stroke-width: 1;");
this.getChildren().add(rect);
this.getChildren().add(text);
this.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
text.setText("" + model.getCurrentlySelectedValue());
}
});
}
}
和
public class Main extends Application {
private int selectedNum = 0;
@Override
public void start(Stage primaryStage) {
Model model = new Model();
try {
Group root = new Group();
Cell cell1 = new Cell(model);
cell1.setLayoutX(100);
cell1.setLayoutY(100);
root.getChildren().add(cell1);
Button numSelection[] = new Button[9];
for (int i = 0; i < 9; i++) {
final int j = i + 1;
numSelection[i] = new Button("" + j);
numSelection[i].setLayoutY((i / 3) * 55 + 200);
numSelection[i].setLayoutX((i % 3) * 55 + 630);
numSelection[i].setMinHeight(50);
numSelection[i].setMinWidth(50);
numSelection[i].setFont(Font.font(20));
root.getChildren().add(numSelection[i]);
numSelection[i].setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
model.setCurrentlySelectedValue(j);
}
});
}
Scene scene = new Scene(root,900,500);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
请注意,如果您只需要一个值,则有一些“捷径”方法;例如您可以使用 IntegerProperty
而不是自定义模型 class。结构和概念确实是一样的。