SWT ExpandListener executes before collapse occurs on Linux

后端 未结 2 1080
死守一世寂寞
死守一世寂寞 2021-01-15 10:16

This is a simple executable snippet that shows the issue.

When using the ExpandBar the desired outcome is to resize the window when there is a collapse or expand.

相关标签:
2条回答
  • 2021-01-15 10:28

    This is an old post but I recently had this problem, and found this solution helphul.

    However, I find that it is only necessary to call shell.pack() from another thread (via syncExec of course). I never have to go through loop. So I ctreated this little subroutine:

    private void async_shell_pack(final Display display, final ExpandBar bar) {
        new Thread(new Runnable(){
             public void run(){
                display.syncExec(new Runnable() {
                    public void run() {
                                bar.getShell().pack(true);
                            }
                        });
                }}).start();
            }
    

    This seems to work fine. For my purposes, better still, was to simply grow the height of the shell by the height of the expanded item using the following listener.

    public void itemExpanded(ExpandEvent e) {
            if (e.item instanceof ExpandItem){
                    ExpandItem item = (ExpandItem)e.item;
                    shell.setSize(shell.getSize().x, shell.getSize().y+item.getHeight());
                } else {
                    System.out.println("Boom");
                }
            }
    

    This means no messing about with threads.

    0 讨论(0)
  • 2021-01-15 10:44

    I am unhappy with this solution but it works.

    Definitely a XXX solution

    Use XXX in a comment to flag something that is bogus but works. Use FIXME to flag something that is bogus and broken. - java.sun.com

    without further ado

    import org.eclipse.swt.*;
    import org.eclipse.swt.layout.*;
    import org.eclipse.swt.widgets.*;
    import org.eclipse.swt.events.ExpandEvent;
    import org.eclipse.swt.events.ExpandListener;
    
    public class ExpandBarExample {
        public static void main(String[] args) {
            Shell shell = new Shell(SWT.DIALOG_TRIM | SWT.MIN
                    | SWT.APPLICATION_MODAL);
            shell.setLayout(new FormLayout());
            shell.setText("Expand Bar");
            final ExpandBar bar = new ExpandBar(shell, SWT.NONE);
            FormData fd = new FormData();
            fd.top = new FormAttachment(0);
            fd.left = new FormAttachment(0);
            fd.right = new FormAttachment(100);
            fd.bottom = new FormAttachment(100);
            bar.setLayoutData(fd);
    
            bar.addExpandListener(new ExpandListener() {
    
                private void resize(final ExpandEvent event, final boolean expand){
    
                    final Display display = Display.getCurrent();
    
                    new Thread(new Runnable() {
                        public void run() {
    
                            final int[] orgSize = new int[1];
                            final int[] currentSize = new int[1];
    
                            final Object lock = new Object();
    
                            if (display.isDisposed() || bar.isDisposed()){
                                return;
                            }
    
                            display.syncExec(new Runnable() {
                                public void run() {
                                    if (bar.isDisposed() || bar.getShell().isDisposed()){
                                        return;
                                    }
    
                                    synchronized(lock){
                                        bar.getShell().pack(true);
                                        orgSize[0] = bar.getShell().getSize().y;
                                        currentSize[0] = orgSize[0];
                                    }
                                }
                            });     
    
                            while (currentSize[0] == orgSize[0]){
                                if (display.isDisposed() || bar.isDisposed()){
                                    return;
                                }
    
                                display.syncExec(new Runnable() {
                                    public void run() {
    
                                        synchronized(lock){
                                            if (bar.isDisposed() || bar.getShell().isDisposed()){
                                                return;
                                            }
    
                                            currentSize[0] = bar.getShell().getSize().y;
    
                                            if (currentSize[0] != orgSize[0]){
                                                return;
                                            }
                                            else{
                                                bar.getShell().layout(true);
                                                bar.getShell().pack(true);
                                            }
                                        }
                                    }
                                });                             
                            }
                        }
                    }).start();
            }
    
            public void itemCollapsed(ExpandEvent event) {
                resize(event, false);
            }
    
            public void itemExpanded(ExpandEvent event) {        
                resize(event, true);
            }
    
            });
    
            Composite composite = new Composite(bar, SWT.NONE);
            fd = new FormData();
            fd.left = new FormAttachment(0);
            fd.right = new FormAttachment(100);
            composite.setLayoutData(fd);
    
            FormLayout layout = new FormLayout();
            layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom = 8;
    
            composite.setLayout(layout);
            Label label = new Label(composite, SWT.NONE);
            label.setText("This is Bar 1");
            ExpandItem item1 = new ExpandItem(bar, SWT.NONE, 0);
            item1.setText("Bar 1");
            item1.setHeight(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
            item1.setControl(composite);
            item1.setExpanded(true);
    
            composite = new Composite(bar, SWT.NONE);
            fd = new FormData();
            fd.left = new FormAttachment(0);
            fd.right = new FormAttachment(100);
            composite.setLayoutData(fd);
    
            layout = new FormLayout();
            layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom = 8;
            composite.setLayout(layout);
            label = new Label(composite, SWT.NONE);
            label.setText("This is Bar2");
            ExpandItem item2 = new ExpandItem(bar, SWT.NONE, 1);
            item2.setText("Bar 2");
            item2.setHeight(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
            item2.setControl(composite);
            item2.setExpanded(true);
    
            composite = new Composite(bar, SWT.NONE);
            fd = new FormData();
            fd.left = new FormAttachment(0);
            fd.right = new FormAttachment(100);
            composite.setLayoutData(fd);
    
            layout = new FormLayout();
            layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom = 8;
            composite.setLayout(layout);
            label = new Label(composite, SWT.NONE);
            label.setText("This is Bar3");
            ExpandItem item3 = new ExpandItem(bar, SWT.NONE, 2);
            item3.setText("Bar 3");
            item3.setHeight(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
            item3.setControl(composite);
            item3.setExpanded(true);
    
            bar.setSpacing(6);
            shell.pack();
            shell.open();
            Display display = shell.getDisplay();
    
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
            display.dispose();
        }
    
    }
    

    If anyone wants to know what this is doing and doesn't want to look at the code.

    Basically the ExpandListener looks at the original height of the shell, and issues syncExec's to pack() the shell until the shell actually changes size. A very busy waiting approach.

    0 讨论(0)
提交回复
热议问题