我有一个带有JSplitPane的Java GUI程序划分内容。 JSplitPane的左侧是一个带有多个选项卡的JTabbedPane - 一个非常复杂的布局。当左侧达到一定程度的复杂性时,拖动分隔线以移动分隔线位置不再有效,但我仍然可以通过显式设置位置来移动分隔线。 (如果重要的话,我正在使用Nimbus LAF。)
它似乎不仅仅是左侧标签的数量。我在左侧包含的某些选项卡使其停止工作而其他选项卡正常。
有没有人碰到这个?
我能够通过在我的JSplitPane子类上添加一个黑客解决方法来解决它。
public void enableDividerWorkaround() {
javax.swing.plaf.basic.BasicSplitPaneUI l_ui = (javax.swing.plaf.basic.BasicSplitPaneUI) getUI();
BasicSplitPaneDivider l_divider = l_ui.getDivider();
l_divider.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
Dimension l_pane_size = getSize();
if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
int l_new_loc = getDividerLocation() + e.getX();
if (l_new_loc >= 0 && l_new_loc <= l_pane_size.width) {
setDividerLocation(l_new_loc);
}
} else {
int l_new_loc = getDividerLocation() + e.getY();
if (l_new_loc >= 0 && l_new_loc <= l_pane_size.height) {
setDividerLocation(l_new_loc);
}
}
}
});
}
UPDATE 这是SSCCE(下面)。当我运行它时,第一次将滑块向右拖动时,它会“捕捉”到长标签的末尾,然后保持固定。我相信它是由长标签引发的。如果我缩短标签,我会在滑块上获得更多的运动范围。那么这是一个错误,还是预期的行为?
public class SplitPaneTest extends javax.swing.JFrame {
public SplitPaneTest() {
initComponents();
}
private void initComponents() {
jSplitPane1 = new javax.swing.JSplitPane();
jLabel1 = new javax.swing.JLabel();
jPanel1 = new javax.swing.JPanel();
jLabel2 = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jSplitPane1.setDividerLocation(450);
jSplitPane1.setName("jSplitPane1");
jLabel1.setText("right side");
jLabel1.setName("jLabel1");
jSplitPane1.setRightComponent(jLabel1);
jPanel1.setName("jPanel1");
jLabel2.setText("left side asd adsf asdf asdf asdf sadf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdfa end");
jLabel2.setName("jLabel2");
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel2)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel2)
.addContainerGap(420, Short.MAX_VALUE))
);
jSplitPane1.setLeftComponent(jPanel1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane1)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane1)
);
pack();
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new SplitPaneTest().setVisible(true);
}
});
}
protected javax.swing.JLabel jLabel1;
protected javax.swing.JLabel jLabel2;
protected javax.swing.JPanel jPanel1;
protected javax.swing.JSplitPane jSplitPane1;
}
答案 0 :(得分:3)
我花了很多时间试图达到一个目标 SSCCE但无法这样做
请问什么? SSCCE最多5分钟
现在还有两个问题
也有SplitPaneUI
的定义,因为if (ui instanceof BasicSplitPaneUI) {
可以返回false
描述了添加MouseMotionListener
EDIT_1st。
JSplitPane的左侧是一个带有多个标签的JTabbedPane - 非常复杂的布局。当左侧达到一定程度的复杂性时,拖动分隔线以移动分隔线位置号 更长的工作,但我仍然可以通过明确设置移动分隔线 位置。
调整JSplitPane容器大小时的分配空间重量 拆分窗格控制分割时分隔符的行为 窗格已调整大小。如果重量为0,则给予所有额外空间 右或底组件。如果重量为1,则所有额外空间均为 给予左侧或顶部组件。权重.3指定 left或top组件获得额外空间的三分之一。重量 还决定了当分裂的大小时孩子们如何失去空间 窗格缩小了。例如,权重为0表示左侧或顶部 组件不会丢失任何空间。
重量也控制分隔线的起始位置。对于 例如,如果重量是.5,则分隔线位于中心。 COPY
// Create a left-right split pane
JSplitPane pane = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT, leftComponent, rightComponent);
// Get current weight
double weight = pane.getResizeWeight(); // 0.0 by default
// Keep the size of the right component constant
weight = 1D;
pane.setResizeWeight(weight);
// Split the space evenly
weight = .5D;
pane.setResizeWeight(weight);
EDIT_2nd。
你忘了告诉我们在Nimbus中有分频器闪烁,而不是标准L&amp; Fs的剩余部分
import java.awt.Dimension;
import java.awt.EventQueue;
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();
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);
}
}
}
});
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) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
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}) {
});
pane.setPreferredSize(new Dimension(200, 100));
return pane;
}
}
答案 1 :(得分:3)
这似乎是故意行为。在javax.swing.plaf.basic.BasicSplitPaneDivider.DragController的构造函数中找到以下代码:
minX = leftC.getMinimumSize().width;
然后在同一个班级
/**
* Returns the new position to put the divider at based on
* the passed in MouseEvent.
*/
protected int positionForMouseEvent(MouseEvent e) {
int newX = (e.getSource() == BasicSplitPaneDivider.this) ?
(e.getX() + getLocation().x) : e.getX();
newX = Math.min(maxX, Math.max(minX, newX - offset));
return newX;
}
因此,基本用户界面似乎不会让你拖动分隔线,使左侧小于最小尺寸。
在我的情况下,这种行为不符合我的需要,所以我的小解决方案是必要的。