Java SWT透明按钮/标签
我已经研究了好几天了。似乎大多数人都想把按钮放在透明的画布或外壳上。我需要在画布/组件上放置透明的可单击对象。在我的测试中,我发现如果我不尝试将对象放在画布上,它就永远不会显示 在最后一个项目中,应用程序将显示动画对象,其中包含许多我计划使用图像的控件 在这个例子中,我试图计算出我使用了Snipped195,它显示了一个旋转的圆环。我试图在圆环体上放置一个图像标签,这样当圆环体转动时,它将通过透明的标签区域显示出来。我已经设置了一个gif文件,它是一个红色加号,背景是透明的。我还学习了一些代码(不记得它是从哪里来的),这是paintControl方法的一部分,该方法查找透明像素并构建区域对象。区域对象显然正在做它需要做的事情来定义图像的去向。我是否需要以某种方式将区域应用于图像而不是画布 起初,当我尝试这样做时,我确实显示了图像。但是,在透明区域中,它显示为白色。在实现了paintControl代码之后,它至少正确地处理了透明区域。现在我需要得到要显示的实际图像内容 我构建了一个对象来处理图像标签。我称之为透明标签。它看起来像:Java SWT透明按钮/标签,java,swt,Java,Swt,我已经研究了好几天了。似乎大多数人都想把按钮放在透明的画布或外壳上。我需要在画布/组件上放置透明的可单击对象。在我的测试中,我发现如果我不尝试将对象放在画布上,它就永远不会显示 在最后一个项目中,应用程序将显示动画对象,其中包含许多我计划使用图像的控件 在这个例子中,我试图计算出我使用了Snipped195,它显示了一个旋转的圆环。我试图在圆环体上放置一个图像标签,这样当圆环体转动时,它将通过透明的标签区域显示出来。我已经设置了一个gif文件,它是一个红色加号,背景是透明的。我还学习了一些代码(
public class TransparentImageLabel extends Canvas {
private Image labelImage;
public TransparentImageLabel(Composite parent, Image image, int style) {
super(parent, style);
this.labelImage = image;
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
TransparentImageLabel.this.widgetDisposed(e);
}
});
addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
TransparentImageLabel.this.paintControl(e);
}
});
}
private void widgetDisposed(DisposeEvent e) {
}
private void paintControl(PaintEvent event) {
System.out.println("at paint control");
ImageData imgData = this.labelImage.getImageData();
Region region = new Region();
if (imgData.alphaData != null) {
Rectangle pixel = new Rectangle(0, 0, 1, 1);
for (int y = 0; y < imgData.height; y++) {
for (int x = 0; x < imgData.width; x++) {
if (imgData.getAlpha(x, y) == 255) {
pixel.x = imgData.x + x;
pixel.y = imgData.y + y;
region.add(pixel);
}
}
}
} else {
ImageData mask = imgData.getTransparencyMask();
Rectangle pixel = new Rectangle(0, 0, 1, 1);
for (int y = 0; y < mask.height; y++) {
for (int x = 0; x < mask.width; x++) {
if (mask.getPixel(x, y) != 0) {
pixel.x = imgData.x + x;
pixel.y = imgData.y + y;
region.add(pixel);
}
}
}
}
this.setRegion(region);
event.gc.drawImage(labelImage, this.getBounds().x, this.getBounds().y);
region.dispose();
}
}
public class Snippet195 {
private Image redPlus;
static void drawTorus(float r, float R, int nsides, int rings) {
float ringDelta = 2.0f * (float) Math.PI / rings;
float sideDelta = 2.0f * (float) Math.PI / nsides;
float theta = 0.0f, cosTheta = 1.0f, sinTheta = 0.0f;
for (int i = rings - 1; i >= 0; i--) {
float theta1 = theta + ringDelta;
float cosTheta1 = (float) Math.cos(theta1);
float sinTheta1 = (float) Math.sin(theta1);
GL11.glBegin(GL11.GL_QUAD_STRIP);
float phi = 0.0f;
for (int j = nsides; j >= 0; j--) {
phi += sideDelta;
float cosPhi = (float) Math.cos(phi);
float sinPhi = (float) Math.sin(phi);
float dist = R + r * cosPhi;
GL11.glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
GL11.glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
GL11.glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
GL11.glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
}
GL11.glEnd();
theta = theta1;
cosTheta = cosTheta1;
sinTheta = sinTheta1;
}
}
private Snippet195() {
final Display display = new Display();
Shell shell = new Shell(display, SWT.NO_REDRAW_RESIZE);
shell.setLayout(new FillLayout());
Composite comp = new Composite(shell, SWT.NONE);
comp.setLayout(new FillLayout());
GLData data = new GLData();
data.doubleBuffer = true;
redPlus = new Image(shell.getDisplay(), new ImageData(
Snippet237.class.getResourceAsStream("/red-plus.png")));
final GLCanvas canvas = new GLCanvas(comp, SWT.NONE, data);
canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.setAlpha(15);
e.gc.drawImage(Snippet195.this.redPlus, 0, 0);
}
});
canvas.setCurrent();
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
canvas.addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
Rectangle bounds = canvas.getBounds();
float fAspect = (float) bounds.width / (float) bounds.height;
canvas.setCurrent();
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glViewport(0, 0, bounds.width, bounds.height);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(45.0f, fAspect, 0.5f, 400.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
}
});
GL11.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GL11.glColor3f(1.0f, 0.0f, 0.0f);
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
GL11.glClearDepth(1.0);
GL11.glLineWidth(2);
GL11.glEnable(GL11.GL_DEPTH_TEST);
TransparentImageLabel redPlusLabel = new TransparentImageLabel(canvas,
redPlus, SWT.NONE);
redPlusLabel.setSize(48, 48);
redPlusLabel.setLocation(500, 200);
shell.setText("SWT/LWJGL Example");
shell.setSize(880, 720);
shell.open();
final Runnable run = new Runnable() {
int rot = 0;
public void run() {
if (!canvas.isDisposed()) {
canvas.setCurrent();
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT
| GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(.3f, .5f, .8f, 1.0f);
GL11.glLoadIdentity();
GL11.glTranslatef(0.0f, 0.0f, -10.0f);
float frot = rot;
GL11.glRotatef(0.15f * rot, 2.0f * frot, 10.0f * frot, 1.0f);
GL11.glRotatef(0.3f * rot, 3.0f * frot, 1.0f * frot, 1.0f);
rot++;
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
GL11.glColor3f(0.9f, 0.9f, 0.9f);
drawTorus(1, 1.9f + ((float) Math.sin((0.004f * frot))), 25, 75);
canvas.swapBuffers();
display.asyncExec(this);
}
}
};
canvas.addListener(SWT.Paint, new Listener() {
public void handleEvent(Event event) {
run.run();
}
});
display.asyncExec(run);
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
public static void main(String[] args) {
new Snippet195();
}
}
我必须靠近。定义为透明的图像区域将绘制为透明。但是我得到的只是一个白色的加号,而不是图像中的红色
问题出在您的
TransparentImageLabel#paintControl(..)
方法中。将最后第二行更正为以下内容:
event.gc.drawImage(labelImage,0,0);
因为您是在画布的上下文中绘制的,所以为位置指定的坐标应该是相对于该
画布的。您当前使用的是相对于其父级返回的画布的位置。能否提供您试图绘制到画布上的透明图像?这解决了问题。它在旋转的螺旋上工作良好。非常感谢你。因为它是从论坛上的建议中获得的,所以我仍然在学习代码是如何工作的。我用旋转的螺旋线测试了这个。但它将被用来浏览移动的地图。地图每秒重绘25次,使用OpenGL重新定位中心。透明按钮需要一个与贴图关联的重画事件,以便它可以在每次绘制贴图时重画。canvas.addPaintListener的用途是在每次重新绘制螺旋线时发出重新绘制按钮的信号。这是正确的吗?这段代码我读了很久了,所以我不太确定。但是你可以试试看。由于要添加的图像是一个单独的控件(GLCanvas的子控件),因此它可能不需要在每次绘制父控件时重新绘制。试试看,也让我知道。如果问题解决了,你可能会接受答案。