将鼠标悬停在 JSplitPane 分隔线上时更改光标
Change cursor when hovering over JSplitPane divider
当我将鼠标悬停在 JSplitPane
分隔线上时,我需要更改光标。这纯粹是为了提高可用性。我发现了两种方法来实现这一点。代码如下
方法 01
BasicSplitPaneUI basicSplitPaneUI = (BasicSplitPaneUI)splitPane.getUI();
BasicSplitPaneDivider divider = basicSplitPaneUI.getDivider();
divider.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
方法 02
Component divider = splitPane.getComponent(2);
divider.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
我的问题是,如果 JSplitPane
的顶部容器是 JFrame
或 JWindow
,这两种方法都可以正常工作。为了测试,我写了一小段代码,其中 JSplitPane
添加到 JPanel
,然后再添加到 JFrame
。将鼠标悬停在分隔线上时,光标会按预期变化。
但我正在为 intellij 开发一个 Tool Window
插件,JSplitPane
(包含在 JPanel
中)被添加到 ToolWindow
容器中。在这种情况下,当我将鼠标悬停在分隔线上时,光标保持不变。
下面是我为模拟上述场景而编写的一些测试代码。
案例01
public class Main {
public static void main(String args[]){
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
//PanelWithSplitPane extends JPanel. Builds the JSplitPane
PanelWithSplitPane viewer = new PanelWithSplitPane();
f.add(viewer, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
}
输出:按预期工作。光标悬停在分隔线上方时会发生变化
案例02:Intellij插件
注意:这是一个intellij插件项目,在plugin.xml文件中指定了toolWindow
扩展名。基本上 createToolWindowContent
方法是在 IDE 中打开工具 Window 时执行的。视图和任何进一步的用户交互都是从这里处理的。
public class TestPane implements ToolWindowFactory {
//this method gets called when the toolWindow is opened in the IDE
@Override
public void createToolWindowContent(Project project, ToolWindow toolWindow) {
PanelWithSplitPane viewer = new PanelWithSplitPane();
toolWindow.getComponent().add(panel);
}
}
输出:没有按预期工作。光标悬停在分隔线上方时保持不变
PanelWithSplitPane 代码
public class PanelWithSplitPane extends JPanel {
public PanelWithSplitPane() {
this.setLayout(new BorderLayout());
JSplitPane splitPane = new javax.swing.JSplitPane();
splitPane.setBorder(null);
splitPane.setDividerLocation(1300);
splitPane.setDividerSize(6);
splitPane.setContinuousLayout(true);
splitPane.setOneTouchExpandable(true);
BasicSplitPaneUI basicSplitPaneUI = (BasicSplitPaneUI)splitPane.getUI();
BasicSplitPaneDivider divider = basicSplitPaneUI.getDivider();
divider.setCursor(new Cursor(Cursor.HAND_CURSOR));
this.add(splitPane);
}
}
例如,通过使用MouseListener及其方法mouseEntered/mouseExited(通过returns Cursor恢复默认值)
注意我无法删除黑色矩形(在运行时创建的不需要的绘画人工制品,移动分隔线时,您可以在左侧看到它)
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
public class JSplitPaneToy {
private JSplitPane sp;
public JSplitPaneToy() {
sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, makePanel(), makePanel());
/*SplitPaneUI ui = sp.getUI();
if (ui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) ui).getDivider().setBorder(null);
}*/
BasicSplitPaneUI l_ui = (BasicSplitPaneUI) sp.getUI();
final BasicSplitPaneDivider l_divider = l_ui.getDivider();
l_divider.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
Dimension l_pane_size = sp.getSize();
if (sp.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
int l_new_loc = sp.getDividerLocation() + e.getX();
if (l_new_loc >= 0 && l_new_loc <= l_pane_size.width) {
sp.setDividerLocation(l_new_loc);
}
} else {
int l_new_loc = sp.getDividerLocation() + e.getY();
if (l_new_loc >= 0 && l_new_loc <= l_pane_size.height) {
sp.setDividerLocation(l_new_loc);
}
}
}
});
l_divider.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
l_divider.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
}
@Override
public void mouseExited(MouseEvent e) {
l_divider.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
});
sp.setBorder(BorderFactory.createEmptyBorder());
/*sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
ui = sp.getUI();
if (ui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) ui).getDivider().setBorder(null);
}
sp.setBorder(BorderFactory.createEmptyBorder());
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
ui = sp.getUI();
if (ui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) ui).getDivider().setBorder(null);
}
sp.setBorder(BorderFactory.createEmptyBorder());
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
ui = sp.getUI();
if (ui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) ui).getDivider().setBorder(null);
}
sp.setBorder(BorderFactory.createEmptyBorder());*/
JFrame frame = new JFrame("JSplitPane Toy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(sp);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
/*try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
}*/
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JSplitPaneToy jSplitPaneToy = new JSplitPaneToy();
}
});
}
private JScrollPane makePanel() {
JScrollPane pane = new JScrollPane(new JTable(
new Object[][]{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}, new Object[]{1, 2, 3}) {
private static final long serialVersionUID = 1L;
});
pane.setPreferredSize(new Dimension(200, 100));
return pane;
}
}
我更改了将 JPanel
添加到 ToolWindow
的代码,现在 setCursor 方法按预期工作。变化如下所示。
旧版本:
PanelWithSplitPane viewer = new PanelWithSplitPane();
toolWindow.getComponent().add(panel);
新变体:
PanelWithSplitPane viewer = new PanelWithSplitPane();
final ContentFactory contentFactory = toolWindow.getContentManager().getFactory();
final Content content = contentFactory.createContent(viewer, "", true);
toolWindow.getContentManager().addContent(content);
当我将鼠标悬停在 JSplitPane
分隔线上时,我需要更改光标。这纯粹是为了提高可用性。我发现了两种方法来实现这一点。代码如下
方法 01
BasicSplitPaneUI basicSplitPaneUI = (BasicSplitPaneUI)splitPane.getUI();
BasicSplitPaneDivider divider = basicSplitPaneUI.getDivider();
divider.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
方法 02
Component divider = splitPane.getComponent(2);
divider.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
我的问题是,如果 JSplitPane
的顶部容器是 JFrame
或 JWindow
,这两种方法都可以正常工作。为了测试,我写了一小段代码,其中 JSplitPane
添加到 JPanel
,然后再添加到 JFrame
。将鼠标悬停在分隔线上时,光标会按预期变化。
但我正在为 intellij 开发一个 Tool Window
插件,JSplitPane
(包含在 JPanel
中)被添加到 ToolWindow
容器中。在这种情况下,当我将鼠标悬停在分隔线上时,光标保持不变。
下面是我为模拟上述场景而编写的一些测试代码。
案例01
public class Main {
public static void main(String args[]){
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
//PanelWithSplitPane extends JPanel. Builds the JSplitPane
PanelWithSplitPane viewer = new PanelWithSplitPane();
f.add(viewer, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
}
输出:按预期工作。光标悬停在分隔线上方时会发生变化
案例02:Intellij插件
注意:这是一个intellij插件项目,在plugin.xml文件中指定了toolWindow
扩展名。基本上 createToolWindowContent
方法是在 IDE 中打开工具 Window 时执行的。视图和任何进一步的用户交互都是从这里处理的。
public class TestPane implements ToolWindowFactory {
//this method gets called when the toolWindow is opened in the IDE
@Override
public void createToolWindowContent(Project project, ToolWindow toolWindow) {
PanelWithSplitPane viewer = new PanelWithSplitPane();
toolWindow.getComponent().add(panel);
}
}
输出:没有按预期工作。光标悬停在分隔线上方时保持不变
PanelWithSplitPane 代码
public class PanelWithSplitPane extends JPanel {
public PanelWithSplitPane() {
this.setLayout(new BorderLayout());
JSplitPane splitPane = new javax.swing.JSplitPane();
splitPane.setBorder(null);
splitPane.setDividerLocation(1300);
splitPane.setDividerSize(6);
splitPane.setContinuousLayout(true);
splitPane.setOneTouchExpandable(true);
BasicSplitPaneUI basicSplitPaneUI = (BasicSplitPaneUI)splitPane.getUI();
BasicSplitPaneDivider divider = basicSplitPaneUI.getDivider();
divider.setCursor(new Cursor(Cursor.HAND_CURSOR));
this.add(splitPane);
}
}
例如,通过使用MouseListener及其方法mouseEntered/mouseExited(通过returns Cursor恢复默认值)
注意我无法删除黑色矩形(在运行时创建的不需要的绘画人工制品,移动分隔线时,您可以在左侧看到它)
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
public class JSplitPaneToy {
private JSplitPane sp;
public JSplitPaneToy() {
sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, makePanel(), makePanel());
/*SplitPaneUI ui = sp.getUI();
if (ui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) ui).getDivider().setBorder(null);
}*/
BasicSplitPaneUI l_ui = (BasicSplitPaneUI) sp.getUI();
final BasicSplitPaneDivider l_divider = l_ui.getDivider();
l_divider.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
Dimension l_pane_size = sp.getSize();
if (sp.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
int l_new_loc = sp.getDividerLocation() + e.getX();
if (l_new_loc >= 0 && l_new_loc <= l_pane_size.width) {
sp.setDividerLocation(l_new_loc);
}
} else {
int l_new_loc = sp.getDividerLocation() + e.getY();
if (l_new_loc >= 0 && l_new_loc <= l_pane_size.height) {
sp.setDividerLocation(l_new_loc);
}
}
}
});
l_divider.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
l_divider.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
}
@Override
public void mouseExited(MouseEvent e) {
l_divider.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
});
sp.setBorder(BorderFactory.createEmptyBorder());
/*sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
ui = sp.getUI();
if (ui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) ui).getDivider().setBorder(null);
}
sp.setBorder(BorderFactory.createEmptyBorder());
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
ui = sp.getUI();
if (ui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) ui).getDivider().setBorder(null);
}
sp.setBorder(BorderFactory.createEmptyBorder());
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
ui = sp.getUI();
if (ui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) ui).getDivider().setBorder(null);
}
sp.setBorder(BorderFactory.createEmptyBorder());*/
JFrame frame = new JFrame("JSplitPane Toy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(sp);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
/*try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
}*/
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JSplitPaneToy jSplitPaneToy = new JSplitPaneToy();
}
});
}
private JScrollPane makePanel() {
JScrollPane pane = new JScrollPane(new JTable(
new Object[][]{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}, new Object[]{1, 2, 3}) {
private static final long serialVersionUID = 1L;
});
pane.setPreferredSize(new Dimension(200, 100));
return pane;
}
}
我更改了将 JPanel
添加到 ToolWindow
的代码,现在 setCursor 方法按预期工作。变化如下所示。
旧版本:
PanelWithSplitPane viewer = new PanelWithSplitPane();
toolWindow.getComponent().add(panel);
新变体:
PanelWithSplitPane viewer = new PanelWithSplitPane();
final ContentFactory contentFactory = toolWindow.getContentManager().getFactory();
final Content content = contentFactory.createContent(viewer, "", true);
toolWindow.getContentManager().addContent(content);