JOptionPane没有按钮

17

我需要展示一条信息,需要在屏幕上停留5秒钟,在此期间,用户不能关闭对话框。规范清楚地指出,对话框不应该有任何按钮。 有没有办法在JOptionPane.showMessageDialog中使用无按钮的方式来显示对话框?


1
也许创建一个JWindow(这样它就是无装饰的,并且在标题栏中没有“关闭”按钮等)并为您的消息创建一个JLabel会满足您的需求?然后简单地创建一个定时器来自动关闭它。 - bobby_light
4个回答

41

使用showOptionDialog这种方式怎么样?也许不是showMessageDialog,但当我们没有按钮或文本输入的位置时,它可以实现同样的效果(缺点是用户可以关闭窗口):

enter image description here

  JOptionPane.showOptionDialog(null, "Hello","Empty?", JOptionPane.DEFAULT_OPTION,JOptionPane.INFORMATION_MESSAGE, null, new Object[]{}, null);

更新

这里还有另一种方法,它使用JOptionPaneJDialog(更好的是用户无法关闭):

enter image description here

final JOptionPane optionPane = new JOptionPane("Hello world", JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION, null, new Object[]{}, null);

final JDialog dialog = new JDialog();
dialog.setTitle("Message");
dialog.setModal(true);

dialog.setContentPane(optionPane);

dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.pack();

//create timer to dispose of dialog after 5 seconds
Timer timer = new Timer(5000, new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent ae) {
        dialog.dispose();
    }
});
timer.setRepeats(false);//the timer should only go off once

//start timer to close JDialog as dialog modal we must start the timer before its visible
timer.start();

dialog.setVisible(true);

@joeyrohan 是的,在添加组件的任何窗口上都需要使用 pack() - David Kroukamp
哦,好的,是有的;我问这个问题是因为我认为我们在 JOptionPane.showMessageDialog 中没有。 - joey rohan
@joeyrohan 没问题... JOptionPane 是一个包含显示简单消息的方法的类,它们可能从类本身内部调用 pack() 方法。 - David Kroukamp

1

看起来David想出了一些东西来满足你的“没有按钮”的要求。

话虽如此,听起来你可能需要澄清你的真正需求。是真的需要对话框无法关闭,还是说没有关闭对话框的按钮?JOptionPane和JDialog有一个像标准窗口一样的关闭按钮。


0
我使用了上述代码中的一部分来创建一个可外部调用的“方法”。这样可以允许多个弹出窗口。我的版本允许更改消息类型、标题、显示时间、屏幕位置、文本,并提供更改文本消息字体和颜色的示例。
/*
 * LabelDemo.java contains a method that allow multiple popups. This version allows
 * changing the message type, title, display time, screen placement, text and
 * provides examples of changing the font and color of the text message.
 */ 

package components;

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.Timer;

/*
 * LabelDemo.java 
 * 
 */
public class LabelDemo {
   public LabelDemo() {
   }

   public static void main(String[] args) {
      TextDisplayPopup("1st popup", "<html><font size=11 color=blue>information type",
            6, 50, 105, JOptionPane.INFORMATION_MESSAGE);
      TextDisplayPopup("2nd popup", "<html><font size=15 color=red>ERROR TYPE\n"
            + "<html><font size=6 color=green>2nd line with long sentence for checking"
            + " popup box dynamic sizing.",
            10, 240, 240, JOptionPane.ERROR_MESSAGE);
   }

   public static void TextDisplayPopup(String strTitle, String strText,
         int iDelayInSeconds, int iX_Location, int iY_Location, int iMessageType) {
      final JOptionPane optionPane = new JOptionPane(strText,
            iMessageType, JOptionPane.DEFAULT_OPTION,
            null, new Object[]{}, null);
      final JDialog dialog = new JDialog();
      dialog.setTitle(strTitle);
      dialog.setModal(false);
      dialog.setContentPane(optionPane);
      dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
      dialog.pack();
      dialog.setLocation(iX_Location, iY_Location);

      //create timer to dispose of dialog after, iDelayInSeconds, seconds
      Timer timer = new Timer(iDelayInSeconds*1000, new AbstractAction() {
          @Override
          public void actionPerformed(ActionEvent ae) {
              dialog.dispose();
          }
      });
      timer.setRepeats(false);  //  one-time use timer

      //  timer removes dialog after iDelayInSeconds
      timer.start();
      dialog.setVisible(true);
      System.out.println("end of test");
   }
}

输出: 第一个弹出窗口

第二个弹出窗口


-1

我觉得你不能使用JOptionPane,因为如果我没记错的话,它们总是至少有一个按钮。 但是你可以使用一个类似于this的闪屏面板,或者你可以使用一个普通的面板并在其中运行一个线程。 就像这样

public class TestFrame extends JFrame implements Runnabel{

   private Thread thread;
   private CallerClass c; //Class which built this frame

   public TestPanel(CallerClass cc){
         this.c = cc;
         this.thread = null;
         //Window can't be closed on (x)
         this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 
         //some things you put into your frame
         //...
         this.setVisible(true);
   }

   public synchronized void start(){
         if (thread == null){
         thread = new Thread(this);
     thread.start();
     }


    @Override
    public void run() {
          try{
              Thread.sleep(5000);
          }catch(InterruptedException e){ }

          this.setVisible(false);
          this.c.destroyFrame();

          this.stop();
     }
 }

destroyFrame() 是你的类中构建该面板并销毁它(将其设置为 null 或其他内容)的方法,如果你不想让图形界面的剩余部分冻结,就必须使用 SwingUtilities.invokeLater(new TestFrame(this)) 创建此框架。


-1 这段代码看起来根本无法编译和运行,同时也违反了许多Swing最佳实践。 - David Kroukamp
2
我同意David的观点,使用线程来控制对话框,并在EDT上重新同步是不好的做法,特别是当javax.swing.Timer就足够时。 - MadProgrammer
@alexvii:这不是整个代码,它只应该显示重要的部分,我认为它会工作。在阅读了这行代码 this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 之后,请再次问自己这个问题,这个类扩展了 JPanel。你还认为它可以运行吗? - nIcE cOw
1
@GagandeepBali:谢谢,这是正确的。我不知道为什么,但我混淆了Frame和Panel,实际上应该是JFrame.. 在那里你可以使用"setDefaultCloseOperation"。 - Alex VII
@alexvii:我怀疑对答案的编辑仍然没有任何作用。该调用Thread.sleep(...)会阻塞事物,这应该不被阻塞 - 如果您了解初始线程,则为EDT(事件分派线程)。 - nIcE cOw
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接