我必须在哪里初始化类成员变量JavaFX
我正在通过Java中的scene builder使用JavaFX和JFoenix制作一个应用程序,但是我在初始化类成员变量时遇到了一些问题。这是我的密码我必须在哪里初始化类成员变量JavaFX,java,javafx,scenebuilder,Java,Javafx,Scenebuilder,我正在通过Java中的scene builder使用JavaFX和JFoenix制作一个应用程序,但是我在初始化类成员变量时遇到了一些问题。这是我的密码 public class MessageApp extends Application { private AnchorPane mainLayout; private Stage primaryStage; private int i = 5; public void init() { i
public class MessageApp extends Application {
private AnchorPane mainLayout;
private Stage primaryStage;
private int i = 5;
public void init() {
i = 0;
}
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(PeerApp.class.getResource("PeerApp.fxml"));
mainLayout = loader.load();
} catch (IOException e) {
e.printStackTrace();
}
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Test");
JFXDecorator decorator = new JFXDecorator(primaryStage, mainLayout);
decorator.setCustomMaximize(true);
Scene scene = new Scene(decorator, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
@FXML
private void clickSendMessage() {
System.out.println("i = " + i);
}
public static void main(String[] args) {
launch(args);
}
}
这里的问题是,当我单击触发clickSendMessage
功能的发送按钮时,即使我在init
功能或start
功能中将I重置为0,我的println
打印“I=5”。重置它的唯一方法是将i=0放入clickSendMessage函数本身
因此,在这种情况下,这不是一个大问题,但是如果我在声明过程中没有初始化类成员变量,即使我在init
或start
函数中初始化它,当我单击我的发送按钮时,我的应用程序崩溃,因为在这个阶段它仍然被视为null,但我不知道为什么
有什么线索吗?我必须在哪里初始化我的类成员变量
编辑:
好的,我试着为我的视图创建一个专用的控制器,我的第一个问题似乎已经解决了,一切都按照预期进行了初始化,但是现在我的列表视图
没有在每次我向列表中添加联系人
时更新,但以前是这样。我不知道我通过创建一个独立的控制器打破了什么,知道吗
这是完整的代码
PeerApp.java
public class PeerApp extends Application {
private AnchorPane mainLayout;
private Stage primaryStage;
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(PeerApp.class.getResource("PeerApp.fxml"));
mainLayout = loader.load();
} catch (IOException e) {
e.printStackTrace();
}
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Peer Messenger");
JFXDecorator decorator = new JFXDecorator(primaryStage, mainLayout);
decorator.setCustomMaximize(true);
Scene scene = new Scene(decorator, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
PeerAppController.java
public class PeerAppController {
private PeerApplication peer = new PeerApplication("1234");
private ObservableList<Contact> contacts;
private ChangeListener<Contact> listener;
private int i = 5;
@FXML
private JFXListView<Contact> contactList;
@FXML
private JFXButton addContactButton;
@FXML
private JFXTextArea messageTextArea;
@FXML
private GridPane chatGridPane;
@FXML
private JFXButton sendButton;
@FXML
public void initialize() {
initPeer();
initRootLayout();
contacts = FXCollections.observableArrayList(Contact.extractor());
contactList.setItems(contacts);
listener = new ChangeListener<Contact>() {
@Override
public void changed(ObservableValue<? extends Contact> observable, Contact oldValue, Contact newValue) {
chatGridPane.getChildren().clear();
List<Message> conversation = contacts.get(contactList.getSelectionModel().getSelectedIndex()).getConversation();
int i;
i = 0;
while (conversation.size() >= i + 1) {
Label messageLabel = new Label(conversation.get(i).getContent());
chatGridPane.addRow(i, messageLabel);
i++;
}
}
};
contactList.getSelectionModel().selectedItemProperty().addListener(listener);
i = 0;
}
private void initPeer() {
peer.init(EncryptionType.NONE, CompressionType.NONE);
peer.getPeerDaemonPlug().setComListener(new ICommunicationListener() {
@Override
public void onDataReceived(String s) {
Label labelMessage = new Label(s);
GridPane.setHalignment(labelMessage, HPos.RIGHT);
chatGridPane.addRow(getRowCount(chatGridPane) + 1, labelMessage);
contacts.get(contactList.getSelectionModel().getSelectedIndex()).getConversation().add(new Message(s, false));
}
@Override
public void onStreamPacketCompleted(OutputStream outputStream) {
}
});
}
private void initRootLayout() {
// Init the layout
ColumnConstraints c1 = new ColumnConstraints();
c1.setPercentWidth(100);
sendButton = new JFXButton();
contactList = new JFXListView<Contact>();
chatGridPane = new GridPane();
chatGridPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
chatGridPane.getColumnConstraints().add(c1);
}
@FXML
private void clickAddContact() {
TextInputDialog dialog = new TextInputDialog("");
dialog.setTitle("New Contact");
dialog.setHeaderText("Add a new contact");
dialog.setContentText("Enter the ID of your contact:");
Optional<String> result = dialog.showAndWait();
result.ifPresent(id -> {
Contact c = new Contact(id);
contacts.add(c);
System.out.println(contactList.getItems().size());
});
}
@FXML
private void clickSendMessage() {
// Not to be there
String message = messageTextArea.getText();
Label labelMessage = new Label(message);
try {
peer.sendRequest(sendDataToNode, new SendDataToNodeParam(contactList.getSelectionModel().getSelectedItem().toString(), message));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
i = 0;
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
i = 1;
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
i = 2;
e.printStackTrace();
} catch (InvalidKeyException e) {
i = 3;
e.printStackTrace();
} catch (BadPaddingException e) {
i = 4;
e.printStackTrace();
} catch (IOException e) {
i = 5;
e.printStackTrace();
}
messageTextArea.setText("");
GridPane.setHalignment(labelMessage, HPos.LEFT);
chatGridPane.addRow(getRowCount(chatGridPane) + 1, labelMessage);
contacts.get(contactList.getSelectionModel().getSelectedIndex()).getConversation().add(new Message(message, true));
System.out.println("i = " + i);
}
private int getRowCount(GridPane pane) {
int numRows = pane.getRowConstraints().size();
for (int i = 0; i < pane.getChildren().size(); i++) {
Node child = pane.getChildren().get(i);
if (child.isManaged()) {
Integer rowIndex = GridPane.getRowIndex(child);
if(rowIndex != null){
numRows = Math.max(numRows,rowIndex+1);
}
}
}
return numRows;
}
}
公共类PeerAppController{
私有PeerApplication对等方=新PeerApplication(“1234”);
私人关系;
私人监听;
私人int i=5;
@FXML
私有JFXListView联系人列表;
@FXML
专用JFXButton addContactButton;
@FXML
私有JFXTextArea messageTextArea;
@FXML
私有网格窗格聊天网格窗格;
@FXML
私有JFXButton sendButton;
@FXML
公共无效初始化(){
initPeer();
initRootLayout();
contacts=FXCollections.observearraylist(Contact.extractor());
联系人列表。设置项目(联系人);
listener=新的ChangeListener(){
@凌驾
public void已更改(observeValue我的朋友,你是否也将PeerApp.fxml的控制器设置为MessageApp
否则,当您单击“发送”按钮时,它不会触发clickSendMessage()
但如果您将PeerApp.fxml的控制器设置为MessageApp,javafx会自动创建MessageApp的另一个实例,因此如果您单击“发送”按钮,它实际上会触发MessageApp的clickSendMessage()的另一个实例,并打印其i变量
或者您可以发布您的PeerApp.fxml代码以方便我们检查
init()方法是从应用程序类重写的,它将在我们启动javafx应用程序时自动运行。我的朋友,您是否也将PeerApp.fxml的控制器设置为MessageApp
否则,当您单击“发送”按钮时,它不会触发clickSendMessage()
但如果您将PeerApp.fxml的控制器设置为MessageApp,javafx会自动创建MessageApp的另一个实例,因此如果您单击“发送”按钮,它实际上会触发MessageApp的clickSendMessage()的另一个实例,并打印其i变量
或者您可以发布您的PeerApp.fxml代码以方便我们检查
init()方法是从应用程序类重写的,它将在我们启动javafx应用程序时自动运行。在我看来,将负责启动应用程序并加载.fxml
文件的类混合在一起是不好的做法对于作为您的控制器的类
,它关心控制您的UI,例如,在您的示例中,您有clickSendMessage()
方法,该方法必须在控制器类中
因此,我建议您编写一个单独的类作为控制器,将控制器附加到.fxml
文件,然后您可以更轻松地处理UI和逻辑部分之间的所有交互。我可以向您展示一个简单的示例:
package stackoverflow;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
public class TestController implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {
// here are all stuffs initialized
}
}
然后.fxml
文件如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="500.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/8.0.91" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="stackoverflow.TestController">
// here you can fill it with content
</AnchorPane>
//在这里,您可以用内容填充它
现在你有了一个单独的控制器和一个.fxml
,你可以像在主类中那样加载这个.fxml
,然后你可以在你的控制器中添加所有你想要控制你的应用程序的东西,包括这个方法。这是一个构建javafx应用程序的简单而清晰的方法。
我认为这是可以理解的,但如果我错过了什么,请随时问我。在我看来,混合负责启动应用程序并加载.fxml
文件的类是一种不好的做法对于作为您的控制器的类
,它关心控制您的UI,例如,在您的示例中,您有clickSendMessage()
方法,该方法必须在控制器类中
因此,我建议您编写一个单独的类作为控制器,将控制器附加到.fxml
文件,然后您可以更轻松地处理UI和逻辑部分之间的所有交互。我可以向您展示一个简单的示例:
package stackoverflow;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
public class TestController implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {
// here are all stuffs initialized
}
}
然后.fxml
文件如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="500.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/8.0.91" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="stackoverflow.TestController">
// here you can fill it with content
</AnchorPane>
//在这里,您可以用内容填充它
现在你有了一个单独的控制器和一个.fxml
,你可以像在主类中那样加载这个.fxml
,然后你可以在你的控制器中添加所有你想要控制你的应用程序的东西,包括这个方法。这是一个构建javafx应用程序的简单而清晰的方法。
我认为这是可以理解的,但如果我错过了什么,请随时问我。如果你不初始化变量,它们有一个默认值。对于任何对象s,它是null
,对于int
它是0。并且你从不调用init()
那么为什么假设i为0?我如何在声明时直接初始化尽可能多的字段。如果您希望i
为0,则将其声明为private int i=0<