【发布时间】:2018-03-20 08:01:46
【问题描述】:
我正在尝试使用 SWT 创建一个自定义滑块,但我得到了一个奇怪的结果,我希望我在这里遗漏了一些东西,我想要一个带有内部画布的 Composite,它的边距大约为 15上、左、右和下。 类似的东西:
所以我写了一个这样的主要内容:
Main.java
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class Main {
public static void main (String [] args) {
Display display = new Display ();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1,false));
shell.setSize(400,400);
CustomSlider slider= new CustomSlider(shell, SWT.NONE);
shell.pack();
shell.open ();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
}
还有扩展 Composite 的 customSlider 类:
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
public class CustomSlider extends Composite {
private Canvas progressBar;
private Rectangle progressBarRect;
private int knobSize=15;
private Point thisSize;
private boolean hover=false;
public CustomSlider(Composite arg0, int arg1) {
super(arg0, arg1);
thisSize= new Point(400, 50);
setSize(400, 50);
setBackground(arg0.getDisplay().getSystemColor(SWT.COLOR_MAGENTA));
GridLayout gl= new GridLayout(1,false);
setLayout(gl);
setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
progressBar = new Canvas(this, SWT.NONE);
GridLayout gl2= new GridLayout(1,false);
gl2.marginBottom=knobSize;
gl2.marginTop=knobSize;
gl2.marginLeft=knobSize;
gl2.marginRight=knobSize;
gl2.marginWidth=knobSize;
gl2.marginHeight=knobSize;
progressBar.setLayout(gl2);
GridData gd=new GridData(SWT.FILL, SWT.FILL, true, true);
progressBar.setLayoutData(gd);
progressBar.addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent arg0) {
Canvas canvasProgress=(Canvas)arg0.widget;
progressBarRect= canvasProgress.getBounds();
GC gc=arg0.gc;
gc.setForeground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_GREEN));
if (hover){
gc.setBackground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_RED));
}else{
gc.setBackground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_BLUE));
}
gc.fillRectangle(progressBarRect);
gc.drawRectangle(progressBarRect);
}
});
Listener listener = new Listener() {
public void handleEvent(Event event) {
System.out.println("---------------");
System.out.println("Canvas:"+((Canvas)event.widget).getBounds());
System.out.println("Composite:"+((Canvas)event.widget).getParent().getBounds());
System.out.println("Shell:"+((Canvas)event.widget).getParent().getParent().getBounds());
Display display=((Widget)event.widget).getDisplay();
switch (event.type) {
case SWT.MouseHover:
if (progressBarRect.contains(new Point(event.x, event.y))){
hover=true;
}else{
hover=false;
}
break;
case SWT.MouseDown:
break;
case SWT.MouseMove:
if (progressBarRect.contains(new Point(event.x, event.y))){
hover=true;
}else{
hover=false;
}
break;
case SWT.MouseEnter:
if (progressBarRect.contains(new Point(event.x, event.y))){
hover=true;
}else{
hover=false;
}
break;
case SWT.MouseExit:
if (progressBarRect.contains(new Point(event.x, event.y))){
System.out.println("progressBarRect:"+progressBarRect);
System.out.println("Point"+new Point(event.x, event.y));
System.out.println("HOVER!");
hover=true;
}else{
System.out.println("OUT!");
hover=false;
}
break;
case SWT.MouseUp:
break;
}
display.asyncExec(() -> progressBar.redraw());
}
};
progressBar.addListener(SWT.MouseDown, listener);
progressBar.addListener(SWT.MouseUp, listener);
progressBar.addListener(SWT.MouseMove, listener);
progressBar.addListener(SWT.MouseExit, listener);
progressBar.addListener(SWT.MouseEnter, listener);
progressBar.addListener(SWT.MouseHover, listener);
}
public Point getThisSize() {
return thisSize;
}
public void setThisSize(Point thisSize) {
this.thisSize = thisSize;
}
}
现在,第一件事是结果与我想要的不符,似乎没有考虑边距,或者最好只有两个(顶部和左侧):
其次,事件会导致意想不到的结果:MouseExit 事件表明我仍在画布上悬停,即使我不在合成中! :S
你能帮我理解这里发生了什么吗?
提前谢谢你...
编辑 按照 Greg 的建议,我将代码编辑如下:
主要:
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class Main {
public static void main (String [] args) {
Display display = new Display ();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1,false));
//shell.setSize(400,400);
CustomSlider2 slider= new CustomSlider2(shell, SWT.NONE);
shell.pack();
shell.open ();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
}
而自定义滑块变成了CustomSlider2:
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
public class CustomSlider2 extends Composite {
private Canvas progressBar;
private Rectangle progressBarRect;
private int knobSize=15;
private boolean hover=false;
public CustomSlider2(Composite arg0, int arg1) {
super(arg0, arg1);
setBackground(arg0.getDisplay().getSystemColor(SWT.COLOR_MAGENTA));
setLayout(new GridLayout(1,false));
progressBar = new Canvas(this, SWT.CENTER);
final GridData gd=new GridData(SWT.FILL, SWT.FILL, true, true);
gd.widthHint = 100;
gd.heightHint = 50;
GridLayout gl= new GridLayout();
gl.numColumns=1;
gl.marginWidth=knobSize;
gl.marginHeight=knobSize;
progressBar.setLayoutData(gd);
progressBar.setLayout(gl);
progressBar.addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent arg0) {
Canvas canvasProgress=(Canvas)arg0.widget;
Rectangle clientArea= canvasProgress.getBounds();
progressBarRect=new Rectangle(clientArea.x, clientArea.y, clientArea.x + clientArea.width - 1, clientArea.y + clientArea.height - 1);
GC gc=arg0.gc;
gc.setForeground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_GREEN));
if (hover){
gc.setBackground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_RED));
}else{
gc.setBackground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_BLUE));
}
gc.fillRectangle(progressBarRect);
gc.drawRectangle(progressBarRect);
}
});
Listener listener = new Listener() {
public void handleEvent(Event event) {
System.out.println("---------------");
System.out.println("Canvas:"+((Canvas)event.widget).getBounds());
System.out.println("Composite:"+((Canvas)event.widget).getParent().getBounds());
System.out.println("Shell:"+((Canvas)event.widget).getParent().getParent().getBounds());
Display display=((Widget)event.widget).getDisplay();
switch (event.type) {
case SWT.MouseEnter:
hover=true;
break;
case SWT.MouseExit:
hover=false;
break;
}
display.asyncExec(() -> progressBar.redraw());
}
};
progressBar.addListener(SWT.MouseExit, listener);
progressBar.addListener(SWT.MouseEnter, listener);
}
}
所以事件问题似乎已解决,但布局问题没有解决...我仍然没有画布周围的边距...
【问题讨论】:
-
不要将
setSize(或setBounds)与布局混合 - 布局将覆盖大小。 -
嗨,格雷格,但我没有混合它,我为 Composite (CustomSlider) 使用了 set size 并让 SWT 决定 Canvas 的边界,但我告诉 SWT 为 Canvas 使用网格布局n 为了周围有边距...有什么问题?
-
我已经做了一个测试,即使在 Composite 上注释掉 setSize 结果也没有改变,边距仅适用于顶部和左侧... :(
-
您的外壳有一个 GridLayout,它将覆盖 CustomSlider 的大小。我并不是说这是这里唯一的问题。
-
嗨 Greg,因为没有显示没有布局的 Composite,这意味着永远不应该使用 setSize?这对我来说听起来很奇怪......对不起这个愚蠢的问题,但我正在努力学习......