【问题标题】:How to notify the user of important events for a desktop application?如何通知用户桌面应用程序的重要事件?
【发布时间】:2009-03-10 09:10:02
【问题描述】:

除了 MS Office 等其他软件外,我们的客户还使用我们的软件(Java Swing 应用程序开始使用 Webstart)来完成他的工作。有时,他必须毫不拖延地在我们的软件中处理重要事件。客户希望有一个突出的通知。现在他可能正在使用 Excel,所以弹出一个消息框是不够的(尽管任务栏中的条目会闪烁)。

我们需要一些机制,例如 Outlook 通知程序,即始终可见但不会窃取焦点的弹出窗口。通知程序应一直显示,直到消息的原因消失(用户已解决问题)或用户已关闭消息(如在 Outlook 中)。此外,我们希望显示一个托盘图标并可能播放声音。

我已经尝试过 Java6 java.awt.SystemTray 以及 JDIC(版本 0.9,因为我们已经在该项目的类路径中拥有该库)等价物,但我没有找到设置超时的方法TrayIcon.displayMessage 方法,消息似乎并不总是在最前面。

除了 JNI 之外,还有其他选项可以实现所请求的行为吗?

如果 JNI 是唯一的选择,并且由于 Windows 是我们客户的唯一平台,那么 Outlook 通知程序是 Outlook 独有的功能,还是可以通过 Windows API 免费使用?

或者还有哪些其他选项可以通知用户要在一个软件中执行的重要任务,而不会妨碍他在另一个软件中完成当前任务。因此,系统模式对话框是没有选择的!

【问题讨论】:

    标签: java winapi swing usability java-native-interface


    【解决方案1】:

    尝试在您的 JFrame/JWindow 上使用 setAlwaysOnTop

    【讨论】:

    • 很好的提示。将未修饰的 JDialog 与 setAlwaysOnTop 一起使用并不能集中注意力,并且确实始终位于系统范围的顶部。结合 java.awt.SystemTray 这可能是我们需要的。
    • 我认为这将是我们要走的路,因为 Snarl 很好,但由于安装开销,它不是一个真正的选择。使用 java.awt.GraphicsEnvironment 我将尝试将窗口定位在左下角(假设用户在默认位置有任务栏)。
    【解决方案2】:

    对于 OS X,显而易见的答案是使用Growl。但是有一个小项目在 Windows 环境中提供类似的服务。它被称为Snarl。这可能会给你一个新的尝试选择。

    缺点:您必须在客户端的机器上安装一个工具。根据您的描述,我假设您在公司工作场所有一组已定义的用户,对吗?因此,尽管如此,这可能是可以接受的。

    【讨论】:

    • 是的,它是在公司工作场所定义的一组用户,我会看看这个工具。
    • Growl 和 Snarl 似乎是令人印象深刻的工具,并且似乎很容易从应用程序中使用,而无需付出太多努力,效果也很好。但是,对于我们的客户来说,需要在每台客户端电脑上安装该工具可能是不可行的。
    • Snarl4Java 是在 GPL 下发布的,因此我们没有选择。唯一的方法是我们自己使用 JNI 实现连接。
    【解决方案3】:

    Using Tray:您使用哪个组件来显示消息(JPopup、JDialog、JFrame、JWindow)?

    无论你使用哪个,尽量让它无法聚焦(覆盖isFocusable方法)并调用toFront

    也让我知道结果。

    【讨论】:

    • java.awt.TrayIcon 有一个方法 displayMessage,它会根据消息类型、标题和文本弹出一个带有图标的气泡。因此无法控制消息的显示方式。此功能被记录为依赖于平台。因此,未来的实际行为可能会发生变化。
    【解决方案4】:

    如果您有预算,请考虑使用JIDE 的许可证。 JIDE 有一个警报弹出窗口,其设计看起来与 Outlook 弹出窗口/警报小部件完全一样。

    【讨论】:

      【解决方案5】:

      这是一个例子:

      class AlertWindow extends Window implements MouseListener
      {
          AlertWindow(JFrame frame)
          {
              super(frame);
              this.setAlwaysOnTop(true);
              this.setFocusable(false);
              this.setSize(200, 200);
              this.setLocation(500, 0);
              this.setBackground(Color.BLACK);
              addMouseListener(this);
      
              try {
                  Class<?> awtUtilitiesClass = Class.forName("com.sun.awt.AWTUtilities");
                  Method mSetWindowOpacity = awtUtilitiesClass.getMethod("setWindowOpacity", Window.class, float.class);
                  mSetWindowOpacity.invoke(null, this, Float.valueOf(0.50f));
              } catch (NoSuchMethodException ex) {
                  ex.printStackTrace();
              } catch (SecurityException ex) {
                  ex.printStackTrace();
              } catch (ClassNotFoundException ex) {
                  ex.printStackTrace();
              } catch (IllegalAccessException ex) {
                  ex.printStackTrace();
              } catch (IllegalArgumentException ex) {
                  ex.printStackTrace();
              } catch (InvocationTargetException ex) {
                  ex.printStackTrace();
              }
          }
      
          public void mouseClicked(MouseEvent e)
          {
              this.setVisible(false);
          }
      
          public void mousePressed(MouseEvent e)
          {
          }
      
          public void mouseReleased(MouseEvent e)
          {
          }
      
          public void mouseEntered(MouseEvent e)
          {
          }
      
          public void mouseExited(MouseEvent e)
          {
          }
      }
      

      【讨论】:

      • 既然你对所有的异常都做同样的事情......为什么不只用 cath Exception 代替呢?还是我错过了什么?
      猜你喜欢
      • 2018-05-27
      • 2015-02-01
      • 2011-07-22
      • 1970-01-01
      • 2012-04-20
      • 2015-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多