我的应用程序有一个有两个孩子的SashForm。我希望在调整窗口大小时左边的孩子保持相同的大小。我想要Eclipse使用Package Explorer和主编辑器做同样的事情。调整窗口大小时,只有文本编辑器会更改大小。但是,包装资源管理器仍然可以通过窗扇调整大小。
我尝试使用以下
sashForm.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
int width = sashForm.getClientArea().width;
int[] weights = sashForm.getWeights();
weights[1] = width - weights[0];
sashForm.setWeights(weights);
}
});
问题是左侧尺寸的宽度要么缩小到0还是要扩大太多。看起来在调用它之前更新了权重。
如果我将权重[0]设置为等于某个常数,则按我想要的那样。
答案 0 :(得分:2)
我设法得到一个运行示例,应该让你知道如何解决你的问题。问题是,SashForm
使用权重而不是像素。因此,您必须根据父级大小计算左侧孩子必须占用的百分比,并将其余孩子分配给正确的孩子。
在我的代码示例中,您可以指定左子项的宽度并为右侧子项设置最小大小,以便SashForm
始终显示两者。
private static final int MIN_WIDTH_LEFT = 100;
private static final int MIN_WIDTH_RIGHT = 50;
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
final SashForm form = new SashForm(shell, SWT.HORIZONTAL);
Button button = new Button(form, SWT.PUSH);
button.setText("Left");
Button buttonR = new Button(form, SWT.PUSH);
buttonR.setText("Right");
form.setWeights(new int[] {1, 2});
shell.addListener(SWT.Resize, new Listener()
{
@Override
public void handleEvent(Event arg0)
{
int width = shell.getClientArea().width;
int[] weights = form.getWeights();
if(width >= MIN_WIDTH_LEFT + MIN_WIDTH_RIGHT)
{
weights[0] = 1000000 * MIN_WIDTH_LEFT / width;
weights[1] = 1000000 - weights[0];
}
else
{
weights[0] = 1000000 * MIN_WIDTH_LEFT / (MIN_WIDTH_LEFT + MIN_WIDTH_RIGHT);
weights[1] = 1000000 * MIN_WIDTH_RIGHT / (MIN_WIDTH_LEFT + MIN_WIDTH_RIGHT);
}
System.out.println(width + " " + Arrays.toString(weights));
form.setWeights(weights);
}
});
shell.pack();
shell.setSize(600, 400);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
这就是它的样子:
启动:
调整大小后:
当减小窗口大小直到它太小而不能显示最小尺寸时:
正如您在本案例中所看到的,忽略了左子项的最小大小,但仍然可以显示两个孩子。
答案 1 :(得分:2)
这是我能想到的最佳解决方案。
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
public class Main {
private static int leftWidth, oldWeight;
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
shell.setSize(600, 400);
final SashForm form = new SashForm(shell, SWT.HORIZONTAL);
final Button button = new Button(form, SWT.PUSH);
button.setText("Left");
button.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(Event arg0) {
int[] weights = form.getWeights();
// oldWeights is used to distinguish between a window resize and
// a sash move
if (oldWeight != weights[0]) {
System.out.println("Weights changed!");
oldWeight = weights[0];
leftWidth = (int) Math.round((double) form.getClientArea().width
* (double) weights[0]
/ (double) (weights[0] + weights[1]));
}
}
});
Button buttonR = new Button(form, SWT.PUSH);
buttonR.setText("Right");
form.setWeights(new int[] { 200, 800 });
leftWidth = 200;
form.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(Event arg0) {
int width = form.getClientArea().width;
int[] weights = form.getWeights();
double perChange = (double) leftWidth / (double) width;
weights[0] = (int) (perChange * 1000.0);
weights[1] = 1000 - weights[0];
// oldWeights must be set before form.setWeights
oldWeight = weights[0];
form.setWeights(weights);
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
由于四舍五入的问题,当窗口调整大小时窗扇跳转大约1px,但它似乎做了我想要的。
这是一个非常hacky的解决方案,我想知道是否有更好的解决方案。如果你让窗口小于左按钮,它也会崩溃,但这很容易修复。
答案 2 :(得分:0)
必须重写SashForm才能获得此行为。 <script src="https://code.jquery.com/jquery-1.12.1.min.js"></script>
<table class="table">
<tbody>
<tr class="parent" id="2479">
<td><span class="btn btn-default">expand</span></td>
</tr>
<tr class="child-2479">
<td>row 1</td>
<td>row 1</td>
<td>row 1</td>
<td>row 1</td>
<td>row 1</td>
<td>row 1</td>
</tr>
<tr class="parent" id="2800">
<td><span class="btn btn-default">expand</span></td>
</tr>
<tr class="child-2800">
<td>row 2</td>
<td>row 2</td>
<td>row 2</td>
<td>row 2</td>
<td>row 2</td>
<td>row 2</td>
</tr>
</tbody>
</table>
是旧行为; new SashForm(Composite parent, int style)
使用以像素为单位指定的宽度/高度。
未使用SashForm的两个以上复合子项进行测试,如果在使用新行为时没有new SashForm(Composite parent, int style, false)
,则会出现奇怪行为,但不会破坏SashForm的现有用法
e.g:
setLength
第一个按钮默认为250像素,第二个按钮
SashForm.java:
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
final SashForm form = new SashForm(shell, SWT.HORIZONTAL);
Button button = new Button(form, SWT.PUSH);
button.setText("Left");
Button buttonR = new Button(form, SWT.PUSH);
buttonR.setText("Right");
form.setLengths(new int[] { 250, 25 });
shell.pack();
shell.setSize(600, 400);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
SashFormData.java:
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
public class SashForm extends Composite {
/**
* The width of all sashes in the form.
*/
public int SASH_WIDTH = 3;
int sashStyle;
final private boolean weighted;
Sash[] sashes = new Sash[0];
// Remember background and foreground
// colors to determine whether to set
// sashes to the default color (null) or
// a specific color
Color background = null;
Color foreground = null;
Control[] controls = new Control[0];
Control maxControl = null;
Listener sashListener;
static final int DRAG_MINIMUM = 20;
public SashForm(Composite parent, int style) {
super(parent, checkStyle(style));
super.setLayout(new SashFormLayout());
sashStyle = ((style & SWT.VERTICAL) != 0) ? SWT.HORIZONTAL : SWT.VERTICAL;
if ((style & SWT.BORDER) != 0) sashStyle |= SWT.BORDER;
if ((style & SWT.SMOOTH) != 0) sashStyle |= SWT.SMOOTH;
sashListener = new Listener() {
public void handleEvent(Event e) {
onDragSash(e);
}
};
weighted = true;
}
public SashForm(Composite parent, int style, boolean weighted) {
super(parent, checkStyle(style));
super.setLayout(new SashFormLayout());
sashStyle = ((style & SWT.VERTICAL) != 0) ? SWT.HORIZONTAL : SWT.VERTICAL;
if ((style & SWT.BORDER) != 0) sashStyle |= SWT.BORDER;
if ((style & SWT.SMOOTH) != 0) sashStyle |= SWT.SMOOTH;
sashListener = new Listener() {
public void handleEvent(Event e) {
onDragSash(e);
}
};
this.weighted = weighted;
}
static int checkStyle (int style) {
int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
return style & mask;
}
Sash createSash() {
Sash sash = new Sash(this, sashStyle);
sash.setBackground(background);
sash.setForeground(foreground);
sash.setToolTipText(getToolTipText());
sash.addListener(SWT.Selection, sashListener);
return sash;
}
@Override
public int getOrientation() {
//checkWidget();
return (sashStyle & SWT.VERTICAL) != 0 ? SWT.HORIZONTAL : SWT.VERTICAL;
}
/**
* Returns the width of the sashes when the controls in the SashForm are
* laid out.
*
* @return the width of the sashes
*
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*
* @since 3.4
*/
public int getSashWidth() {
checkWidget();
return SASH_WIDTH;
}
@Override
public int getStyle() {
int style = super.getStyle();
style |= getOrientation() == SWT.VERTICAL ? SWT.VERTICAL : SWT.HORIZONTAL;
if ((sashStyle & SWT.SMOOTH) != 0) style |= SWT.SMOOTH;
return style;
}
/**
* Answer the control that currently is maximized in the SashForm.
* This value may be null.
*
* @return the control that currently is maximized or null
*/
public Control getMaximizedControl(){
//checkWidget();
return this.maxControl;
}
public int[] getWeights() {
checkWidget();
Control[] cArray = getControls(false);
int[] ratios = new int[cArray.length];
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
ratios[i] = (int)(((SashFormData)data).weight * 1000 >> 16);
} else {
ratios[i] = 200;
}
}
return ratios;
}
Control[] getControls(boolean onlyVisible) {
Control[] children = getChildren();
Control[] result = new Control[0];
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Sash) continue;
if (onlyVisible && !children[i].getVisible()) continue;
Control[] newResult = new Control[result.length + 1];
System.arraycopy(result, 0, newResult, 0, result.length);
newResult[result.length] = children[i];
result = newResult;
}
return result;
}
boolean getWeighted() {
return weighted;
}
void onDragSash(Event event) {
Sash sash = (Sash)event.widget;
int sashIndex = -1;
for (int i= 0; i < sashes.length; i++) {
if (sashes[i] == sash) {
sashIndex = i;
break;
}
}
if (sashIndex == -1) return;
Control c1 = controls[sashIndex];
Control c2 = controls[sashIndex + 1];
Rectangle b1 = c1.getBounds();
Rectangle b2 = c2.getBounds();
Rectangle sashBounds = sash.getBounds();
Rectangle area = getClientArea();
boolean correction = false;
if (getOrientation() == SWT.HORIZONTAL) {
correction = b1.width < DRAG_MINIMUM || b2.width < DRAG_MINIMUM;
int totalWidth = b2.x + b2.width - b1.x;
int shift = event.x - sashBounds.x;
b1.width += shift;
b2.x += shift;
b2.width -= shift;
if (b1.width < DRAG_MINIMUM) {
b1.width = DRAG_MINIMUM;
b2.x = b1.x + b1.width + sashBounds.width;
b2.width = totalWidth - b2.x;
event.x = b1.x + b1.width;
event.doit = false;
}
if (b2.width < DRAG_MINIMUM) {
b1.width = totalWidth - DRAG_MINIMUM - sashBounds.width;
b2.x = b1.x + b1.width + sashBounds.width;
b2.width = DRAG_MINIMUM;
event.x = b1.x + b1.width;
event.doit = false;
}
Object data1 = c1.getLayoutData();
if (data1 == null || !(data1 instanceof SashFormData)) {
data1 = new SashFormData();
c1.setLayoutData(data1);
}
Object data2 = c2.getLayoutData();
if (data2 == null || !(data2 instanceof SashFormData)) {
data2 = new SashFormData();
c2.setLayoutData(data2);
}
((SashFormData)data1).weight = (((long)b1.width << 16) + area.width - 1) / area.width;
((SashFormData)data1).length = b1.width;
((SashFormData)data2).weight = (((long)b2.width << 16) + area.width - 1) / area.width;
((SashFormData)data2).length = b2.width;
} else {
correction = b1.height < DRAG_MINIMUM || b2.height < DRAG_MINIMUM;
int totalHeight = b2.y + b2.height - b1.y;
int shift = event.y - sashBounds.y;
b1.height += shift;
b2.y += shift;
b2.height -= shift;
if (b1.height < DRAG_MINIMUM) {
b1.height = DRAG_MINIMUM;
b2.y = b1.y + b1.height + sashBounds.height;
b2.height = totalHeight - b2.y;
event.y = b1.y + b1.height;
event.doit = false;
}
if (b2.height < DRAG_MINIMUM) {
b1.height = totalHeight - DRAG_MINIMUM - sashBounds.height;
b2.y = b1.y + b1.height + sashBounds.height;
b2.height = DRAG_MINIMUM;
event.y = b1.y + b1.height;
event.doit = false;
}
Object data1 = c1.getLayoutData();
if (data1 == null || !(data1 instanceof SashFormData)) {
data1 = new SashFormData();
c1.setLayoutData(data1);
}
Object data2 = c2.getLayoutData();
if (data2 == null || !(data2 instanceof SashFormData)) {
data2 = new SashFormData();
c2.setLayoutData(data2);
}
((SashFormData)data1).weight = (((long)b1.height << 16) + area.height - 1) / area.height;
((SashFormData)data2).weight = (((long)b2.height << 16) + area.height - 1) / area.height;
}
if (correction || (event.doit && event.detail != SWT.DRAG)) {
c1.setBounds(b1);
sash.setBounds(event.x, event.y, event.width, event.height);
c2.setBounds(b2);
}
}
@Override
public void setOrientation(int orientation) {
checkWidget();
if (orientation == SWT.RIGHT_TO_LEFT || orientation == SWT.LEFT_TO_RIGHT) {
super.setOrientation(orientation);
return;
}
if (getOrientation() == orientation) return;
if (orientation != SWT.HORIZONTAL && orientation != SWT.VERTICAL) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
sashStyle &= ~(SWT.HORIZONTAL | SWT.VERTICAL);
sashStyle |= orientation == SWT.VERTICAL ? SWT.HORIZONTAL : SWT.VERTICAL;
for (int i = 0; i < sashes.length; i++) {
sashes[i].dispose();
sashes[i] = createSash();
}
layout(false);
}
@Override
public void setBackground (Color color) {
super.setBackground(color);
background = color;
for (int i = 0; i < sashes.length; i++) {
sashes[i].setBackground(background);
}
}
@Override
public void setForeground (Color color) {
super.setForeground(color);
foreground = color;
for (int i = 0; i < sashes.length; i++) {
sashes[i].setForeground(foreground);
}
}
@Override
public void setLayout (Layout layout) {
checkWidget();
return;
}
public void setMaximizedControl(Control control){
checkWidget();
if (control == null) {
if (maxControl != null) {
this.maxControl = null;
layout(false);
for (int i= 0; i < sashes.length; i++){
sashes[i].setVisible(true);
}
}
return;
}
for (int i= 0; i < sashes.length; i++){
sashes[i].setVisible(false);
}
maxControl = control;
layout(false);
}
public void setSashWidth(int width) {
checkWidget();
if (SASH_WIDTH == width) return;
SASH_WIDTH = width;
layout(false);
}
@Override
public void setToolTipText(String string) {
super.setToolTipText(string);
for (int i = 0; i < sashes.length; i++) {
sashes[i].setToolTipText(string);
}
}
public void setWeights(int[] weights) {
checkWidget();
Control[] cArray = getControls(false);
if (weights == null || weights.length != cArray.length) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
int total = 0;
for (int i = 0; i < weights.length; i++) {
if (weights[i] < 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
total += weights[i];
}
if (total == 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data == null || !(data instanceof SashFormData)) {
data = new SashFormData();
cArray[i].setLayoutData(data);
}
((SashFormData)data).weight = (((long)weights[i] << 16) + total - 1) / total;
}
layout(false);
}
public void setLengths(int[] lengths) {
checkWidget();
Control[] cArray = getControls(false);
if (lengths == null || lengths.length != cArray.length) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
int total = 0;
for (int i = 0; i < lengths.length; i++) {
if (lengths[i] < 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
total += lengths[i];
}
if (total == 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data == null || !(data instanceof SashFormData)) {
data = new SashFormData();
cArray[i].setLayoutData(data);
}
((SashFormData)data).length = lengths[i];
}
layout(false);
}
}
SashFormLayout.java:
class SashFormData {
long weight;
int length;
String getName () {
String string = getClass ().getName ();
int index = string.lastIndexOf ('.');
if (index == -1) return string;
return string.substring (index + 1, string.length ());
}
@Override
public String toString () {
return getName()+" {length="+length+", weight="+weight+"}"; //$NON-NLS-2$
}
}