我知道很多人都遇到过这个问题,但我在网上找到的解决方案似乎并没有解决我的问题。我有一个有三个按钮的复合材料。我想要的是以下内容: 当我单击一个按钮时,我想要一些其他按钮变灰(setEnabled(false))并且一段时间后(在执行方法之后),我希望再次启用该按钮。
通过在父容器上调用layout()方法解决了许多此类问题,或者通过调用Display.getCurrent()来解决this very similar one。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()
方法并没有解决我的问题。
谢谢, EGE
答案 0 :(得分:3)
好的,我已经纠正了ginu的答案:
New Runnable()。run()确实没什么用,但想法是正确的:
你需要一个新的线程来完成你的工作。问题是,从那个线程你不能在按钮上调用setEnabled,因为这只能在SWT-Event线程中完成。
所以你需要另一个runnable来重置按钮。第二个runnable传递给Display.callAsync并在实际执行之前返回,但这并不重要。您还可以使用Display.callSync(Runnable),该调用将阻止您的调用线程,直到runnable返回。
在Eclipse中测试过,到目前为止看起来很不错。
编辑:顺便说一下,调用layout()或Display.update()不起作用的原因是你当前正在用你的工作阻塞SWT-Thread,所以对布局/更新的调用排队并且只执行当你离开事件处理程序时。永远不要阻止事件处理程序做长时间的工作。 :)
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();
}
}
}
}
答案 1 :(得分:0)
您的代码段似乎没有完整,但有关您的问题的一些事情会浮现在脑海中。您可以使用setEnabled,如下面的代码段所示。对于更高级的东西,你可以使用.exclude属性和setVisible来查看GridLayout和GridData。作为参考,SWT Snippets page非常棒。
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();
}
}
}
}
答案 2 :(得分: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();
}
}
}
}