SWT 调整大小错误

4

我一直在使用SWT,发现了一个问题:

当选择和取消选择复选框并最大化窗口时,即使第一个按钮的图标为空,它也会被设置。同时,按钮上的文本布局可能不正确。

重现错误的步骤如下:

  1. 选择复选框1
  2. 取消选择复选框1
  3. 选择复选框3
  4. 最大化窗口

复选框1的图标应该是空的,但实际上显示了“叉号”图标。

  public static void main(String[] args) {
       final Display d = new Display();
       Shell s = new Shell(d);
       s.setLayout(new GridLayout(2, false));
       s.setSize(500, 500);

       new Label(s, SWT.NONE).setText("C");
       final Button c = new Button(s, SWT.CHECK);

       new Label(s, SWT.NONE).setText("L1");
       final Button b = new Button(s, SWT.PUSH | SWT.FLAT);
       b.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
       b.setText("Button 1");
       b.setEnabled(false);

       new Label(s, SWT.NONE).setText("C2");
       final Button c2 = new Button(s, SWT.CHECK);

       new Label(s, SWT.NONE).setText("L2");
       final Button b2 = new Button(s, SWT.PUSH | SWT.FLAT);
       b2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
       b2.setImage(null);
       b2.setText("Button 2");
       b2.setEnabled(false);

       new Label(s, SWT.NONE).setText("C3");
       final Button c3 = new Button(s, SWT.CHECK);

       new Label(s, SWT.NONE).setText("L3");
       final Button b3 = new Button(s, SWT.PUSH | SWT.FLAT);
       b3.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
       b3.setText("Button 3");
       b3.setEnabled(false);

       c.addSelectionListener(new SelectionAdapter() {
           @Override
           public void widgetSelected(SelectionEvent e) {
               if (!b.isEnabled()) {
                   b.setImage(d.getSystemImage(SWT.ICON_ERROR));
                   b.setEnabled(true);
               } else {
                   b.setImage(null);
                   b.setEnabled(false);
               }
           }
       });

       c2.addSelectionListener(new SelectionAdapter() {
           @Override
           public void widgetSelected(SelectionEvent e) {
               if (!b2.isEnabled()) {
                   b2.setImage(d.getSystemImage(SWT.ICON_ERROR));
                   b2.setEnabled(true);
               } else {
                   b2.setImage(null);
                   b2.setEnabled(false);
               }
           }
       });

       c3.addSelectionListener(new SelectionAdapter() {
           @Override
           public void widgetSelected(SelectionEvent e) {
               if (!b3.isEnabled()) {
                   b3.setImage(d.getSystemImage(SWT.ICON_ERROR));
                   b3.setEnabled(true);
               } else {
                   b3.setImage(null);
                   b3.setEnabled(false);
               }
           }
       });

       s.open();
       while (!s.isDisposed()) {
           if (!d.readAndDispatch())
               d.sleep();
       }
       d.dispose();
   }

无法在macOS 10.12.6上使用来自Eclipse Oxygen的SWT进行再现。 - greg-449
我正在Windows 7上使用Eclipse 3.4。 - Michael
Eclipse 3.4已经过时了,很可能自那以后已经修复了这个问题。尝试使用这里的SWT jars。 - greg-449
我能够在Windows 10上使用SWT 4.7进行复现。 - avojak
1
在Windows 10 SWT 4.5上重现。你发现了一个非常奇怪的问题。最好在这里发布一个错误报告。 - Baz
1个回答

1
这并不是理想的情况,但如果你需要解决问题,可以尝试包装 Button 并使用 StackLayout 来在可用的 Button 和不可用的 Button 之间切换。这样就不会添加/移除 Image。这也修复了布局问题,因为实际的 Button 实例没有改变状态。

例如:
public static class MyButton {

    private final Button buttonEnabled;
    private final Button buttonDisabled;

    private final Composite stackComposite;
    private final StackLayout stackLayout;

    public MyButton(final Composite parent, final String text) {
        stackComposite = new Composite(parent, SWT.NONE);
        stackLayout = new StackLayout();
        stackComposite.setLayout(stackLayout);
        stackComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

        buttonEnabled = createButton(stackComposite, text, true);
        buttonDisabled = createButton(stackComposite, text, false);

        stackLayout.topControl = buttonEnabled;
    }

    public void setEnabled(final boolean enabled) {
        stackLayout.topControl = enabled ? buttonEnabled : buttonDisabled;
        stackComposite.layout();
    }

    public boolean isEnabled() {
        return stackLayout.topControl.equals(buttonEnabled) ? true : false;
    }

    private static Button createButton(final Composite parent,
            final String text, final boolean enabled) {
        final Button button = new Button(parent, SWT.PUSH | SWT.FLAT);
        button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        button.setText(text);
        button.setEnabled(enabled);
        if (enabled) {
            button.setImage(parent.getDisplay().getSystemImage(SWT.ICON_ERROR));
        }
        return button;
    }

}

再次强调,这并不是理想的解决方法,但您可以随时向MyButton类添加方法(addListener(...)等),以调用已启用的Button上的方法,这仅是实现细节。

main方法的更改:

public static void main(final String[] args) {

    // ...

    new Label(s, SWT.NONE).setText("C");
    final Button c = new Button(s, SWT.CHECK);

    new Label(s, SWT.NONE).setText("L1");
    final MyButton b = new MyButton(s, "Button 1");

    // ...

    c.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(final SelectionEvent e) {
            b.setEnabled(!b.isEnabled());
        }
    });

    // ...

}

结果: (请注意,我只更改了第一个按钮)

enter image description here enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接