目录
项目需求
项目实现
Part1
需求分析:
代码实现:
(1)需要键盘事件
(2)需要鼠标事件和键盘事件配合的:
(3)不需要事件配合
项目需求
首先项目之前已经实现的需求:
1.鼠标单击背景就可以在画布上产生一个圆
2.鼠标单击圆就可以选中该圆,若单击选中该圆之后不释放并进行拖动鼠标就可以移动该圆
根据已有需求之后要实现的需求:
项目实现
Part1
需求分析:
首先对需求进行分类:(需求的编号后序一直会使用)
(1)需要键盘事件的:
1.6 用户可以通过按键盘上的delete键删除所选目标器
(2)需要鼠标事件和键盘事件配合的:
1.1 背景上点击shift创建一个
1.3 用户可以通过shift单击目标,然后向左或向右拖动来调整目标的大小(只使用dX来更改大小)。(目标的最小半径为5像素)
1.5 用户可以通过点击背景来清除所有内容
注:1.5 个人认为点击背景清除所有内容与创建圆冲突 故将Ctrl+鼠标单击设为清除屏幕
(3)不需要事件配合的:
1.7 目标在圆心显示其订单号(即它们在模型中存储的顺序)
(4)之前需求已经实现的:
1.2 通过单击目标并拖动来移动目标
1.4 用户可以通过点击目标来选择一个目标(用不同的颜色绘制目标)
代码实现:
(1)需要键盘事件
实现方法:
1.创建键盘单击事件
2.在键盘单击事件中写相应的功能代码
代码模板:
键盘按下:
btn.setOnKeyPressed((e)->{
if (e.getCode().getName().equals(KeyCode.A.getName())) {
// 相应功能代码
}
});
1.6 用户可以通过按键盘上的delete键删除所选目标器
实现方法:
1.为画布对象创建键盘单击事件
2.单击事件内写删除当前所选目标圆
代码实现:
BlobView.java
public void setController(BlobController controller) {
myCanvas.setOnMousePressed(controller::handlePressed);
myCanvas.setOnMouseDragged(controller::handleDragged);
myCanvas.setOnMouseReleased(controller::handleReleased);
// 添加键盘单击事件
myCanvas.setOnKeyPressed(controller::keyHandlePressed);
}
BlobController.java
public void keyHandlePressed(KeyEvent event) { // 键盘输入
if (event.getCode() == KeyCode.DELETE){
Blob blob = iModel.getSelected();
model.deleteBlobs(iModel.getSelected());
}
}
(2)需要鼠标事件和键盘事件配合的:
实现方法:
1.创建鼠标单击事件
2.在键盘单击事件中写相应的功能代码
3.使用 鼠标事件对象event中的isXXXDown()判断相对键盘按键是否按下
4.再进行进一步的功能实现
代码模板:
// shift + 鼠标单击
btn.setOnMousePressed((e)->{
// 若shift键被按下
if (e.isShiftDown())) {
// 相应功能代码
}
});
1.1 背景上点击shift创建一个圆
1.5 用户可以通过点击背景来清除所有内容
实现方法:
1.创建鼠标释放事件(创建和删除是鼠标释放时进行的)
2.在事件函数中利用按键是否按下函数进行判断
3.按下shift时,创建圆
4.按下ctrl时,删除所有内容
代码实现:
BlobView.java
public void setController(BlobController controller) {
myCanvas.setOnMousePressed(controller::handlePressed);
myCanvas.setOnMouseDragged(controller::handleDragged);
// 添加鼠标释放事件
myCanvas.setOnMouseReleased(controller::handleReleased);
myCanvas.setOnKeyPressed(controller::keyHandlePressed);
}
BlobController.java
public void handleReleased(MouseEvent event) { // 鼠标释放
switch (currentState) {
case PREPARE_CREATE -> {
if (event.isShiftDown()){
// 创建一个⚪
Blob blob = model.addBlob(event.getX(), event.getY());
currentState = State.READY;
}else if (event.isControlDown()){
// 删除所有⚪
model.clear();
}
}
case DRAGGING -> {
// iModel.unselect();
currentState = State.READY;
}
}
}
1.3 用户可以通过shift单击目标,然后向左或向右拖动来调整目标的大小(只使用dX来更改大小)。(目标的最小半径为5像素)
实现方法:
1.创建鼠标拖动事件
2.在拖动时判断是否shift按下
3.在判断之后的代码写圆放大缩小相应的代码
4.Blob类种添加更改半径的方法
代码实现:
BlobView.java
public void setController(BlobController controller) {
myCanvas.setOnMousePressed(controller::handlePressed);
// 添加鼠标拖动事件
myCanvas.setOnMouseDragged(controller::handleDragged);
myCanvas.setOnMouseReleased(controller::handleReleased);
myCanvas.setOnKeyPressed(controller::keyHandlePressed);
}
BlobController.java
public void handleDragged(MouseEvent event) { // 鼠标拖动
switch (currentState) {
case PREPARE_CREATE -> {
currentState = State.READY;
}
case DRAGGING -> {
// 没有按下shift键
if (!event.isShiftDown()){
// 拖动被选中的⚪
dX = event.getX() - prevX;
dY = event.getY() - prevY;
prevX = event.getX();
prevY = event.getY();
double preX = iModel.getSelected().getX();
double preY = iModel.getSelected().getY();
model.moveBlob(iModel.getSelected(), dX,dY);
}else{
// 更改⚪的大小
dX = event.getX() - prevX;
Blob blob = iModel.getSelected();
double preR = blob.getR();
model.motifyR(blob,dX);
}
}
}
}
Blob.java
public void motifyR(double dX){
r += dX;
if (r < 5){
r = 5;
}else if (r > 100){
r = 100;
}
}
(3)不需要事件配合
1.7 目标在圆心显示其订单号(即它们在模型中存储的顺序)
思路:
1.在Blob类中添加count属性进行标号
2.将对圆的标号的设置与调整交给BlobModel方法
实现方法:
1.在Blob对象中添加count属性
2.在BlobModel中创建添加count属性作为计数器
3.在BlobModel中的添加,删除圆圈的方法中使用计数器对圆圈进行标号并进行调整
代码实现:
Blob.java
public class Blob {
double x,y;
double r;
int count;
public Blob() {
}
public Blob(double nx, double ny, int count) {
x = nx;
y = ny;
r = 50;
this.count = count;
}
public Blob(double x, double y, double r, int count) {
this.x = x;
this.y = y;
this.r = r;
this.count = count;
}
}
BlobModel.java
public class BlobModel {
private List<BlobModelListener> subscribers;
private List<Blob> blobs;
// 计数器
int count = 0;
public BlobModel() {
subscribers = new ArrayList<>();
blobs = new ArrayList<>();
}
public Blob addBlob(double x, double y) {
// 添加圆圈时 自动计数
count = count + 1;
Blob blob = new Blob(x, y, count);
blobs.add(blob);
notifySubscribers();
return blob;
}
public Blob addBlob(double x, double y, double r) {
count = count + 1;
Blob blob = new Blob(x, y, r, count);
blobs.add(blob);
notifySubscribers();
return blob;
}
public void moveBlob(Blob b, double dx, double dy) {
b.move(dx,dy);
notifySubscribers();
}
public void addSubscriber(BlobModelListener sub) {
subscribers.add(sub);
}
private void notifySubscribers() {
subscribers.forEach(s -> s.modelChanged());
}
public List<Blob> getBlobs() {
return blobs;
}
public boolean hitBlob(double x, double y) {
for (Blob b : blobs) {
if (b.contains(x,y)) return true;
}
return false;
}
public Blob whichHit(double x, double y) {
for (Blob b : blobs) {
if (b.contains(x,y)) return b;
}
return null;
}
public Blob deleteBlobs(Blob blob) {
// 删除圆圈时 将标号小于当前圆的标号 - 1
int count = blob.getCount();
Iterator<Blob> it = blobs.iterator();
while (it.hasNext()) {
Blob s = it.next();
if (blob.equals(s)) {
it.remove();
}
if(s.getCount() > count){
s.setCount(s.getCount() - 1);
}
}
notifySubscribers();
// 删除一个计数器 - 1
this.count -= 1;
return blob;
}
public void clear(){
// 清空list时 计数器归零
blobs.clear();
System.out.println("清空list"+blobs);
this.count = 0;
notifySubscribers();
}
public void motifyR(Blob blob, double dX){
blob.motifyR(dX);
notifySubscribers();
}
}
这是本次小项目的第一部分就完成了,后序还有后三个部分的思路和代码。