I am designing the close window functionality for my desktop application. A high level explanation of the functionality is listed:
If I click the Exit menuItem, it prompts a ConfirmBox the user to confirm whether he wants to save or not before closing the application.
If the user click on the CloseButton on the window to force close the window (i.e. setOnCloseRequest function), the Exit menuItem event is fire off, which brings the user to case (1) again.
Within my ConfirmBoxcode, I have bind ENTER key to save things, N key to not save things and ESCAPE key to close confirmBox.
I have also set accelerator for the Exit menuItem (METAKEY + E).
Everything works fine. However, there is a minor bug if I follow this special sequence of steps. Whenever I use the accelerator for the Exit menuItem (i.e. METAKEY + E) and then I press either one of the 3 keys(ENTER, ESCAPE, N), the confirmBox closes but it pops up again.
I am wondering why is this happening only in this very special case?
public class ConfirmBox {
// answer[0] determines the need to Save
// answer[1] determines whether to close the application or not
private static boolean[] answer = new boolean[]{false,false};
private static Stage window;
public static boolean[] displayWarning(String title, String message){
window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(title);
window.setMinWidth(300);
Label label = new Label();
label.setText(message);
Button yesButton = new Button("Yes");
Button noButton = new Button("No");
// needToSave = true, close Application = true and close this confirmbox
yesButton.setOnAction(ey ->{
answer[0] = true;
answer[1] = true;
window.close();
});
// needToSave = false, close Application = true and close this confirmbox
noButton.setOnAction(en -> {
answer[0] = false;
answer[1] = true;
window.close();
});
// needToSave = false, close Application = false and close this confirmbox
window.setOnCloseRequest(e -> {
answer[0] = false;
answer[1] = false;
closeConfirmBox();
});
// key binding
window.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
if ( e.getCode() == KeyCode.N){
noButton.fire();
e.consume();
}
});
// bind enter key to yesButton
window.addEventHandler(KeyEvent.KEY_PRESSED, ev -> {
if (ev.getCode() == KeyCode.ENTER ){
yesButton.fire();
ev.consume();
}
});
window.addEventFilter(KeyEvent.KEY_PRESSED, ev ->{
if(ev.getCode()==KeyCode.ESCAPE){
ev.consume();
answer[0] = false;
answer[1] = false;
closeConfirmBox();
}
});
VBox layout = new VBox(20);
layout.setPadding(new Insets(20,5,20,5));
HBox bottomLayout = new HBox(50);
bottomLayout.setPadding(new Insets(20,5,20,5));
bottomLayout.getChildren().addAll(yesButton,noButton);
bottomLayout.setAlignment(Pos.CENTER);
layout.getChildren().addAll(label,bottomLayout);
layout.setAlignment(Pos.CENTER);
Scene scene = new Scene(layout);
window.setScene(scene);
window.showAndWait();
return answer;
}
public static void closeConfirmBox(){
window.close();
}
}
Within my controller class, this is how I designed my MenuItem menuItemExit.
menuItemExit.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e){
//System.out.println("set stage" + primaryStage);
boolean[] answer;
boolean needToSave = false;
boolean closeApplication = false;
if(saved.get() == false){
answer = ConfirmBox.displayWarning("Warning", "Do you want to save your stuff?");
needToSave = answer[0];
closeApplication = answer[1];
}
if(needToSave == true){
menuItemSave.fire();
}
if(closeApplication== true){
Platform.runLater(new Runnable() {
public void run() {
close();
}
});
}
}
});
primaryStage.setOnCloseRequest(e -> {
e.consume();
menuItemExit.fire();
});
menuItemExit.setAccelerator(new KeyCodeCombination(KeyCode.E, KeyCombination.META_DOWN));
public void close(){
this.primaryStage.close();
}
Related
I would like to run a method that would close a pop up window when an answer is selected or the window is closed manually and then return the value selected (a boolean). Unfortunately, I do not know how I would retreive the data because I initially call the method that displays the query, not the close method.
I have tried many different things but when I try to use a close method I am unable to retrieve the data returned from it. Otherwise, the data returns before the user is able to mutate it. Neither result achieves my goal
This is my method that creates the box. I currently just close the window instead of closing via an alternate closing method.
public class ConfirmBox
{
static boolean answer;
public static boolean display(String title, String question) {
Stage window = new Stage();
//Block events to other windows
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(title);
window.setMinWidth(250);
//LabelQ
Label label = new Label();
label.setText(question);
//YesBox
Button yesB= new Button("Yes");
yesB.getStyleClass().add("button-green");
yesB.setOnAction(e -> {
answer=true;
window.close();
});
//NoBox
Button noB= new Button("No");
noB.getStyleClass().add("button-red");
yesB.setOnAction(e -> {
answer=false;
window.close();
});
window.setOnCloseRequest(e ->{
e.consume();
window.close();
});
VBox layout = new VBox(10);
layout.getChildren().addAll(label, yesB, noB);
layout.setAlignment(Pos.CENTER);
//Display window and wait for it to be closed before returning
Scene scene = new Scene(layout, 800, 200);
scene.getStylesheets().add("styles.css");
window.setScene(scene);
window.showAndWait();
return answer;
}
}
This is my method that runs everything thus far.
public class Main extends Application
{
Stage window;
String gender;
String name;
public static void main (String[] args){
launch (args);
}
public void start(Stage primaryStage) throws Exception{
window= primaryStage;
window.setTitle("Pokemon Gray");
GridPane grid= new GridPane();
grid.setPadding(new Insets(10, 10, 10, 10));
grid.setVgap(8);
grid.setHgap(10);
// Name Label
Label nameLabel= new Label("UserName");
GridPane.setConstraints(nameLabel,0, 0);
//Name input
TextField nameInput = new TextField();
GridPane.setConstraints(nameInput,1, 0);
//GenderLabel
Label genderLabel= new Label("Gender");
GridPane.setConstraints(genderLabel,0, 1);
//Gender Boy
Button boySelect= new Button("Boy");
boySelect.getStyleClass().add("button-blue");
GridPane.setConstraints(boySelect, 1, 1);
boySelect.setOnAction(e-> gender="Male");
//Gender Girl
Button girlSelect= new Button("Girl");
girlSelect.getStyleClass().add("button-red");
GridPane.setConstraints(girlSelect, 2, 1);
girlSelect.setOnAction(e-> gender="Female");
//Login
Button saveName= new Button("Save Name");
GridPane.setConstraints(saveName, 1, 2);
saveName.setOnAction( e -> {
boolean valid =verifyText(nameInput.getText());
if ((valid)&&((gender == "Male")||(gender=="Female"))){
String qStr= "Are you sure your name is "+nameInput.getText()+" and you are a "+gender+"?";
boolean confirmed= ConfirmBox.display("Confirmation", qStr );
if (confirmed == true){
name= nameInput.getText();
}
}
else{
ErrorBox.display("Error", "You must enter a name less than 20 characters long and a gender");
}
});
grid.getChildren().addAll(nameLabel, nameInput, genderLabel, boySelect, girlSelect, saveName);
Scene scene= new Scene(grid, 1000, 1000);
scene.getStylesheets().add("styles.css");
window.setScene(scene);
window.show();
}
public boolean verifyText(String text){
boolean valid;
if ((text.length() > 0) && (text.length() <= 20)){
valid= true;
}
else{
valid=false;
}
return valid;
}
}
I want to be able to run a seperate method that closes it and returns the answer boolean in the ConfirmBox to the Main method. But currently it returns null because it returns immediately.
Edit: It should be noted I currently do not have a close method. I deleted my previous one because it caused many issues.
I think that you can't do that, you need to do another screen like:
If(button.getResult==yes){"charge yesscreen")else{"charge no screen"}
The controllers for differents screens can't interectionate with another screens, you only can call the differents screens from to a controller but you can't pass values with hims, try do something like this I work with javafx with this mentality all screens are independents and you only invoce the differents screens . you can do something like this:
class first screen{
is a girl?
is a charizar?
is a x)
if(isgirl && is a x...){
call screen x
}else if(ismen&& is a z..){
call screen z
}
{
In my javafx program is a popup which lets user press keys and then it sets label accordingly. My problem is with key combinations that are shortcuts for underlying OS for example if user presses Win+R then Run.exe starts but my program should just set the label to "Win+R". My question is how to stop keyevents from triggering OS shortcuts.
Here is the relevant code.
public void showInput() {
Set codes = new HashSet();
Stage inputWindow = new Stage();
GridPane pane = new GridPane();
Scene scene = new Scene(pane);
Label label = new Label("Here comes the pressed keys");
scene.setOnKeyPressed(e -> {
e.consume();
int code = e.getCode().ordinal();
if (label.getText().equals("Here comes the pressed keys")){
codes.add(code);
label.setText(String.valueOf(e.getCode().getName()));
} else if (!codes.contains(code)){
codes.add(code);
label.setText(label.getText() + "+" + e.getCode().getName());
}
});
scene.setOnKeyReleased(e -> {
e.consume();
inputWindow.close();
});
pane.add(label, 0, 0);
inputWindow.setScene(scene);
inputWindow.show();
}
I tried e.consume() but it did not help.
It's possible with JNA, but is a bad idea. Don't intercept well-known key combinations.
Nevertheless, below is a working example. It basically uses the SetWindowsHookEx Win32 API and then blocks the Win+R key combination in the hook callback.
import com.sun.jna.platform.win32.*;
public class Test {
public static User32.HHOOK hHook;
public static User32.LowLevelKeyboardProc lpfn;
public static void main(String[] args) throws Exception {
WinDef.HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
lpfn = new User32.LowLevelKeyboardProc() {
boolean winKey = false;
public WinDef.LRESULT callback(int nCode, WinDef.WPARAM wParam, WinUser.KBDLLHOOKSTRUCT lParam) {
if (lParam.vkCode == 0x5B)
winKey = (lParam.flags & 0x80) == 0;
if (lParam.flags == 0 && lParam.vkCode == 0x52 && winKey) {
System.out.println("Win-R pressed");
return new WinDef.LRESULT(-1);
}
return User32.INSTANCE.CallNextHookEx(hHook, nCode, wParam, lParam.getPointer());
}
};
hHook = User32.INSTANCE.SetWindowsHookEx(User32.WH_KEYBOARD_LL, lpfn, hMod, 0);
if (hHook == null) {
System.out.println("Unable to set hook");
return;
}
User32.MSG msg = new User32.MSG();
while (User32.INSTANCE.GetMessage(msg, null, 0, 0) != 0) {
}
if (User32.INSTANCE.UnhookWindowsHookEx(hHook))
System.out.println("Unhooked");
}
}
(The needed JNA JAR dependency is net.java.dev.jna : platform)
Not possible, Java layer is above OS layer meaning your code is handled by the JVM and the JVM is handled by the OS. So there is no way to "skip" the OS layer and send your commands directly to Java.
I need to react on a key + mouse event combination like:
Ctrl + Shift + R + left_mousebutton_clicked
But I can't figure out, how to handle the "left_mousebutton_clicked" only if the key combination of Ctrl + Shift + R occurs.
A solution like
if(MouseEvent.isControlDown())
will not work cause there may be different key combinations with any kind of the letters.
Any ideas?
You can use a container to store the currently pressed keys:
private final Set<KeyCode> pressedKeys = new HashSet<>();
You can attach listeners to the Scene of the control the you want to target with the mouse-click:
scene.setOnKeyPressed(e -> pressedKeys.add(e.getCode()));
scene.setOnKeyReleased(e -> pressedKeys.remove(e.getCode()));
While these listeners maintain the set, you can simply attach a listener on the target Node:
Label targetLabel = new Label("Target Label");
targetLabel.setOnMouseClicked(e -> {
if (e.getButton() == MouseButton.PRIMARY &&
pressedKeys.contains(KeyCode.R) &&
e.isShortcutDown() &&
e.isShiftDown())
System.out.println("handled!");
});
Example Application:
public class MouseClickExample extends Application {
private final Set<KeyCode> pressedKeys = new HashSet<>();
public static void main(String[] args) {
launch(args);
}
#Override public void start(Stage stage) {
VBox root = new VBox();
Scene scene = new Scene(root, 450, 250);
scene.setOnKeyPressed(e -> pressedKeys.add(e.getCode()));
scene.setOnKeyReleased(e -> pressedKeys.remove(e.getCode()));
Label targetLabel = new Label("Target Label");
targetLabel.setOnMouseClicked(e -> {
if (e.getButton() == MouseButton.PRIMARY && pressedKeys.contains(KeyCode.R) && e.isShortcutDown() && e.isShiftDown())
System.out.println("handled!");
});
root.getChildren().add(targetLabel);
stage.setScene(scene);
stage.show();
}
}
Note: The meta keys are also stored in the Set but they are not used by this example. The meta keys could be also checked in the set rather than using methods on the mouse-event.
Both ctrl and shift can be done the way you aproached it there. The left mouse key is the PrimaryButton
if(mouseEvent.isControlDown() && mouseEvent.isShiftDown && mouseEvent.isPrimaryKeyDown){
// Do your stuff here
}
And for the "non special" key (like r) I thnk you need to make a global boolean - and a seperate keyevent listener for it. So:
boolean rIsDown = false;
scene.setOnKeyPressed(e -> {
if(e.getCode() == KeyCode.R){
System.out.println("r was pressed");
//set your global boolean "rIsDown" to true
}
});
scene.setOnKeyReleased(e -> {
if(e.getCode() == KeyCode.R){
System.out.println("r was released");
//set it rIsDown back to false
}
});
Then use your it together with the other conditions...
if(mouseEvent.isControlDown() && mouseEvent.isShiftDown && rIsDown && mouseEvent.isPrimaryKeyDown){
// Do your stuff here
}
We are using a OTB Application called Teamcenter. I am writing a add on application that is invoked from a menu selection in the Teamcenter Application.
When they click the menu item, that executes a handler class and that creates the base dialog for my application.
It will Show Selected Component from Teamcenter on Open dialog .
Dialog has One text field with Button.
User go back to parent window and select item and then click button on dialog this will set selected item on opened dialog.
But When Dialog open and i go back to parent i.e OTB teamcenter application for selecting item it takes time it looks like it got hanged.
Note:
Text Button
List
text and button are adjacent field.
If user select 1200 parts and goto menu and select item then it will show popup and then click on parent window for single item selection,clicking on parent takes time
but if we have 200 parts and then go back and click on parent window it doesn't take much time
Can anyone please suggest how to improve time performance ?
// open( ) : First Call on Menu selection will call open() method
//setSourceBomLinesOnSessionInfo() :Call from Open method() to set Required selected item information in session required to be set on Dialog List component
// SetScope() :Set text data on button selection on opened dialog
// user will go on parent window and select item and then coming back on opened dialog and click button
public void open()
{
eQOTMLoggerManager.logger.debug("open 'OTM Compare' Dialog");
eQOTMSessionInfo.getInstance().clearCurrentSelection();
Shell prevShell = getOTMCompareDialog();
if (prevShell != null)
{
prevShell.setMinimized(false);
}else{
try{
//Set Source BomLine on OTM Dialog Window
bSetInputOnDialog = setSourceBomLinesOnSessionInfo();
if( bSetInputOnDialog )
{
initializeUIComponents();
mainDialogShell.open();
Display display = mainDialogShell.getDisplay();
while (!mainDialogShell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
mainDialogShell.dispose();
}
else if (mainDialogShell != null)
{
mainDialogShell.dispose();
}
eQOTMLoggerManager.logger.error("INFO:Exit initialize UI Components for OTM compare dialog.");
}
catch (Throwable th)
{
eQOTMLoggerManager.logger.error("Exception occurred while initializing UI Components for OTM compare dialog. Error: "+th.getMessage(),th);
}
}
}
//Initialize UI Component
private void initializeUIComponents() throws TCException
{
eQOTMLoggerManager.logger.error("INFO:In initialize UI Components for OTM compare dialog !!!");
mainDialogShell = new Shell(this.m_parentShell, SWT.DIALOG_TRIM |SWT.MODELESS);
mainDialogShell.setText(this.m_sOTMDialogTitle);
mainDialogShell.setLocation(getParent().toDisplay(300, 200));
mainDialogShell.setSize(450, 400);
/* Image dialogicon = new Image(mainDialogShell.getDisplay(),"icon/ecubeIcon.png");
mainDialogShell.setImage(dialogicon);
*/
/*Main grid*/
GridLayout gridLayout = new GridLayout(4, false);
gridLayout.verticalSpacing = 10;
mainDialogShell.setLayout(gridLayout);
//Scope label to display on UI
new Label(mainDialogShell, SWT.NONE|SWT.CENTER).setText("Scope:");
//Text filed for scope
this.m_textScopeName = new Text(mainDialogShell,SWT.READ_ONLY|SWT.SINGLE | SWT.BORDER);
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.horizontalSpan = 2;
this.m_textScopeName.setLayoutData(gridData);
//Button to set scope
Button btnsetscope = new Button(mainDialogShell, SWT.PUSH);
btnsetscope.setText("Set Scope");
gridData = new GridData();
gridData.horizontalSpan = 1;
gridData.horizontalAlignment = GridData.END;
btnsetscope.setLayoutData(gridData);
//Label for List of Parts to Compare
new Label(mainDialogShell, SWT.NONE).setText("List of Parts to Compare :");
//Text filed for List of Parts to Compare
m_listKitParts = new Text(mainDialogShell, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL
| SWT.V_SCROLL);
gridData = new GridData(GridData.FILL, GridData.FILL, true, true);
gridData.horizontalSpan = 3;
gridData.grabExcessVerticalSpace = true;
m_listKitParts.setLayoutData(gridData);
final Button btnCompare = new Button(mainDialogShell, SWT.PUSH);
btnCompare.setText("Identify");
gridData = new GridData();
gridData.horizontalSpan = 3;
gridData.horizontalAlignment = GridData.END;
btnCompare.setLayoutData(gridData);
final Button btnCancel = new Button(mainDialogShell, SWT.PUSH);
btnCancel.setText(" Cancel ");
gridData = new GridData();
gridData.horizontalSpan = 1;
gridData.horizontalAlignment = GridData.END;
btnCancel.setLayoutData(gridData);
long start_time = System.nanoTime();
/*
TCComponentBOMLine[] alSelectedSRCBOMLinetemp = eQOTMSessionInfo.getInstance().getCurrentSourceBOMLines();
int componentsize=alSelectedSRCBOMLinetemp.length;
for(int i=0;i<componentsize;i++)
{
m_listKitParts.append(alSelectedSRCBOMLinetemp[i].toString()+"\n");
}
*/
InterfaceAIFComponent selectedcomponent[]=m_sourcepanel.getSelectedComponents();
int componentsize=selectedcomponent.length;
for(int i=0;i<componentsize;i++)
{
m_listKitParts.append(selectedcomponent[i]+"\n");
}
long end_time = System.nanoTime();
double difference = (end_time - start_time)/1e6;
eQOTMLoggerManager.logger.error("INFO:Response return to TC. Total time taken: "+(difference)/1000);
//Set scope Button Listener
btnsetscope.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent event)
{
//Set Scope for Compare BOMLine operation
SetScope();
}
});
//Compare Button Listener
btnCompare.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent event)
{
if(m_textScopeName.getText().length()<=0)
{
m_textScopeName.setFocus();
MessageBox.post(Messages.eQOTM_ScopeSelection_info,Messages.eQOTM_ScopeSelection_title, 2);
}
else
{
btnCompare.setEnabled(false);
btnCancel.setEnabled(false);
Job serverJob = new Job(eQOTMConstants.Stausmessage)
{
protected IStatus run(IProgressMonitor monitor)
{
eQOTMLoggerManager.logger.error("INFO:Started backgound thread to call MI process\n");
compareBOMLines();
mainDialogShell.getDisplay().syncExec(new Runnable()
{
public void run()
{
mainDialogShell.close();
}
});
return Status.OK_STATUS;
}
};
serverJob.setPriority(Job.SHORT);
serverJob.schedule();
}
}
});
//cancel Button Listener
btnCancel.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent e)
{
mainDialogShell.close();
}
});
eQOTMLoggerManager.logger.error("INFO:Exit initialize UI Components for OTM compare dialog.");
}
private boolean setSourceBomLinesOnSessionInfo() throws TCException
{
eQOTMLoggerManager.logger.debug("In setSourceBomLinesOnCompareDialog");
InterfaceComparable sourcePanel = m_currentTcApplication.getActiveComparable();
eQOTMSessionInfo objOTMSession = eQOTMSessionInfo.getInstance();
this.m_sourcepanel=sourcePanel;
TCComponentBOMLine[] arrayOfTargetTCComponentBOMLine = null;
ArrayList<TCComponentBOMLine> arrlcheckedBOMLine = new ArrayList<TCComponentBOMLine>();
if(((BOMTreeTable)sourcePanel.getCompareTreeTable()).getBOMWindow().getTopBOMLine().getDisplayType().toString().equals(eQOTMConstants.IS_MFG_PLAN))
{
if( !SetScope() )//on error return false
return false;
if( !setCheckedBomlines(arrlcheckedBOMLine)){//on error return false
return false;
}
arrayOfTargetTCComponentBOMLine = (TCComponentBOMLine[])arrlcheckedBOMLine.toArray(new TCComponentBOMLine[arrlcheckedBOMLine.size()]);
}else
{
//EBOM Install to -EBOM Install /MBOM kit to EBOM install Comparison
arrayOfTargetTCComponentBOMLine = ((BOMTreeTable)sourcePanel.getCompareTreeTable()).getSelectedBOMLines();
}
if ( arrayOfTargetTCComponentBOMLine == null || arrayOfTargetTCComponentBOMLine.length == 0)
{
MessageBox.post(Messages.eQOTM_KitSelection_info,Messages.eQOTM_KitSelection_title, 2);
return false;
}
objOTMSession.setCurrentSourceBOMLines(arrayOfTargetTCComponentBOMLine);
eQOTMLoggerManager.logger.error("INFO:No. of Bomlines selected for comparison : "+arrayOfTargetTCComponentBOMLine.length);
eQOTMLoggerManager.logger.debug("Exit setSourceBomLinesOnCompareDialog");
return true;
}
private boolean SetScope()
{
InterfaceComparable targetPanel = m_currentTcApplication.getActiveComparable();
eQOTMSessionInfo objOTMSession = eQOTMSessionInfo.getInstance();
objOTMSession.setTargetBOMTreeTable((BOMTreeTable)targetPanel.getCompareTreeTable());
try
{
objOTMSession.addUserSessionVariable(eQOTMConstants.REVISIONRULE,((BOMTreeTable)targetPanel.getCompareTreeTable()).getBOMWindow().getRevisionRule().toString());
}
catch (Exception e)
{
eQOTMLoggerManager.logger.error("Error occurred while getting RevisionRule from TC user session. Error : "+e.getMessage(),e);
MessageBox.post(Messages.eQOTM_ScopeRevisionRule_info,Messages.eQOTM_ScopeSelection_title, 2);
return false;
}
TCComponentBOMLine[] arrayOfScopeTCComponentBOMLine = ((BOMTreeTable)targetPanel.getCompareTreeTable()).getSelectedBOMLines();
if( arrayOfScopeTCComponentBOMLine==null || arrayOfScopeTCComponentBOMLine.length<1 )
{
MessageBox.post(Messages.eQOTM_ScopeSelection_info,Messages.eQOTM_ScopeSelection_title, 2);
return false;
}
TCComponentBOMLine scopebomline = arrayOfScopeTCComponentBOMLine[0];
try
{
if (scopebomline.getChildrenCount() ==0)
{
MessageBox.post(Messages.eQOTM_ScopeNoChild_info,Messages.eQOTM_ScopeSelection_title, 2);
return false;
}
}
catch (TCException localTCException1)
{
eQOTMLoggerManager.logger.error("Exception Occurred while getting child count for scope");
}
this.m_textScopeName.setText(scopebomline.toString());
eQBOMLineBean currentScopeBOMLine = new eQBOMLineBean(scopebomline);
objOTMSession.setCurrentScopeBOMLine(currentScopeBOMLine);
return true;
}
When a user closes any of the application windows using the Window Close Button(red X) button. It causes Widget is Disposed issues with my application. When they close the window using the close application I provided. Everything works correctly.
#Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.OK_ID, "Close Aplot", true);
}
#Override
protected void okPressed() {
getShell().setVisible(false);
}
Can you catch the press of the Window Close Button(red X) to use the code above?
Can you just disable the Window close Button(red X)?
Listen for SWT.Close on the Shell.
This should help:
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.addListener(SWT.Close, new Listener()
{
public void handleEvent(Event event)
{
int style = SWT.APPLICATION_MODAL | SWT.YES | SWT.NO;
MessageBox messageBox = new MessageBox(shell, style);
messageBox.setText("Information");
messageBox.setMessage("Close the shell?");
event.doit = messageBox.open() == SWT.YES;
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
It will prompt the user to verify the decision.
In a jface dialog, always it will invoke close() method irrespective of where OK is pressed or CANCEL is pressed or close(red x button) is clicked.
Override close method and check return code ( use getReturnCode() method).
First thing I do is override the close() method in the ApplicationWindow
/** the rc from the message dialog */
int rc = -1;
#Override
public boolean close()
{
MessageDialog messagedialog = new MessageDialog(getShell(),
"Confirm Exit", null, "Are you sure you want to exit?", 4,
new String[]
{ "Yes", "No" }, 1);
messagedialog.setBlockOnOpen(true);
messagedialog.open();
rc = messagedialog.getReturnCode();
/** int to hold the return code from the message dialog */
if (rc == 0)
{
return true;
} else
{
return false;
}
}
The second thing I do is listen for events on the 'X' close button
shell.addListener(SWT.Close, new Listener()
{
#Override
public void handleEvent(Event event)
{
switch (rc)
{
case 0: // yes pressed
event.doit = true;
break;
case 1: // no pressed
event.doit = false;
break;
case -1: // escape pressed
break; // do nothing
default:
break;
}
}
});
The "event.doit" boolean field determines the closure of the shell. If the value is equal to 'true' - "lets doit", lets close the shell (i.e. rc = 0).
If this value is equal to 1 (rc = 1) the shell is left open.
If ESC is pressed (i.e. the rc = -1) we simply do nothing. But we could minimize the shell if this was a requirement or perform some other action based on this event.