Now that I am able to set the content of my second wizard's page depending on the first page selection, I am looking for a way to give the focus to my 2nd page's content when the user clicks the next button on the first page.
By default, when the user click the next button, the focus is given to the button composite (next, back or finish button depending on the wizard configuration)
The only way I found to give focus to my page's content is the following one:
public class FilterWizardDialog extends WizardDialog {
public FilterWizardDialog(Shell parentShell, IWizard newWizard) {
super(parentShell, newWizard);
}
#Override
protected void nextPressed() {
super.nextPressed();
getContents().setFocus();
}
}
To me it's a little bit "boring and heavy" to have to override the WizardDialog class in order to implement this behavior. More over, the WizardDialog javadoc says:
Clients may subclass WizardDialog, although this is rarely required.
What do you think about this solution ? Is there any easier and cleaner solution to do that job ?
This thread suggests:
In your wizard page, use the inherited setVisible() method that is called automatically before your page is shown :
public void setVisible(boolean visible) {
super.setVisible(visible);
// Set the initial field focus
if (visible) {
field.postSetFocusOnDialogField(getShell().getDisplay());
}
}
The postSetFocusOnDialogField method contains :
/**
* Posts <code>setFocus</code> to the display event queue.
*/
public void postSetFocusOnDialogField(Display display) {
if (display != null) {
display.asyncExec(
new Runnable() {
public void run() {
setFocus();
}
}
);
}
}
VonC's answer works great, I personally found it to be a little easier to work with like this though:
#Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
Control control = getControl();
if (!control.setFocus()) {
postSetFocus(control);
}
}
}
private void postSetFocus(final Control control) {
Display display = control.getDisplay();
if (display != null) {
display.asyncExec(new Runnable() {
#Override
public void run() {
control.setFocus();
}
});
}
}
Related
I am trying to make a password checker, and I am trying to have an icon set as X until the user meets the condition of the password being at least 8 characters long. I am trying to set up a while loop for while the program is running, which will in turn run another while loop which will update the icon. I am doing this because a want it to always be checking to see if the condition is met and not need the user to click a button for example. I have placed the code inside the initComponents of the public form PasswordCheckerUI, but when I hit run on the program, it says running but my GUI doesn't pop up. How would I change the code to make this work(if needed) or where would I have to move it to? I have tried making a public static void with the code and calling it within the initCompnents, but it yielded the same results. Lastly, I tried to call the method within the main method, but the variables aren't static so that did not work either
public class PasswordCheckerUI extends javax.swing.JFrame {
public PasswordCheckerUI() {
initComponents();
while (Thread.currentThread().isAlive()) {
while (txtPassword.getText().length() < 8) {
lblMinCharIcon.setIcon(X);
if (txtPassword.getText().length() >= 8) {
lblMinCharIcon.setIcon(Check);
}
}
}
}
}
Events in Swing don't just happen when the user clicks on a button - they happen all the time (when moving the mouse, when clicking, when editing text, when ...) and they are therefore the best way to solve your problem.
You can for example listen the document change events on the txtPassword and change the icon depending on the new length of the password:
public class PasswordCheckerUI {
private JTextField txtPassword;
private JLabel lblMinCharIcon;
public PasswordCheckerUI() {
txtPassword = new JTextField(40);
txtPassword.getDocument().addDocumentListener(
new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
checkPasswordLen(txtPassword);
}
#Override
public void removeUpdate(DocumentEvent e) {
checkPasswordLen(txtPassword);
}
#Override
public void changedUpdate(DocumentEvent e) {
checkPasswordLen(txtPassword);
}
}
);
}
private void checkPasswordLen(JTextField tf) {
if (tf.getText().length() < 8) {
lblMinCharIcon.setIcon(x);
} else {
lblMinCharIcon.setIcon(check);
}
}
}
I have a custom widget which is can accept a widget inside of it. Here is the code:
public class CustomDivWidget extends Widget {
protected Element divElement = DOM.createDiv();
public CustomDivWidget() {
divElement.getStyle().setWidth(100, Unit.PX);
divElement.getStyle().setHeight(100, Unit.PX);
divElement.getStyle().setBorderStyle(BorderStyle.SOLID);
divElement.getStyle().setBorderWidth(1, Unit.PX);
divElement.getStyle().setBorderColor("blue");
setElement(divElement);
}
public void add(Widget child) {
divElement.appendChild(child.getElement());
}
}
Then this is how I used it:
public void onModuleLoad() {
CustomDivWidget customDiv = new CustomDivWidget();
TextButton button = new TextButton("Button 1");
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("Button 1 clicked!");
}
});
customDiv.add(button);
RootPanel.get().add(customDiv);
}
When I run it, it show correctly the widget I want like this :
But the problem is, the click handler was not working when I tried to click the button. The questions are :
Why it is not working?
What should I do to make it working?
Any comments or suggestions will be appreciated. Thanks and regards.
I think you are bypassing GWT's event system this way (I'm not sure though). However, why not using a FlowPanel?
protected FlowPanel fp = new FlowPanel();
public CustomDivWidget() {
fp.getElement().getStyle().setWidth(100, Unit.PX);
fp.getElement().getStyle().setHeight(100, Unit.PX);
fp.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
fp.getElement().getStyle().setBorderWidth(1, Unit.PX);
fp.getElement().getStyle().setBorderColor("blue");
setElement(fp.getElement());
}
Apart from that, why are you using DOM elements instead of widgets? Using widgets instead of having to deal with the DOM is one of the key features of a toolkit like GWT (just my opinion here).
Edit : try to attach the handler directly to the DOM, to see if it makes any difference :
DOM.setEventListener(button.getElement(), new EventListener() {
#Override
public void onBrowserEvent(Event e) {
switch (DOM.eventGetType(e)) {
case Event.ONCLICK:
System.out.println("click");
break;
}
}
});
Right now I have the following code working:
#UiHandler("usernameTextBox")
void onUsernameTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
#UiHandler("passwordTextBox")
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
void keyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}
I would like the ability to have just one listener for all elements on the view without duplicating an event for each textbox.
The end goal is that if they press enter, regardless of where they are on the page, it should submit the form.
Thanks!
What works, but still requires you to specify it for each widget, but doesn't require duplicate code:
#UiHandler({"usernameTextBox", "passwordTextBox"})
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
Yes jackcrews is correct. Also you can try the following. It may be VerticalPanel, DockLayoutPanel etc....
UiBinder.ui.xml
<gwt:VerticalPanel ui:field="mainPanel">
<gwt:Label>Name</gwt:TextBox>
<gwt:TextBox ui:field="textBox">
</gwt:VerticalPanel>
Main.java
#UiField
VerticalPanel mainPanel;
public Main() {
focushandler();
}
void focusHandler() {
mainPanel.addDomHandler(new Handler(), KeyPressEvent.getType());
}
final class Handler implements KeyPressHandler {
#Override
public void onKeyPress(KeyPressEvent event) {
//Code what you expect
}
}
Actually this has more number of lines. But it is good practice.
Regards,
Gnik
I found out that the g:FocusPanel allows me to capture events for everything inside the panel.
#UiHandler("focusPanel")
void onFocusPanelKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}
I have an SWT WizardDialog with a number of pages. When this dialog first opens I have to do a check for some conditions and if those conditions are met I need to show a popup over the freshly opened dialog.
So I have this code to listen for SWT.Show event. The event listener responds to SWT.Show to conduct its tests and show a message box:
final WizardDialog dialog = new WizardDialog(shell, wizard);
dialog.setTitle("New Wizard");
dialog.create();
dialog.getShell().addListener(SWT.Show, new Listener()
{
private boolean firstShowing = true;
#Override
public void handleEvent(Event event)
{
if (firstShowing && someConditionExists())
{
MessageBox messageBox = new MessageBox(dialog.getShell(), SWT.OK
| SWT.ICON_WARNING);
messageBox.setMessage("Test");
messageBox.open();
firstShowing = false;
}
}
});
dialog.open();
Except it's called too soon! The dialog is not visible when the handler is called. My message box appears before the dialog is visible and the dialog only appears when I dismiss the message box.
So clearly the SWT.Show is unreliable, at least on Windows where I'm running it. I've also tried putting this code into a ShellListener on the activation but that happens even before the SWT.Show example above.
So how do I reliably show a message box when the dialog is made visible?
Plan B is a dirty timer based hack where a timer is set to fire 200 ms into the future and hope that it triggers when the dialog is visible but obviously this could introduce it's own issues.
I'm using in similar situation (need that appStarted() is called after application window is visible) something like below.
public class App extends ApplicationWindow {
#Override
protected Control createContents(Composite parent) {
// ...
getShell().addShellListener(new ShellAdapter() {
#Override
public void shellActivated(ShellEvent shellevent) {
if (!started) {
Shell s = (Shell) shellevent.getSource();
s.setVisible(true);
appStarted();
started = true;
}
}
});
}
}
Maybe You can use the same like below:
final WizardDialog dialog = new WizardDialog(shell, wizard);
dialog.setTitle("New Wizard");
dialog.create();
dialog.getShell().addShellListener(new ShellAdapter() {
#Override
public void shellActivated(ShellEvent shellevent) {
if (firstShowing && someConditionExists()) {
Shell s = (Shell) shellevent.getSource();
s.setVisible(true);
MessageBox messageBox = new MessageBox(dialog.getShell(), SWT.OK | SWT.ICON_WARNING);
messageBox.setMessage("Test");
messageBox.open();
firstShowing = false;
}
}
});
dialog.open();
Instead of hooking the SWT.Show event, you may get more luck with hooking a PaintListener on to your dialog's Composite. (You'll probably want to unhook it during the first execution.)
What about overriding dialog.open() methodon your WizardDialog class? The first line of the overridden method would call super.open(), which would make it visible. Just put your custom code after that, in the .open() method.
The issue with the approach you're taking above appears to be that it responds to a Show event, which is simply notification that Show has been requested, not that the dialog is visible. The Show event could very well be designed to allow you to know when something is about to be shown, and take some action before that happens, as you've experienced.
I know that this is an old thread. But in case someone finds it useful, I found that overriding Dialog.create() rather than Dialog.open() worked for me.
it's called too soon!
I also run recently in the same trouble. The code was executed too early - my upload action (which I wanted to start automatically under some conditions) was started before the page was displayed.
This happens because the page can only be shown after the code in the SWT.SHOW listener or in the inherited setVisible() method is completed.
#Override
public void setVisible(boolean visible) {
if (visible) {
org.eclipse.ui.progress.UIJob("Auto start the upload") {
#Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (isAutoStartQcUploadSelected)
startUpload();
return Status.OK_STATUS;
}
};
uiJob.schedule();
}
super.setVisible(visible);
}
org.eclipse.ui.progress.UIJob as described FAQ_Can_I_make_a_job_run_in_the_UI_thread has solved the issue.
P.S.: Yes, I know that's an old question :-)
But it is the first one propesed by google and the hint with the UI Job was missing.
The code of marioosh can be further improved, by storing the ShellAdapter in a variable.
Remove the ShellAdapter when the listener is triggered for the first time.
The variable started is no longer needed.
The statement s.setVisible(true); is not necessary, because this event is just triggered when the shell gets visible.
public class App extends ApplicationWindow {
#Override
protected Control createContents(Composite parent) {
// ...
ShellAdapter shellActivatedAdapter = new ShellAdapter() {
#Override
public void shellActivated(ShellEvent shellevent) {
shellevent.getSource().removeShellListener(shellActivatedAdapter);
appStarted();
}
};
getShell().addShellListener(shellActivatedAdapter);
}
}
I don't know how to show another page on button click in blackberry using java.
I assume you have a ButtonField added to some kind of Screen. You need to set the FieldChangeListener for the ButtonField:
class YourScreen extends FullScreen {
public YourScreen() {
super();
ButtonField btn = new ButtonField("mybutton");
btn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
synchronized (UiApplication.getApplication().getEventLock()) {
UiApplication.getUiApplication().pushScreen(new FullScreen());
}
}
});
add(btn);
}
}
Also note that you need to either get the event lock before pushing the screen or pass UiApplication.invokeLater a Runnable like so:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new FullScreen());
}
});
Some basics on UI threading issue on BB here: http://www.thinkingblackberry.com/archives/182
UiApplication.getUiApplication.pushScreen(new Screen());
http://www.blackberry.com/developers/docs/4.5.0api/index.html