【问题标题】:Why do newly created elements in a Java SWT Selection listener not get displayed/trigger a paint event?为什么 Java SWT 选择侦听器中新创建的元素不会显示/触发绘制事件?
【发布时间】:2026-02-06 11:55:01
【问题描述】:

我在使用 SWT(标准小部件工具包)和重绘时遇到了问题。基本上我希望在单击按钮时发生一些事情,例如出现的新元素。为简单起见,此处为文本。

但是,当我单击按钮时,没有任何反应,没有元素出现,也没有触发 PaintEvent。当我调整窗口大小时,突然所有元素都在那里(因为这会触发paintEvent/redrawing)。

文档和博客文章告诉我,每当需要重绘某些东西时,都会触发绘制事件。我认为向应用程序添加新元素会属于该类别。

所以问题是:我在这里做错了吗?我应该手动调用 layout()/redraw() 来触发重绘吗?这对我来说似乎很乏味,据我了解,大多数情况下 SWT 会为我处理。

哦,我正在使用 SWT 4.2.2 运行 Linux x64。但是我们几乎可以在任何平台上(以及旧的 SWT 3.7)上使用它。

下面是我的小示例代码:

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;

public class MainExample {

    public static void createText(Shell shell) {
      Text text = new Text(shell, SWT.SINGLE);
      text.setText("here is some fancy text");
    }

    public static void main (String [] args) {
        Display display = new Display ();
        Shell shell = new Shell (display);
        Button button = new Button(shell, SWT.PUSH);
        button.setText("I am a button");

        button.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                System.out.println("Button Clicked");
                // Why do these texts not show up and not trigger a Paint Event?
                createText(e.display.getActiveShell());
            }
        });

        createText(shell);
        shell.setLayout (new RowLayout());
        shell.addPaintListener(new PaintListener() {
            public void paintControl(PaintEvent e) {
                // just triggered in the beginning and with resizes
                System.out.println("Hooray we got a Paint event");
            }
        });
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }

}

请记住,这不仅仅是为了让该示例正常工作。对于一个更大的项目来说,这是一个简单版本的问题:-)

非常感谢任何帮助!

【问题讨论】:

    标签: java events user-interface swt paint


    【解决方案1】:

    如果你使用布局,你应该在添加一个新的子元素到复合后调用 Composite.layout()(或 layout(true))。 在调用 layout() 之前,布局不知道(所以不要放置小部件)。

    顺便说一句,如果您调整外壳(复合)的大小,布局会自动使其内部缓存无效并检查所有子级,放置它们。这就是为什么在调整外壳大小后会出现新创建的文本的原因。

    【讨论】:

    • 我担心这会是答案.. 非常感谢:-)
    最近更新 更多