- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
它来了它来了,最后一期终于来了。理论上该讲的全都讲完了,只剩下那个拖了好几期的自定义控件和一个比较没有存在感的设置功能没有讲。所以这次就重点介绍它们俩吧.
首先我们快速浏览下设置的实现,上图:
然后是控制器代码:
package controllers;
import components.GameEnum;
import javafx.animation.FadeTransition;
import javafx.animation.RotateTransition;
import javafx.animation.SequentialTransition;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.util.Duration;
import static components.Constant.*;
/**
* @description: 设置界面控制逻辑
* @author: 郭小柒w
* @time: 2023/6/15
*/
public class SettingsController {
@FXML // 单选按钮, 难度
private RadioButton easy, medium, hard, custom;
@FXML // 文本框组, 自定义游戏数据
private TextField numWidth, numHeight, numBomb;
@FXML // 保存按钮
private Button save;
@FXML // 辅助效果图
private ImageView loading;
// 单选按钮组
private ToggleGroup degree;
public void initialize() {
// 文本框默认不可编辑
numWidth.setEditable(false);
numHeight.setEditable(false);
numBomb.setEditable(false);
// 首先尝试使用已保存设置
switch (GAME) {
case MEDIUM:
medium.setSelected(true);
break;
case HARD:
hard.setSelected(true);
break;
case CUSTOM:
custom.setSelected(true);
numWidth.setEditable(true);
numHeight.setEditable(true);
numBomb.setEditable(true);
numWidth.setText(GAME.width + "");
numHeight.setText(GAME.height + "");
numBomb.setText(GAME.bomb + "");
break;
default:
easy.setSelected(true);
break;
}
// 单选按钮分组
degree = new ToggleGroup();
easy.setToggleGroup(degree);
medium.setToggleGroup(degree);
hard.setToggleGroup(degree);
custom.setToggleGroup(degree);
// 难度按钮选中事件
degree.selectedToggleProperty().addListener(((observable, oldValue, newValue) -> {
String id = ((RadioButton) newValue).getId();
// 只有选中自定义难度情况下可编辑文本框, 默认不可编辑
if (id.equals("custom")) {
GAME = GameEnum.CUSTOM;
numWidth.setEditable(true);
numHeight.setEditable(true);
numBomb.setEditable(true);
} else {
// 清空文本框并设置为不可编辑
numWidth.setText(null);
numHeight.setText(null);
numBomb.setText(null);
numWidth.setEditable(false);
numHeight.setEditable(false);
numBomb.setEditable(false);
if (id.equals("easy")) {
GAME = GameEnum.EASY;
} else if (id.equals("medium")) {
GAME = GameEnum.MEDIUM;
} else {
GAME = GameEnum.HARD;
}
}
}));
// 保存按钮点击事件
save.setOnMouseClicked(event -> {
try {
// 如果是自定义难度, 保存输入的值
if (GAME == GameEnum.CUSTOM) {
try {
// 保存自定义输入
GAME.setWidth(Integer.parseInt(numWidth.getText()));
GAME.setHeight(Integer.parseInt(numHeight.getText()));
GAME.setBomb(Integer.parseInt(numBomb.getText()));
} catch (NumberFormatException e) {
// 输入问题导致的转换失败, 按简单设置处理
GAME.setWidth(9);
GAME.setHeight(9);
GAME.setBomb(10);
}
}
// 设置用于动画效果的图片
loading.setImage(new Image(LOAD_IMG));
loading.setVisible(true);
// 点击保存时的动画效果,分两步, 1:旋转缓冲 2:图片淡出
RotateTransition transition1 = new RotateTransition(Duration.seconds(1), loading);
// 旋转角度
transition1.setByAngle(360);
transition1.setOnFinished(event1 -> {
loading.setImage(new Image(SAVE_IMG));
});
FadeTransition transition2 = new FadeTransition(Duration.seconds(1), loading);
// 不透明度变化
transition2.setFromValue(1);
transition2.setToValue(0);
SequentialTransition sequence = new SequentialTransition(transition1, transition2);
// 播放动画
sequence.play();
} catch (Exception e) {
System.out.println("Error on [Class:SettingsController, Method:initialize, Event: save]=>");
e.printStackTrace();
}
});
}
}
和上期排行版难度按钮类似,都是单选按钮分组然后设置对应点击事件。不同的是不像排行版切换那样直观,这里需要一个提示来让玩家清楚保存是生效了的,所以我设置了保存按钮和对应的动画提示。下面介绍自定义控件的实现( 设置真的没有存在感,哈哈哈 ).
LedNumber ,这个东西可是费了我老半天劲。我的思路是既然想在界面上显示,他要么是布局要么是控件,经过尝试后发现还是控件合理。所以这个自定义类要继承 Control 类,然后按照要求实现 createDefaultSkin 方法。到这里我就不会了,它要求的返回值类型为 Skin<?> ,这是啥,没见过啊。求助万能的GPT后大概明白了它的要求( 我理解的不一定准确 )——控件显示是需要有Skin的,没有的话就类似无内容的Label,不设置背景色在界面上看起来就跟没有一样。所以我按GPT的提示创建了对应的skin类 LedNumberSkin ,并在里面进行外观设计.
设计思路受这篇文章启发: https://blog.csdn.net/hx0_0_8/article/details/8012448 。
其思想就是将数字看作由以下七个线段组合而成,不同数字使用不同的线段:
只是这样看起来还不够美观,所以可以对这些线段的拼接处进行处理,比如下面这种形式( 绘制的有些简陋,代码中是可以控制连接处贴合的,适当留白更立体 ):
那么代码中是如何实现的呢?对于每一条边,可以使用多边形Polygon类实现,只需要依次写入它的坐标即可( 必须是顺时针或者逆时针,起始点位置不做要求 ),如下:
/**
* 计算自定义多边形各顶点坐标
*
* @param toward 多边形朝向 [01234: 右下左上中]
* @param x 起始点横坐标
* @param y 起始点纵坐标
* @return 坐标数组
*/
public ArrayList<Double> getPoints(int toward, double x, double y) {
ArrayList<Double> points = new ArrayList();
// 添加起始点坐标
points.add(x);
points.add(y);
// 按顺时针方向依次添加其余坐标
switch (toward) {
case 0:
points.add(x + height);
points.add(y + height);
points.add(x + height);
points.add(y + height + lenShort);
points.add(x);
points.add(y + lenLong);
break;
case 1:
points.add(x + lenLong);
points.add(y);
points.add(x + height + lenShort);
points.add(y + height);
points.add(x + height);
points.add(y + height);
break;
case 2:
points.add(x + height);
points.add(y - height);
points.add(x + height);
points.add(y + height + lenShort);
points.add(x);
points.add(y + lenShort);
break;
case 3:
points.add(x + lenShort);
points.add(y);
points.add(x + height + lenShort);
points.add(y + height);
points.add(x - height);
points.add(y + height);
break;
case 4:
points.add(x + height);
points.add(y - height + 2);
points.add(x + height + lenShort);
points.add(y - height + 2);
points.add(x + lenLong);
points.add(y);
points.add(x + height + lenShort);
points.add(y + height - 2);
points.add(x + height);
points.add(y + height - 2);
break;
}
return points;
}
有了绘制方法,接下来就是具体数字需要的初始化方法:
/**
* 构建点阵数字需要的边
*/
public void init() {
// 初始化
for (int i = 0; i < 7; ++i) {
polygons[i] = new Polygon();
}
// 计算出各多边形的顶点坐标
polygons[0].getPoints().addAll(getPoints(0, 1, 1));
polygons[1].getPoints().addAll(getPoints(1, 2, 0));
polygons[2].getPoints().addAll(getPoints(2, height + lenShort + 3, height + 1));
polygons[3].getPoints().addAll(getPoints(2, height + lenShort + 3, height + lenLong + 3));
polygons[4].getPoints().addAll(getPoints(3, height + 2, lenLong * 2 - 1));
polygons[5].getPoints().addAll(getPoints(0, 1, lenLong + 3));
polygons[6].getPoints().addAll(getPoints(4, 2, lenLong + 2));
// 根据edges数组判断每条边待设置的颜色
for (int i = 0; i < 7; ++i) {
if(edges[index][i]) {
polygons[i].setFill(Color.web("#FF0000"));
} else {
polygons[i].setFill(Color.web("#680404"));
}
pane.getChildren().add(polygons[i]);
}
getChildren().add(pane);
}
注: edges为二维boolean数组,控制每条边的颜色显示 [true:亮红色, false:暗红色] 。
这样就有了每个数字对应的外观,由于我使用的jdk版本较早,所以不支持 LedNumber 类运行中修改 Skin ,所以采用以下方式实现数字显示切换:
/**
* 切换数字显示
* @param index 要转化成的数字
*/
public void switchSkin(int index) {
// 清空当前控件的子节点, 重新添加
getChildren().clear();
LedNumber newLedNumber = new LedNumber(index);
getChildren().add(newLedNumber);
}
这样就完成了LED数字的显示,感觉这个想法还是很不错的。而且在这个基础上你甚至还可以自己实现电子万年历之类的程序,有兴趣的伙伴可以尝试下。到此本次扫雷项目已经介绍差不多了,如果您还有疑问欢迎在评论区留言,有缘明年再见( 开鸽! ) 。
——————————————我———是———分———割———线————————————— 。
稀里糊涂地讲完啦,不知道大家能理解多少😟。过一阵子应该会去上海吧,找朋友聚聚,散散心开启新生活,如正文结尾所说,我们有缘的话明年博客园再会啦,886✈️! 。
最后此篇关于基于JavaFX的扫雷游戏实现(五)——设置和自定义控件的文章就讲到这里了,如果你想了解更多关于基于JavaFX的扫雷游戏实现(五)——设置和自定义控件的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我想实现自定义搜索,但遇到了一个麻烦。我需要将 UIButton、SearchBar 组合在一个控件中,以便我可以通过指针引用它。然后我将向该组合控件动态添加更多 UIbutton。最重要的是,我想将
它没有在我的方法中执行 if block 中的语句 母版页:- 页面加载事件:- Control c = new Control(); DoSomething(c); 我的方法:- protecte
ComboBox 控件有一个 setConverter 方法,请参阅 JavaFX ComboBox - Display text but return ID on selection举个例子。我正在
我没有找到任何包含用于标记化(标记)文本输入的控件的 wpf 库。也许我找不到库,因为我错误地调用了这个组件。怎么叫或者哪里有这样的库? 最佳答案 DevExpress WPF 库包含多个数据编辑控件
是否有 Silverlight 控件允许您输入文本并将其突出显示为代码? 例如: foreach (client in Clients){ client.Save();} would become
我有以下用户控件 a) Panel.ZIndex="99999999" 是否是将此控件设置为该控件中 TopMost 的正
是否可以在 Windows 窗体中使用 C# 在窗体加载时隐藏所有特定控件,例如标签或按钮,然后选择显示我不想显示的那些? 我有一个包含很多按钮和标签的程序,但我只想在加载时显示一两个,我觉得对每个标
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: Duplicating components at Run-Time 我有一个TMyControl ( Contro
我正在尝试在 Delphi 中编写一个 dll 库,其中包含一个创建 TFrame 后代实例并返回它的函数。但是当我在应用程序中导入这个函数时,每次调用它时,我都会得到一个异常,例如“'xxx'控件没
是否有 Win32 API 调用来确定哪些窗口和/或控件在特定坐标和/或鼠标下可见? 最佳答案 您可以使用GetWindowFromPoint 。它将返回窗口句柄,以便您可以使用 GetClassNa
我需要在编辑控件中输入以下公式: 公式是在 MS Word 中制作的。尝试将其复制/粘贴到编辑控件(单行或多行)后,我得到 M 0.33 Q10T9.1-9.7。 当我输入这个时,我正在研究 Rich
我只是想成功地将它添加到我的窗口中,但这却出奇地困难。 我已经尝试过 #include "windef.h" #include "winbase.h" #include "initguid.h" #i
我希望能够使用 google maps api v3 拥有自己的“街景”按钮。单击按钮时,我希望它根据我的标记经纬度加载街景。然后我希望按钮更改为“返回 map ”,然后再次加载默认 map View
我目前正在用 PHP 开发(另一个)开源 CMS,我想使用 javascript 控件,尤其是管理面板。问题是,是否有任何具有 PHP 接口(interface)的开源、可自由分发的控件(用于创建 j
我为其编写软件的产品之一是会计类应用程序。它用 C++ 编写,使用 C++ Builder 和 VCL 控件,连接到运行在 Linux 上的 PostgreSQL 数据库。 PostgreSQL 数据
我使用 Key Listener 来读取用户的输入,但我遇到了问题。首先,我读到 JTextField“请输入您的姓名”。如果用户输入一个名字,例如 John,它将更改为 John。但是,如果用户输入
我正在尝试对齐数据表列中的复选框(h=center,v=middle) ... 但复选框仍然显示在错误的位置(见附图)
我有一个包含统计信息的 JSON 数据树: { prefix: "a", count: 20, children: [ { prefix: "a:b", c
我在 Photoshop 中设计了一个模型,我打算将它应用到我的产品目录的 ListView 控件中,但它似乎没有正确显示(未对齐?),我希望这里的人可以像我一样指出我的错误试图弄清楚无济于事。 预期
您是使用 ASP.NET 控件还是仅使用带有 CSS 的 HTML? 我在 TextBox 和 DropDownList 的宽度方面遇到了一些问题。在不同的浏览器中,宽度会有所不同,控件的大小也不会相
我是一名优秀的程序员,十分优秀!