我创建了一个包含多行的网格窗格。标记应该只能在1行上移动。移动鼠标时,它应仅向左,向右或向右移动。当您单击标记时,它应该被锁定,不再移动。它应该用不同的颜色突出显示。 我怎么能得到这个? 如果您知道任何教程或示例,请添加,谢谢。
消息输出:
执行 C:\ Users \用户s22380 \桌面\ TEMP \ JavaFXApplication9 \ DIST \ run269988000 \ JavaFXApplication9.jar 使用平台C:\ Program Files \ Java \ jdk1.8.0_92 \ jre / bin / java Application构造函数中的异常 java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:498)at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389) 在 com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:498)at sun.launcher.LauncherHelper $ FXHelper.main(LauncherHelper.java:767) 引起:java.lang.RuntimeException:无法构造Application 实例:类javafxapplication9.JavaFXApplication9 at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907) 在 com.sun.javafx.application.LauncherImpl.lambda $ launchApplication $ 155(LauncherImpl.java:182) 在java.lang.Thread.run(Thread.java:745)引起: java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在 com.sun.javafx.application.LauncherImpl.lambda $ launchApplication1 $ 161(LauncherImpl.java:819) 在 com.sun.javafx.application.PlatformImpl.lambda $ runAndWait $ 175(PlatformImpl.java:326) 在 com.sun.javafx.application.PlatformImpl.lambda为$ null $ 173(PlatformImpl.java:295) 在java.security.AccessController.doPrivileged(Native Method)at com.sun.javafx.application.PlatformImpl.lambda $ runLater $ 174(PlatformImpl.java:294) 在 com.sun.glass.ui.InvokeLaterDispatcher $ Future.run(InvokeLaterDispatcher.java:95) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)at com.sun.glass.ui.win.WinApplication.lambda为$ null $ 148(WinApplication.java:191) ... 1更多引起:java.lang.NullPointerException at sample.Controller。(Controller.java:33)at javafxapplication9.JavaFXApplication9。(JavaFXApplication9.java:19) ... 13更多异常运行应用程序 javafxapplication9.JavaFXApplication9 Java结果:1正在删除 目录 C:\ Users \用户s22380 \桌面\ TEMP \ JavaFXApplication9 \ DIST \ run269988000 jfxsa-run:BUILD SUCCESSFUL(总时间:1秒)
答案 0 :(得分:0)
这个怎么样:Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application
{
Controller controller = new Controller(10,10);
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
loader.setController(this.controller);
Parent root = (Parent)loader.load();
this.controller.InitUi();
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
当您在IntelliJ中说新的JavaFX项目时,这基本上就是示例代码。我将其更改为显式设置控制器。但这只是个人偏好。
xaml
<?import javafx.scene.layout.*?>
<GridPane fx:id="mainGrid" alignment="center" gridLinesVisible="true" hgap="10" vgap="10" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
</children>
</GridPane>
再次。基本上是默认的东西。
我还添加了一个样式表来定义不可移动状态的不同锁。 redStyle.css
.button {
-fx-text-fill: #006464;
-fx-background-color: #DFB951;
-fx-border-radius: 20;
-fx-background-radius: 20;
-fx-padding: 5;
}
现在为控制器。
它会做一些事情:
按下按钮后,我会关闭样式表以获得不同的外观。现在这种风格适用于场景中的所有按钮。它可以更改为仅适用于特定的一个。
package sample;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.shape.Rectangle;
public class Controller
{
@FXML
private GridPane mainGrid;
@FXML
private Button movable;
private final int sizeX;
private final int sizeY;
private final double minMoveDistanc = 3;
private boolean canMove = true;
private Double lastX = null;
private Double lastY = null;
private String redButtonStyle = Controller.class.getResource("redStyle.css").toExternalForm();
public Controller(int sizeX, int sizeY)
{
this.sizeX = sizeX;
this.sizeY = sizeY;
}
public void InitUi()
{
if (this.mainGrid != null)
{
final int numCols = sizeX;
final int numRows = sizeY;
for (int i = 0; i < numCols; i++)
{
ColumnConstraints colConst = new ColumnConstraints();
this.mainGrid.getColumnConstraints().add(colConst);
}
for (int i = 0; i < numRows; i++)
{
RowConstraints rowConst = new RowConstraints();
this.mainGrid.getRowConstraints().add(rowConst);
}
// add rectangle to keep grid in size
for (int i = 0; i < numCols; i++)
{
for (int j = 0; j < numRows; j++)
{
Rectangle rect = new Rectangle();
rect.setWidth(50);
rect.setHeight(50);
this.mainGrid.add(rect,i,j);
}
}
// ad movable object (Button)
this.movable = new Button("Hallo");
this.movable.setPrefWidth(50);
this.movable.setPrefHeight(50);
this.movable.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent actionEvent)
{
canMove = ! canMove;
movable.setText(canMove? "move" : "stop");
if (canMove)
{
movable.getScene().getStylesheets().remove(redButtonStyle);
}
else
{
movable.getScene().getStylesheets().add(redButtonStyle);
}
}
});
this.mainGrid.add(this.movable,5,5);
}
if (this.movable != null)
{
this.movable.setOnMouseEntered(new EventHandler<MouseEvent>()
{
@Override
public void handle(MouseEvent mouseEvent)
{
lastX = null;
lastY = null;
}
});
this.movable.setOnMouseExited(new EventHandler<MouseEvent>()
{
@Override
public void handle(MouseEvent mouseEvent)
{
lastX = null;
lastY = null;
}
});
this.movable.setOnMouseMoved(new EventHandler<MouseEvent>()
{
@Override
public void handle(MouseEvent mouseEvent)
{
if (!canMove)
{ return; }
double x = mouseEvent.getSceneX();
double y = mouseEvent.getSceneY();
if (lastX == null)
{
lastX = x;
lastY = y;
return;
}
// calculate delta
double deltaX = x - lastX;
double deltaY = y - lastY;
// remember new position
lastX = x;
lastY = y;
boolean moved = false;
// x movement
if (Math.abs(deltaX) > minMoveDistanc)
{
moved = true;
int currentColumn = GridPane.getColumnIndex(movable);
if (deltaX < 0)
{
GridPane.setColumnIndex(movable, Math.max(currentColumn -1 ,0));
}
else
{
GridPane.setColumnIndex(movable, Math.min(currentColumn + 1 ,sizeX-1));
}
}
// y movement
if (Math.abs(deltaY) > minMoveDistanc)
{
moved = true;
int currentRow = GridPane.getRowIndex(movable);
if (deltaY < 0)
{
GridPane.setRowIndex(movable, Math.max(currentRow - 1 ,0));
}
else
{
GridPane.setRowIndex(movable, Math.min(currentRow + 1 ,sizeY-1));
}
}
if (moved)
{
lastX = null;
lastY = null;
}
}
});
}
}
}