javafx - JavaFX Spinner 在警报后继续旋转
问题描述
我有一个关于 JavaFX 微调器(javafx.scene.control.Spinner)的有趣问题......
对于我的 Spinner,我想在用户第一次单击递增或递减按钮时显示“警告”警报。问题是警报显示得很好,但是一旦显示,微调器就会继续自行递增/递减。它继续永远“旋转”。
这是我使用以下抽象类实现微调器的方式...
public abstract class TimeSpinner extends Spinner<LocalTime> {
protected abstract void displayPopUpOrNot();
@Override
public void decrement(int steps) {
displayPopUpOrNot();
try {
getValueFactory().setValue(LocalTime.parse(getEditor().getText(), DateTimeFormatter.ofPattern(UtilitiesBean.FORMAT_TIMEONLY_12HR, Locale.ENGLISH)));
super.decrement(steps);
}
catch (DateTimeParseException e) {
getEditor().setText(UtilitiesBean.INSTANCE.formatLocalTime(LocalTime.now(), UtilitiesBean.FORMAT_TIMEONLY_12HR));
getValueFactory().setValue(LocalTime.now());
}
}
@Override
public void increment(int steps) {
displayPopUpOrNot();
try {
getValueFactory().setValue(LocalTime.parse(getEditor().getText(), DateTimeFormatter.ofPattern(UtilitiesBean.FORMAT_TIMEONLY_12HR, Locale.ENGLISH)));
super.increment(steps);
}
catch (DateTimeParseException e) {
getEditor().setText(UtilitiesBean.INSTANCE.formatLocalTime(LocalTime.now(), UtilitiesBean.FORMAT_TIMEONLY_12HR));
getValueFactory().setValue(LocalTime.now());
}
}
}
...然后由我的具体微调器类扩展,就像这样...
public class Spinner1 extends TimeSpinner {
private boolean warningDisplayed = false;
protected void displayPopUpOrNot() {
if (!warningDisplayed) {
warningDisplayed = true;
Alert alert = new Alert(AlertType.WARNING, SPINNER_1_MESSAGE);
alert.setHeaderText(null);
alert.showAndWait();
}
}
}
“displayPopUpOrNot”方法包含显示警报的代码。它仅在用户第一次单击递增或递减微调器按钮时执行,因为之后它会设置 warningDisplayed 标志以防止进一步执行。
我的微调器初始化代码包括以下...
timeSpinner.setValueFactory(new TimeSpinnerValueFactory());
...而我的 TimeSpinnerValueFactory 定义如下...
public class TimeSpinnerValueFactory extends SpinnerValueFactory<LocalTime> {
{
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(UtilitiesBean.FORMAT_TIMEONLY_12HR, Locale.ENGLISH);
setConverter(new LocalTimeStringConverter(formatter, null));
}
@Override
public void decrement(int steps) {
if (getValue() == null)
setValue(LocalTime.now());
else {
try {
LocalTime time = getValue();
setValue(time.minusMinutes(steps));
}
catch (DateTimeParseException e) {
setValue(LocalTime.now());
}
}
}
@Override
public void increment(int steps) {
if (this.getValue() == null)
setValue(LocalTime.now());
else {
try {
LocalTime time = getValue();
setValue(time.plusMinutes(steps));
}
catch (DateTimeParseException e) {
setValue(LocalTime.now());
}
}
}
}
如果我在这篇文章中包含了比必要更多的代码,我深表歉意。
有谁知道为什么显示警报后微调器继续旋转以及如何防止这种情况?如果需要更多信息,请告诉我。
感谢您的任何建议!
2021-01-20 更新:我已将微调器简化为整数微调器。此外,根据下面麦迪逊的建议(感谢麦迪逊!),我尝试将微调器逻辑放入警报的结果函数中。
这样做时,我发现问题似乎是当显示警报时,逻辑的行为就像用户按住递增/递减按钮一样。对递增/递减函数的调用将永远继续。
如果有帮助,这是我的(希望是最小的)微调器逻辑,它应该显示这种行为......
public class IntegerSpinner extends Spinner<Integer> {
private boolean popupDisplayed = false;
private boolean popupClosed = false;
@Override
public void decrement(int steps) {
System.out.print("Decrement method called. ");
displayPopUpOrNot(false, steps);
}
@Override
public void increment(int steps) {
System.out.print("Increment method called. ");
displayPopUpOrNot(true, steps);
}
private void incrementDecrement(boolean increment, int steps) {
System.out.print("Popup is now closed. ");
if (increment) {
super.increment(steps);
System.out.println("Increment operation executed.");
}
else {
super.decrement(steps);
System.out.println("Decrement operation executed");
}
}
protected void displayPopUpOrNot(boolean increment, int steps) {
if (!popupDisplayed) {
System.out.println("Popup is being prepared for display.");
popupDisplayed = true;
Alert alert = new Alert(AlertType.WARNING, "My spinner message");
alert.setHeaderText(null);
Optional<ButtonType> option = alert.showAndWait();
if (option.get() == ButtonType.OK) {
popupClosed = true;
incrementDecrement(increment, steps);
}
}
else if (popupClosed) {
incrementDecrement(increment, steps);
}
else {
System.out.println("Popup is open. Increment/decrement operation skipped.");
}
}
}
我创建微调器的代码包括以下内容...
IntegerSpinner integerSpinner = new IntegerSpinner();
integerSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 600, 300));
所以这是我对这个问题的后续问题 - 有没有办法“以编程方式”关闭 Spinner 的鼠标点击?同样,逻辑表现得好像鼠标在 Spinner 上被按住,我想以某种方式将其关闭。当然,我愿意接受有关如何解决此问题的任何其他建议。
我希望我的问题是有道理的。再次感谢到目前为止所有回复的人!
解决方案
我设法找到了这个问题的解决方案,我希望分享它,以防其他人遇到这个问题。
事实证明,当响应单击微调器上的递增或递减按钮而显示警报时,处理的是鼠标单击事件,而不是鼠标释放事件。这意味着,事实上,就所涉及的逻辑而言,在显示警报时,鼠标正按住递增/递减按钮。
为了防止由此产生的无休止的旋转,必须跳过递增/递减逻辑,直到警报关闭并再次单击鼠标递增或递减按钮。
为此,可以将鼠标处理程序添加到微调器,其中包括以下代码...
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton() == MouseButton.PRIMARY) {
if (integerSpinner.isPopupClosed()) {
integerSpinner.setMouseClickedPostPopup(true);
}
}
}
...并且微调器中的 displayPopUpOrNot 方法可以修改如下...
protected void displayPopUpOrNot(boolean increment, int steps) {
if (!popupDisplayed) {
popupDisplayed = true;
Alert alert = new Alert(AlertType.WARNING, "My spinner message");
alert.setHeaderText(null);
Optional<ButtonType> option = alert.showAndWait();
if (option.get() == ButtonType.OK) {
popupClosed = true;
}
}
else if (popupClosed && mouseClickedPostPopup) {
incrementDecrement(increment, steps);
}
}
我已经在我的原始应用程序中实现了这个逻辑,现在一切正常。再次感谢之前的建议。
推荐阅读
- azure - Azure 数据工厂到 Azure Blob 存储权限
- c# - 表单发布请求完成后,如何在使用.netcore的剃须刀网络应用程序中从页面后面的代码关闭网络浏览器窗口
- sparql - 即使在 wiki 数据 sparql 查询中不提供该人的性别,也可以获取一个值
- angular - Angular 10 - 什么是错误:R3InjectorError(AppModule)[Window -> Window -> Window]
- react-native - axios调用后如何获取更新的包装器
- html - 过度选择和选项时如何将光标设置为指针?
- azure - 天蓝色数据工厂管道执行中的 403/307 错误
- python - 如何让我的 sphinx 指令将资产添加到 _static 文件夹?
- odoo - 是否可以在 odoo.fields.HTML 中使用 Javascript?
- python - Python 套接字服务器脚本