在 JTabbedPane 上的 JPanel 上将 JDialog 居中

Posted

技术标签:

【中文标题】在 JTabbedPane 上的 JPanel 上将 JDialog 居中【英文标题】:Center JDialog over JPanel on JTabbedPane 【发布时间】:2012-02-16 09:14:14 【问题描述】:

我已经尝试了在这里和其他网站上找到的所有建议。

我似乎无法将此 JDialog 置于 JTabbedPane 面板的中心。

请注意,我必须禁用关闭按钮,所以我不能使用标准的 JOptionPane.showDialogXYZ() 方法。

有什么想法吗?

import java.awt.BorderLayout;
import java.awt.Dialog.ModalityType;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;

public class CenterDialog extends JFrame

    public CenterDialog()
    
        setResizable(false);

        setName(getClass().getSimpleName());
        setTitle("My Frame");
        setSize(300, 300);

        JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);

        // Add the panel
        tabbedPane.addTab("Button panel", new MyButtonPanel());

        add(tabbedPane, BorderLayout.CENTER);

        getContentPane().add(tabbedPane);
    

    private class MyButtonPanel extends JPanel
    

        public MyButtonPanel()
        
            JButton btnShowDialog = new JButton("Show Dialog");
            btnShowDialog.addActionListener(new BtnShowDialogActionListener());
            add(btnShowDialog);
        

        private class BtnShowDialogActionListener implements ActionListener
        
            public void actionPerformed(ActionEvent e)
            
                // TODO: Figure out how to center this dialog box
                final String YES = "Yup";
                final String NO = "Nope";
                final Object[] options =  YES, NO ;

                final JOptionPane optionPane = new JOptionPane("Is this centered.", JOptionPane.QUESTION_MESSAGE,
                        JOptionPane.YES_NO_OPTION, null, options, NO);

                Frame f = JOptionPane.getFrameForComponent(((JButton) e.getSource()).getParent());
                final JDialog dialog = new JDialog(f, "Question", ModalityType.APPLICATION_MODAL);

                dialog.setContentPane(optionPane);
                dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);

                dialog.addWindowListener(new WindowAdapter()
                
                    public void windowClosing(WindowEvent we)
                    
                        System.out.println("Ignoring close button");
                    
                );

                optionPane.addPropertyChangeListener(new PropertyChangeListener()
                
                    public void propertyChange(PropertyChangeEvent e)
                    
                        String prop = e.getPropertyName();

                        if (dialog.isVisible() && (e.getSource() == optionPane))
                        
                            if (prop.equals(JOptionPane.VALUE_PROPERTY))
                            
                                dialog.setVisible(false);
                            
                        
                    
                );

                dialog.pack();
                dialog.setVisible(true);
            
        
    

    private static void createAndShowGUI()
    
        // Create and set up the window.
        CenterDialog frame = new CenterDialog();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    

    public static void main(String[] args)
    
        SwingUtilities.invokeLater(new Runnable()
        
            public void run()
            
                try
                
                    createAndShowGUI();
                
                catch (Exception e)
                
                    e.printStackTrace();
                    System.exit(0);
                
            
        );
    


【问题讨论】:

感谢您的回复。无论我将哪个组件用于 relativeTo,dialog.setLocationRelativeTo(relativeTo) 都没有正确地将对话框居中。然后,我获取了 Window.setLocationRelativeTo() 的源代码并将其放在我的班级中,以便能够正确调试它。事实证明,问题在于 dialog.getBounds() 被调用并返回 (0,0) 因为对话框尚未打包。因为它没有被打包,所以它没有尺寸——这弄乱了 setLocationRelativeTo() 中的数学。解决办法,先调用 dialog.pack()。 【参考方案1】:

通过将tabbedPane 设置为全局然后dialog.setLocationRelativeTo(tabbedPane);,我稍微接近了您的目标

编辑:一个更精细,并且可能在视觉上准确的解决方案是计算 JDialog 的 x、y 坐标,如下所示:

int xDiff = (tabbedPane.getWidth() - dialog.getWidth()) / 2;
int x = tabbedPane.getX() + xDiff;
int yDiff = (tabbedPane.getHeight() - dialog.getHeight()) / 2;
int y = tabbedPane.getY() + yDiff;
dialog.setLocation(x, y);

老实说,我没有让它完美运行,但这是我的理论!

【讨论】:

hach .. 已经停止阅读您在点击“作为全局”时的预编辑答案 :-) 这既不需要也不需要 - 只需将层次结构向上移动即可。至于手动计算:对话框位置在屏幕坐标中,而组件位置相对于它所在的容器,因此您首先需要将后者转换为屏幕坐标(参见 setLocationRelativeTo 的来源;-) 同意全局位,当我希望找到正确的位置时,这是一种懒惰的解决方法。我也有一种感觉 tabbedPane 相对于它的父级定位。老实说,在我的实验中,我很懒惰(再次)并使用 JFrame 的位置进行数学运算,因为 tabbedPane 很好地坐落在其中;)我真的应该在我的回复中提到这一点>. 【参考方案2】:

使对话框相对于给定组件居中的方法(无需手动计算,内部处理组件到屏幕的坐标映射):

  dialog.setLocationRelativeTo(someComponent);

选择组件,具体取决于您想要实现的目标:

 // center relative to the button
 dialog.setLocationRelativeTo((Component) e.getSource());

 // center relative to button's parent
 dialog.setLocationRelativeTo(((Component) e.getSource()).getParent());

 // center relative to the tabbedPane
 JTabbedPane tabbed = // walk the parent chain until you reach it
 dialog.setLocationRelativeTo(tabbed);

【讨论】:

以上是关于在 JTabbedPane 上的 JPanel 上将 JDialog 居中的主要内容,如果未能解决你的问题,请参考以下文章

第十二周Java总结

从 Java Swing 组件中检索对象

如何更改 JTabbedPane 选项卡的形状?

第12周总结

我可以在 JEditorPane 上方但在 JTabbedPane 下方获得 JTextField 吗?

检测 JPanel 卸载/关闭事件