【问题标题】:components in Jdialog not shownJdialog 中的组件未显示
【发布时间】:2015-12-24 03:45:56
【问题描述】:

我的应用程序是使用 Netbeans IDE (8.0.2) 创建的。 我创建了一个 JFrame,其中包含一个绑定到数据库的 JTable(使用 JPA)。

我添加了一个“刷新”按钮,用于直接从数据库中“刷新”JTable 数据。

我希望在获取数据时显示“请稍候”消息。

为此,我实现了一个扩展 JDialog 的 JDialog_PleaseWait 类。

出于某种奇怪的原因,虽然显示了 JDialog,但它包含的 jLabel 没有显示...

JDialog_PleaseWait 类是:

 public class JDialog_PleaseWait extends javax.swing.JDialog {

//constructor for PleaseWait jDialogs

public JDialog_PleaseWait(String messageToDisplay){
    initComponents();
    this.jLabel_WaitMessage.setText(messageToDisplay);

}
/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {

    jLabel_WaitMessage = new javax.swing.JLabel();

    setTitle("Please wait...");
    setAlwaysOnTop(true);
    setBackground(new java.awt.Color(227, 248, 115));
    setModalityType(java.awt.Dialog.ModalityType.MODELESS);
    setResizable(false);
    setType(java.awt.Window.Type.POPUP);

    jLabel_WaitMessage.setBackground(new java.awt.Color(242, 253, 153));
    jLabel_WaitMessage.setText("WaitMessage");

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jLabel_WaitMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 271, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap())
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jLabel_WaitMessage)
    );

    pack();
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel jLabel_WaitMessage;
// End of variables declaration//GEN-END:variables

}

刷新 JButton 调用名为“reload”的方法,该方法最初必须显示 jDialog,然后执行其余任务。 更具体地说:

public void reload(){

    jTable_Activities.setEnabled(false);  // freezes the JTable

    JDialog_PleaseWait pleaseWaitDialog = new JDialog_PleaseWait("Communicating with database server...."); // create a new PleaseWait JDialog

    pleaseWaitDialog.pack();
    pleaseWaitDialog.setLocationRelativeTo(this); //relative to this frame
    pleaseWaitDialog.setVisible(true);  //display the JDialog

.... ....
    // runs a DB query and updates a JTable
.... ....

所以,由于某种原因,JDialog 窗口弹出但 jLabel 没有显示...

我(我认为我)已经对其他工作正常的 JDialog 做了(确切的?)同样的事情,但是由于某些奇怪的原因,这个 JDialog 不能正常工作......

有什么提示吗?

【问题讨论】:

    标签: java swing components jdialog


    【解决方案1】:

    您可能的问题是您在 Swing 事件线程上获取数据(我没有看到上面使用 Thread/Runnable/SwingWorker 等的任何代码,因此我的假设),这是捆绑事件线程并阻止它做家务——包括将标签绘制到 JDialog。解决方案:在后台线程中获取数据,例如使用 SwingWorker。

    这里有一个例子来说明我的意思。该代码创建了两个 JButton,一个显示 JDialog 2 秒,在这 2 秒内,Thread.sleep(...) 在 Swing 事件线程上运行,另一个在后台线程中运行 Thread.sleep(...)。编译并运行代码,看看会发生什么。

    import java.awt.Dimension;
    import java.awt.GridBagLayout;
    import java.awt.Window;
    import java.awt.Dialog.ModalityType;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class PleaseWaitDialogTest extends JPanel {
        protected static final long SLEEP_TIME = 2000L;
    
        public PleaseWaitDialogTest() {
            add(new JButton(new ShowWaitDialog("Without Thread", KeyEvent.VK_O, false)));
            add(new JButton(new ShowWaitDialog("With BG Thread", KeyEvent.VK_W, true)));
        }
    
        private class ShowWaitDialog extends AbstractAction {
            private boolean useBackgroundThread;
            private JDialog dialog;
    
            public ShowWaitDialog(String name, int mnemonic,
                    boolean useBackgroundThread) {
                super(name);
                putValue(MNEMONIC_KEY, mnemonic);
                this.useBackgroundThread = useBackgroundThread;
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                // create dialog in a lazy way
                if (dialog == null) {
                    Window ancestorWindow = SwingUtilities
                            .getWindowAncestor(PleaseWaitDialogTest.this);
                    String title = "Dialog: " + getValue(NAME);
                    dialog = new JDialog(ancestorWindow, title,
                            ModalityType.MODELESS);
                    dialog.getContentPane().setLayout(new GridBagLayout());
                    dialog.add(new JLabel("Please Wait"));
                    dialog.setPreferredSize(new Dimension(250, 150));
                    dialog.pack();
                    dialog.setLocationByPlatform(true);
                }
                dialog.setVisible(true);
    
                // since the dialog is non-modal, this code will run immediately after
                // the dialog has been set visible
                CloseRunnable closeRunnable = new CloseRunnable(dialog, SLEEP_TIME);
                if (useBackgroundThread) {
                    // run the Runnable in a background thread
                    new Thread(closeRunnable).start();
                } else {
                    // run the Runnable directly on the Swing event thread
                    closeRunnable.run();
                }
            }
        }
    
        private class CloseRunnable implements Runnable {
            protected JDialog dialog;
            private long sleepTime;
    
            public CloseRunnable(JDialog dialog, long sleepTime) {
                this.dialog = dialog;
                this.sleepTime = sleepTime;
            }
    
            @Override
            public void run() {
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                // the dialog *must* be closed on the Swing event thread
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        if (dialog != null) {
                            dialog.setVisible(false);
                        }
                    }
                });
            }
        }
    
        private static void createAndShowGui() {
            PleaseWaitDialogTest mainPanel = new PleaseWaitDialogTest();
    
            JFrame frame = new JFrame("Test");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGui();
                }
            });
        }
    }
    

    【讨论】:

    • 我不介意在 Swing 线程中运行“重新加载”功能。据我了解,如果“请稍候”的工作需要很长时间,我应该使用 SwingWorker,冻结应用。在(至少)这一点上,它并没有花费很多时间,而弹出 JDialog+label 出现(或至少应该出现)“重新加载”作业尚未开始(即首先我尝试获取 JDialog+Label变得可见,然后运行重新加载(数据库查询)..这就是为什么我只是在上面的代码( reload() )的末尾添加了一个注释,以表明最后开始了长时间的工作......
    • @TassosPan:问题很简单——如果你想让对话框绘制并显示它的组件,那么任务需要在后台线程中,这并不难做到.
    • @TassosPan:请参阅发布的代码,该代码准确地展示了我的意思。
    • 非常感谢您的反馈。我打算按照你的建议去做,但我也想对我在上面发表的评论做出回应......即为什么会这样……
    • 此外,在上面运行您的应用程序后,我注意到 JDialog 仅在第一次“无线程”按钮按下时未正确显示。如果我再次单击它,它会一直正确显示...
    猜你喜欢
    • 2011-09-17
    • 2012-09-19
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多