3

多くの人がこの問題を経験していることは知っていますが、私がオンラインで見つけた解決策は私のものを解決していないようです. 3 つのボタンを持つコンポジットがあります。私が欲しいのは次のとおりです: 1 つのボタンをクリックすると、他のボタンをグレー表示 ( setEnabled(false) ) し、しばらくすると (メソッドの実行後)、ボタンを再び有効にしたいと考えています。

このような問題の多くは、親コンテナーで layout() メソッドを呼び出すことによって解決されます。または、これと非常によく似た問題は、Display.getCurrent().update(); を呼び出すことによって解決されます。

簡単に言えば、私のコードは次のように要約できます。


import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;


public class app1 {

    protected Shell shell;

    /**
     * Launch the application.
     * @param args
     */
    public static void main(String[] args) {
        try {
            app1 window = new app1();
            window.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Open the window.
     */
    public void open() {
        Display display = Display.getDefault();
        createContents();
        shell.open();
        shell.layout();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    /**
     * Create contents of the window.
     */
    Button button1 , button2 , button3;
    Label label;
    protected void createContents() {
        shell = new Shell();
        shell.setSize(450, 300);
        shell.setText("SWT Application");
        shell.setLayout(new GridLayout(1,false));
        {
            final Composite composite = new Composite(shell, SWT.NONE);
            composite.setLayout(new GridLayout(3,false));
            GridData gd_composite = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
            gd_composite.grabExcessHorizontalSpace = true;          
            gd_composite.horizontalSpan = 10;   //?
            gd_composite.verticalIndent = 5;
            composite.setLayoutData(gd_composite);
            GridData gd_button;

            {
                button1 = new Button(composite, SWT.NONE);
                button1.setText("Button 1");
                gd_button = new GridData(SWT.FILL, GridData.BEGINNING, false, false);
                gd_button.horizontalSpan = 1;
                button1.setLayoutData(gd_button);
                button1.addSelectionListener(new SelectionListener(){
                    public void widgetSelected(SelectionEvent e){
                        try{
                        button2.setEnabled(false);
                        button2.redraw();
                        button2.update();

                        //composite.redraw();
                        //composite.update();
                        //composite.layout();

                        shell.redraw();
                        shell.update();
                        shell.layout();                     
                        Display.getCurrent().update();
                        }   catch   (Exception e2)  {
                            System.err.println("exception e : " + e2.toString());
                        }

                        System.out.println("basla");


                        try {
                            System.out.println("sleep1");
                            Thread.sleep(100);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }   catch (Throwable th)    {
                            System.err.println("th: " + th.toString());
                        }
                        try {
                            System.out.println("sleep2");
                            Thread.sleep(100);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }   catch (Throwable th)    {
                            System.err.println("th: " + th.toString());
                        }
                        try {
                            System.out.println("sleep3");
                            Thread.sleep(100);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }   catch (Throwable th)    {
                            System.err.println("th: " + th.toString());
                        }

                        for(int i=0 ; i < 10000 ; i++)
                        {
                            System.out.println(i);
                        }
                    }
                    public void widgetDefaultSelected(SelectionEvent e) {
                        System.err.println("widgetDefault !");
                    }
                });
            }
            {
                button2 = new Button(composite, SWT.NONE);
                button2.setText("Button 2");
                gd_button = new GridData(SWT.FILL, GridData.CENTER, false, false);
                gd_button.horizontalSpan = 1;
                button2.setLayoutData(gd_button);
                button2.addSelectionListener(new SelectionListener(){
                    public void widgetSelected(SelectionEvent e){
                        button1.setEnabled(false);
                        composite.layout();
                        for (int i=1; i<=100; i++) {
                             try {
                                  Thread.sleep(10);
                             } catch (Throwable th) {}
                            label.setText(i + " %");
                            label.update();
                        }
                    }
                    public void widgetDefaultSelected(SelectionEvent e) {}
                });
            }

            {
                label = new Label(composite , SWT.NONE);
                label.setText("0 %");
                label.update();
            }
        }
    }
}

何が起こるかというと、widgetSelected() メソッドの最後に到達するとボタンが無効になります。ただし、ラベルは問題なく頻繁に更新されます (label.update() メソッドが存在しない場合でも)。

追加情報: たとえば、ボタンを無効にしてから Thread.sleep() を配置してからボタンを有効にします。最初にスリープし、すぐにボタンを無効にしてから有効にします。したがって、そのようなペイント要求はすべてキューに入れられ、実行の最後に処理されると思います。

役立つ情報:表示が変更された直後に MessageBox を作成して表示すると、表示が変更されることに気付きました。したがって、widgetSelected メソッドで次の変更を行うと:


button2.setEnabled(false)
MessageBox mBox = new MessageBox(Display.getCurrent().getActiveShell(), SWT.ICON_INFORMATION | SWT.OK);
mBox.setText("Information");
mBox.setMessage("Buttons updated!");
mBox.open();

widgetSelected() メソッドが呼び出されるとすぐに、ボタンはグレー表示されます。これは、私の解決策が Display.getCurrent() メソッド内にあると信じさせます。しかし、私は試しました

Display.getCurrent().getActiveShell().redraw()
Display.getCurrent().getActiveShell().update()
Display.getCurrent().getActiveShell().layout()

メソッドとそれらは私の問題を解決しませんでした。

ありがとう、エゲ

4

3 に答える 3

3

わかりました、私はginuからの答えを修正しました:

New Runnable().run() は実際には何もしませんが、考え方は正しいです:

作業を行うには新しいスレッドが必要です。問題は、そのスレッドからボタンで setEnabled を呼び出すことができないことです。これは、SWT イベント スレッド内からしか実行できないためです。

したがって、ボタンをリセットするには別のランナブルが必要です。2 番目の runnable は Display.callAsync に渡され、実際に実行される前に戻りますが、ここでは問題ではありません。Display.callSync( Runnable ) を使用することもできます。その呼び出しは、ランナブルが戻るまで呼び出しスレッドをブロックします。

Eclipseでテストしましたが、これまでのところ良さそうです。

編集: ところで、layout() または Display.update() の呼び出しが機能しなかった理由は、現在作業で SWT スレッドをブロックしているためです。そのため、layout/update の呼び出しはキューに入れられ、終了したときにのみ実行されます。イベント ハンドラ。長い作業を行うためにイベント ハンドラーをブロックしないでください。:)

package test;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Test {

public static void main(final String[] args) {
    final Display display = new Display();
    final Shell shell = new Shell(display);
    shell.setLayout(new GridLayout(3, false));
    final Button button1 = new Button(shell, SWT.PUSH);
    button1.setText("Click");
    final Button button2 = new Button(shell, SWT.PUSH);
    button2.setText("Me");
    final Button button3 = new Button(shell, SWT.PUSH);
    button3.setText("Dude");

    button1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    button2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    button3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));

    button2.setEnabled(false);
    button3.setEnabled(false);

    button1.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(final SelectionEvent e) {
            button1.setEnabled(false);
            button2.setEnabled(true);
            button3.setEnabled(true);

            new Thread( new Runnable() {
                public void run() {
                    try {
                        // Do your operation here.
                        //
                        // Dummy sleep performed here instead.
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    shell.getDisplay().asyncExec( new Runnable() {
                        public void run() {
                          button1.setEnabled(true);
                          button2.setEnabled(false);
                          button3.setEnabled(false);
                        }
                    });
                }
            } ).start();
        }
    });

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

}

}

于 2009-08-25T21:02:00.133 に答える
0

ボタンの有効化/無効化に問題があるのか​​、実行フローの間に遅延を入れるのに問題があるのか​​、私にはよくわかりません。

上記の両方の操作を実行するように、上記のJaredのコードを変更しました。これを見て、これがあなたが探していたものであるかどうか私に知らせてください。

乾杯。:-)

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class app1 {

    public static void main(final String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(3, false));
        final Button button1 = new Button(shell, SWT.PUSH);
        button1.setText("Click");
        final Button button2 = new Button(shell, SWT.PUSH);
        button2.setText("Me");
        final Button button3 = new Button(shell, SWT.PUSH);
        button3.setText("Dude");

        button1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));

        button2.setEnabled(false);
        button3.setEnabled(false);

        button1.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                button1.setEnabled(false);
                button2.setEnabled(true);
                button3.setEnabled(true);

                new Runnable() {
                    public void run() {

                        try {
                            // Do your operation here.
                            //
                            // Dummy sleep performed here instead.
                            Thread.sleep(1000);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }

                    }
                }.run();

                button1.setEnabled(true);
                button2.setEnabled(false);
                button3.setEnabled(false);
            }
        });

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

    }
}
于 2009-08-24T08:53:40.143 に答える
0

スニペットは完全ではないようですが、問題に関していくつかのことが頭に浮かびました。以下のスニペットに示すように、おそらく setEnabled を使用できます。さらに高度なことについては、setVisible と組み合わせて .exclude プロパティを使用して GridLayout と GridData を調べることができます。参考までに、SWT スニペットのページは非常に優れています。

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class App2 {

    public static void main(final String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(3, false));
        final Button button1 = new Button(shell, SWT.PUSH);
        button1.setText("Click");
        final Button button2 = new Button(shell, SWT.PUSH);
        button2.setText("Me");
        final Button button3 = new Button(shell, SWT.PUSH);
        button3.setText("Dude");

        button1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button2.setEnabled(false);
        button3.setEnabled(false);

        button1.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                button1.setEnabled(false);
                button2.setEnabled(true);
                button3.setEnabled(false);
            }
        });

        button2.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                button1.setEnabled(false);
                button2.setEnabled(false);
                button3.setEnabled(true);
            }
        });

        button3.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                button1.setEnabled(true);
                button2.setEnabled(false);
                button3.setEnabled(false);
            }
        });

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

    }
}
于 2009-08-13T19:25:24.070 に答える