InteractionDialog在对话框上的优势?

问题描述 投票:1回答:2

我曾经是recommended而不是InteractionDialog来使用Dialog,但是我没有看到优点。我看到的是一个问题。我需要的是让用户输入PIN或其他密码,然后等待他们的回答。 EDT线程(用户选择保存PIN)和其他线程(网页需要PIN进行登录)都需要这样做。

带有Dialog

  • 我可以从EDT线程调用它,并且效果很好。
  • [在不同线程上时,我可以通过被叫方中的一个内衬简单地进行调整(请参阅我的链接问题中的getFromGui

带有InteractionDialog

  • 我可以通过一些简单的wait / notifyAll魔术从其他线程轻松使用它。
  • 我无法通过EDT线程使用它,除非通过像okBtn.addActionListener(...)这样的回调,它很冗长又丑陋。

所以我很困惑,问:

  • 我从InteractionDialog中得到什么?
  • 无论我在哪个线程上,都有一种简单的方法可以统一使用它吗?
java codenameone event-dispatch-thread
2个回答
1
投票

这里有两件事:

  • 模式
  • 如何运作

对话框可以是模式对话框,也可以是非模式对话框,但它不像InteractionDialog那样具有交互性。模态对话框在内部使用InvokeAndBlock阻止EDT,因此当前线程将停止,直到对话框发出响应为止。这很方便,但存在一些极端情况。例如。启动对话框的事件可能会触发其他事件,这些事件在关闭对话框后会发生并导致异常行为。

但是那不是模态中的大事。情态有效地意味着您身后的形式“不存在”。重要的是对话框的内容,在完成之前,我们不关心后面的表格。这个核心思想意味着对话框可以有效地派生形式,因此它的行为就像显示另一个有效禁用当前形式的形式一样。在对话框后面看到的是先前表格的图形,而不是实际的表格。

文本字段可能会引起问题。因为对话框的放置方式(使用边距将其有效地填充到其窗体内的适当位置),所以当虚拟键盘抬起时,UI不能按照文本字段的要求滚动。由于人们在这种情况下使用对话框,因此我们尝试解决大多数这些问题,但有时很难,例如如果对话框顶部有很多空白,则将虚拟键盘打开并覆盖它。或者,如果用户旋转屏幕,此时对话框的边距将无效。

请注意,在InteractionDialog中,某些问题(例如定位余量)也适用。

现在InteractionDialog是完全不同的野兽,它源于完全不同的用例。如果我们想要一个对话框,例如“浮动在ui顶部的调色板,该怎么办?

我们可以将其从一个位置移动到另一个位置,但仍与基础表单交互。这是InteractionDialog的核心用例。由于这种模态不再是我们所需要的,因此尽管从技术上来说本来可以做到的,但它从未被纳入InteractionDialog中(但对于核心用例而言这没有意义)。

它被实现为Container,放置在当前表单的分层窗格中,因此其周围的表单是真实的。因为表单是“实时”的,所以布局效果更好,而删除模态会使与编辑有关的一些边缘情况变得更好。但是,对话框的定位和旋转仍然存在一些固有的问题。它还允许您在进行输入时在对话框外单击,这对于您的用例而言可能是理想的/不良的效果。

总体上,我仅尝试在非常简单的情况下使用对话框,并尽可能避免输入。如果我使用输入,则永远不会使用多个字段(例如,无用户名和密码字段),因此无需滚动。这些事情也对本机UI不利,例如虚拟键盘遮盖了提交按钮等。由于这些行为很难在所有分辨率/虚拟键盘方案中正确实现。


0
投票

根据Shai的回答,我编写了一个表单,用作大多数对话框的基类。基本上,它显示了子类的内容,并添加了“确定”和“取消”按钮。

有一种可以在EDT线程中使用的方法,例如

public void showAndThen(BooleanConsumer consumer) {
    assert CN.isEdt();

    ...
    okBtn.addActionListener(a -> {
        lastForm.show();
        consumer.accept(true);
    });
    cancelBtn.addActionListener(a -> {
        lastForm.showBack();
        consumer.accept(false);
    });
}

其中BooleanConsumer是简单的void accept(boolean b)接口。

还有其他线程可以使用的另一种方法

@Override public final boolean ask() {
    assert !CN.isEdt();
    final BooleanTransfer transfer = new BooleanTransfer();
    CN.callSerially(() -> showAndThen(result -> transfer.set(result)));
    return transfer.await();
}

其中BooleanTransfer是两类类,其中调用set的线程将boolean传递给调用await的线程。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.