将JMenuItem添加到已经可见的JMenu中

时间:2015-12-04 19:02:53

标签: java swing jmenu jmenuitem

我已经在听MenuListener.menuSelected()知道屏幕上显示JMenu的时间。最初,JMenu有1 JMenuItem,表示“正在加载...”。操作缓慢后,我将JMenuItem添加到JMenuJMenu继续显示“正在加载...”。如果我选择另一个JMenu并返回,则JMenu会显示添加的JMenuItem。如何使添加的JMenuItem立即显示?

以下是重现正在发生的事情的代码。

public class AddMenuItem extends JFrame
{
   private final JMenu m_menu = new JMenu("Edit");

   public static void main(String args[])
   {
      new AddMenuItem().
         setVisible(true);
   }

   public AddMenuItem()
   {
      JMenuBar bar;

      bar = new JMenuBar();

      bar.add(m_menu);
      setJMenuBar(bar);
      setSize(600, 400);

      m_menu.addMenuListener(new MenuListener()
      {
         @Override
         public void menuSelected(MenuEvent e)
         {
            JMenuItem loading;

            loading = new JMenuItem("Loading...");

            loading.setEnabled(false);
            m_menu.removeAll();
            m_menu.add(loading);

            // This represents a long running task which updates the menu afterwards
            new Timer(5 * 1000, event -> updateMenu()).start();
         }

         @Override
         public void menuDeselected(MenuEvent e)
         {
            // nothing to do
         }

         @Override
         public void menuCanceled(MenuEvent e)
         {
            // nothing to do
         }
      });
   }

   private void updateMenu()
   {
      m_menu.removeAll();
      m_menu.add(new JMenuItem("1"));
      m_menu.add(new JMenuItem("2"));
      m_menu.add(new JMenuItem("3"));
      m_menu.revalidate();
   }
}

似乎这个code example完全符合我的要求,但我不确定他们在屏幕上重新绘制可见菜单是做什么的。

2 个答案:

答案 0 :(得分:3)

  

最初,JMenu有1个JMenuItem,表示"正在加载..."。

从侦听器调用的代码在Event Dispatch Thread (EDT)上执行。执行长时间运行的任务时,它会阻止EDT响应事件并重新绘制GUI。

因此,要解决该问题,该菜单项启动的任务需要在单独的线程中执行。您可能需要考虑使用SwingWorker。有关EDTSwingWorker的更多信息,请阅读Concurrency上的Swing教程中的部分。

编辑:

  

问题是,一旦我知道要添加到菜单中的内容,我就不知道如何让菜单显示添加的JMenuItems

您从JMenu的{​​{1}}获得MenuEvent

MenuListener

编辑:

根据SSCCE,您可以执行以下操作:

JMenu menu = (JMenu)e.getSource();
menu.add( new JMenuItem( "Loading..." ) );

但请记住,因为您的长时间运行任务在一个单独的线程中执行,您需要使用SwingUtiltities.invokeLater调用上述代码,以便在EDT上执行代码。

  

看起来这个代码示例正是我想要的,但我不确定他们在屏幕上重新绘制可见菜单是做什么的。

我认为他们只是隐藏并再次显示菜单。

答案 1 :(得分:0)

不要执行EVP_DecryptFinal_ex(),而是执行以下操作...

m_menu.revalidate()