【问题标题】:Is there any way to return from JFileChooser.showOpenDialog() programmatically?有没有办法以编程方式从 JFileChooser.showOpenDialog() 返回?
【发布时间】:2016-02-06 18:57:23
【问题描述】:

这里的上下文是单元测试:在测试结束时,在tearDown,如果JFileChooser 被“挂起”(即显示),我想强制它以“取消”返回价值。

问题是,否则,我调用showOpenDialog(一种阻塞方法)的actionPerformed() 继续存在......我需要关闭那个Runnable

注意 Runnable 运行 actionPerformed 当然是在 EDT 中运行。但是尽管如此,该框架还是能够启动另一个“事件泵”:我的理解是,当您在 EDT 中执行 JFileChooser.showOpenDialog 时,这是非常正常和正确的行为:类似于调用 JOptionPane.showXXX 静态方法之一在美国东部时间。

我还想避免“测试人为”的解决方案:换句话说,应用程序代码必须足以满足自身需求,并且不使用曲折或不自然的机制,因为它知道它将通过测试运行需要为其提供“句柄”的代码。

PS 我实际上使用的是 Jython,而不是 Java,而且我使用的是 Python unittest 模块,而不是基于 Java 的单元测试框架。但这并没有改变所涉及的原则......

PPS (稍后) 我设计了一种我认为相当“不稳定”的方法:这涉及深入挖掘JFileChooser 以识别JButton getText() == "取消"。抱歉,它是用 Jython 编写的,但即使是不懂 Python 的人也应该很容易掌握:

def close_main_frame():
    self.main_frame.dispose()
    self.cancel_button = None
    def explore_descendant_comps( container, method, breadth_first = False, depth = 0 ):
        for component in container.components:
            if isinstance( component, java.awt.Container ):
                if breadth_first:
                    method( component, depth )
                explore_descendant_comps( component, method, breadth_first, depth + 1 )
                if not breadth_first:
                    method( component, depth )
    def identify_cancel_button( comp, depth ):
        if isinstance( comp, javax.swing.JButton ) and comp.text == 'Cancel': 
            self.cancel_button = comp
    explore_descendant_comps( self.main_frame.analysis_file_chooser, identify_cancel_button )
    if self.cancel_button:
        self.cancel_button.doClick()
    else:
        raise Exception()

self.edt_despatcher.run_in_edt( close_main_frame, False ) 

这是“不稳定的”,尤其是因为按钮的“取消”文本可能会被另一种语言的其他名称替换...

【问题讨论】:

  • 其实选择器上有一个cancelSelection()方法。如果你有组件,你不能直接调用吗?可能你需要在调用它之前检查组件上的 instanceOf JFileChooser。
  • 是的...看我的第二条评论...谢谢!
  • 对于涉及 UI 的测试,您需要 FEST code.google.com/archive/p/fest 之类的东西。
  • @Michal 感谢您的链接:有趣。问题是,我使用的是 Jython 和 Python unittest 模块,而不是 Java 单元测试框架。当您在单元测试框架中进行 EDT 时,您肯定是对的,事情变得非常具有挑战性。事实上,Jython 需要自己的东西,尤其是因为 Jython 与标准 CPython(只是开玩笑)不同,它是多线程的,并且涉及 EDT。我正在逐渐发展我自己的一系列技术......其优势在于我了解它实际上在做什么!
  • AFAIK 无论使用哪种单元测试框架,您都可以使用 FEST。 FEST 只是一个允许编写代码进行用户交互的库 - 单击(JB)按钮,在(JT)文本字段中输入文本等等。它类似于用于 Web UI 的 Selenium。

标签: java multithreading unit-testing jython jfilechooser


【解决方案1】:
JFileChooser chooser = new JFileChooser();
chooser.addActionListener( new ActionListener() 
{
    public void actionPerformed(ActionEvent e) 
    {
       if( e.getActionCommand().equals("CancelSelection") )
       {
            chooser.cancelSelection();
       }
    }
} );

public void forceCancel()
{
   ActionEvent e = new ActionEvent(chooser, ActionEvent.ACTION_PERFORMED, "CancelSelection");
   fireActionPerformed(e);
}

public void fireActionPerformed( ActionEvent e )
{
   ActionListener[] listeners = chooser.getActionListeners();
  for( ActionListener listener : listeners )
  {
     listener.actionPerformed( e );
  }
}

使用此代码,您可以调用forceCancel(),它会触发一个动作事件以自动取消JFileChooser。您可以在单元测试中包含forceCancel()

(或)

如果您的 Jython 中有组件,则调用 component.cancelSelection() 通过对组件进行检查实例。

【讨论】:

  • 谢谢...这很好...我唯一的问题是它有点“测试人为”...换句话说,您必须向应用程序代码添加功能,因为你知道测试代码会想要做一些你在应用程序代码中永远不会做的事情(即以编程方式取消)......
  • ...哦!你找到了答案!只是去JFileChooser.cancelSelection()(单独)完全符合我的要求:处理对话框,返回JFileChooser.CANCEL_OPTION...可能有点误导方法名称!
  • 好的。很高兴知道。我编辑了答案以获得(或)部分。我以为您在单元测试代码中无权访问选择器。
猜你喜欢
  • 2013-04-02
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
  • 2018-11-17
  • 2016-02-26
  • 2012-03-16
  • 2011-11-22
  • 2016-03-04
相关资源
最近更新 更多