在模态JDialog之外的光标不正确?

时间:2015-10-04 02:50:39

标签: java swing modal-dialog cursor jdialog

使用方法setCursor()时,要更改组件使用的光标,一切都适用于所有组件,包括JFrameJDialog

此处的问题在于模态 JDialog。当鼠标在里面对话框时,光标会向右显示。但是,当鼠标移动到外部对话框时,光标会重新设置为操作系统默认值,即使基础JFrame使用与对话框相同的自定义光标。

我搜索了很多,发现了一些相关的问题,但没有一个对此有正确答案。

我正在使用Windows 10; JDK 1.8.0_40。

SSCCE:

package br.shura.knockback;

import java.awt.Cursor;
import java.awt.Dimension;
import javax.swing.*;

public class DialogCursorSSCCE extends JFrame {
  public DialogCursorSSCCE() {
    Cursor cursor = new Cursor(Cursor.CROSSHAIR_CURSOR);
    JButton button = new JButton("Click me to open dialog.");

    button.addActionListener(event -> {
      JDialog dialog = new JDialog();
      JLabel label = new JLabel("Move the mouse outside this dialog.");
      int width = label.getFontMetrics(label.getFont()).stringWidth(label.getText());

      label.setPreferredSize(new Dimension(width + 10, 50));
      dialog.add(label);
      dialog.pack();
      dialog.setCursor(cursor);
      dialog.setLocationRelativeTo(button);
      dialog.setModal(true);
      dialog.setTitle("Dialog");
      dialog.setVisible(true);
    });
    button.setAlignmentX(CENTER_ALIGNMENT);
    button.setMaximumSize(new Dimension(400, 100));
    setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
    add(button);
    setCursor(cursor);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setExtendedState(MAXIMIZED_BOTH);
    setTitle("DialogCursorSSCCE");
  }

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

2 个答案:

答案 0 :(得分:3)

  

但是,当鼠标移到对话框之外时,光标会重新设置为操作系统默认值

我对正在发生的事情的猜测是,对话框的边框是OS对等组件。因此,当您离开Swing组件时,会为OS对等体生成鼠标悬停事件,因此光标将设置为操作系统默认值。

当您完全离开对话框时,框架不会收到任何事件,因为对话框是模态的,因此系统光标仍会在框架上方显示。

注意光标在进入标题栏时如何变化。

现在尝试以下方法:

JDialog dialog = new JDialog();
dialog.setUndecorated(true);
dialog.getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);

现在光标只有在到达边框时才会改变,因为Swing正在绘制标题栏。

我也尝试过:

  JDialog dialog = new JDialog();
  dialog.setUndecorated(true);

所以没有装饰但光标在离开窗口时仍会改变。

我不知道怎么回事。

答案 1 :(得分:1)

我讨厌'不可能'答案 - 实际上我必须这样做。所以这里是我找到的解决方法:

1)使用ProgressMonitor(就像这里:https://docs.oracle.com/javase/tutorial/uiswing/components/progress.html) - 不是我的情况,因为我必须强烈定制它

2)模拟模态。这是我的意思的基本想法(是的,我知道我不会以这种方式锁定主框架的GUI - 你也可以做到这一点 - 幸运的是我:不是我的情况)

        mainFrame.addComponentListener(componentListener = new ComponentListener() {
            @Override
            public void componentShown(ComponentEvent e) {
            }

            @Override
            public void componentResized(ComponentEvent e) {
                placeDialog();
            }

            @Override
            public void componentMoved(ComponentEvent e) {
                placeDialog();
            }

            @Override
            public void componentHidden(ComponentEvent e) {
            }
        });
        ((Window) mainFrame).addWindowListener(windowListener = new WindowListener() {
            @Override
            public void windowOpened(WindowEvent e) {
                placeDialog();
            }

            @Override
            public void windowIconified(WindowEvent e) {
                dialog.setVisible(false);
            }

            @Override
            public void windowDeiconified(WindowEvent e) {
                placeDialog();
            }

            @Override
            public void windowDeactivated(WindowEvent e) {
            }

            @Override
            public void windowClosing(WindowEvent e) {
            }

            @Override
            public void windowClosed(WindowEvent e) {
                closeDialog();
            }

            @Override
            public void windowActivated(WindowEvent e) {
                placeDialog();
            }
        });
    }

    private void placeDialog() {
        dialog.setVisible(true);
        dialog.requestFocus();
        dialog.setLocation(mainFrame.getLocation().x + mainFrame.getWidth()/2 - dialog.getWidth()/2,
        mainFrame.getLocation().y + mainFrame.getHeight()/2 - dialog.getHeight()/2);
    }

不要忘记从mainFrame中删除侦听器(如最后一节)

希望有很多优秀的解决方案能够帮助很多人:)