Custom Widget extending textfield - java

Will it be possible just to simply extend textfield in creating a custom widget that consists of a textbox and label and subsequently inheriting the functionality of the textfield as well as the eventhandling.
From what I understand is that one would normaly extend Composite and then implement initWidget() in the constructor.
initWidget(binder.createAndBindUi(this));
Can I do something similar by just extending textfield.
The reason I want to do this is because of creating an indicator textfield with label already but applying the eventhandling in this custom widget gives me unexpected results when I try to use it somewhere.
import com.google.gwt.core.client.GWT;
public class IndicatorTextField extends Composite implements HasText, HasKeyUpHandlers{
public interface Binder extends UiBinder<Widget, IndicatorTextField> {
}
private static final Binder binder = GWT.create(Binder.class);
public interface Style extends CssResource{
String textStyling();
String requiredInputLabel();
String colorNotValidated();
}
#UiField Style style;
#UiField Label label;
#UiField TextBox textBox;
public IndicatorTextField()
{
initWidget(binder.createAndBindUi(this));
}
public void setBackgroundValidateTextbox(boolean validated)
{
if(validated)
{
textBox.getElement().addClassName(style.colorNotValidated());
}
else
{
textBox.getElement().removeClassName(style.colorNotValidated());
}
}
#Override
public String getText() {
return label.getText();
}
#Override
public void setText(String text) {
label.setText(text);
}
#UiHandler("textBox")
public void onKeyUp(KeyUpEvent event)
{
DomEvent.fireNativeEvent(event.getNativeEvent(), this);
}
#Override
public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
//return textBox.addKeyUpHandler(handler);
return addDomHandler(handler, KeyUpEvent.getType());
}
}

Look at the default constructor of the TextBox class.
/**
* Creates an empty text box.
*/
public TextBox() {
this(Document.get().createTextInputElement(), "gwt-TextBox");
}
It creates the text input element. You can create your custom class LabeledTextBox with a constructor like this:
public class LabeledTextBox extends TextBox {
public MyTextBox() {
super(Document.get().createDivElement());
final DivElement labelElement = Document.get().createDivElement();
final InputElement textBoxElement = Document.get().createTextInputElement();
getElement().appendChild(labelElement);
getElement().appendChild(textBoxElement);
}
...
}
I didn't try this class myself. Most likely, it will require extra adjustments, there might be listener issues etc.
Do you really need to create a widget by subclassing TextBox? Why don't you use some sort of Panel instead? It's an easier approach as for me.

Related

SetText To textfiled or lable From other Window javafx

lets say you have lable in MainWindow ..
and you want change value of this lable
from Window2
Not in Same Window !!
i want the changes while the MainWindow its open
It's easy if ur using 2 .fxml files with there own controllers
if that's the case create a new class file namely 'AllControllers'
you have two 2 controllers namely ControllerWindow1 and ControllerWindow2
public class AllControllers {
private static ControllerWindow1 control1;
private static ControllerWindow2 control2;
public static ControllerWindow1 getControl1() {
return control1;
}
public static void setControl1(ControllerWindow1 control1) {
Controlls.control1 = control1;
}
public static ControllerWindow2 getControl2() {
return control2;
}
public static void setControl2(ControllerWindow2 control2) {
Controlls.control2 = control2;
}
}
You have to initialize each controller like this
public class ControllerWindow1 implements Initializable{
#FXML
public Label mylabel;
#Override
public void initialize(URL location, ResourceBundle resources) {
AllControllers.setControl1(this);
}
}
Now you can access your controller from any class. Just use
AllControllers.getControl1().mylabel.setText("hello");

How to make a complex object an Observable

I have multiple JavaFX panes and canvases that reference a complex object with data they need, and I want them to redraw when the object changes.
This would call for the object to be Observable, but which class do I use? JavaFX seems to mostly have ObservableValue subclasses, which wrap a value and allow swapping it out. I don't want to swap out the complex object, just notify the listeners when changes occur. I could do that by implementing addListener, but I'm sure there's a subclass that does it for me already.
class ComplexObject /* extends SomeObservableClass */ {
public int getValue1 { complex calculations... };
public int getValue2 { ... };
public void setNewValue1(int newValue) { ... }
}
class ComplexRenderer extends Canvas implements InvalidationListener {
private ComplexObject complexObject;
public void setComplexObject(ComplexObject complexObject) {
this.complexObject = complexObject;
complexObject.addListener(this);
}
public void draw() { ... }
}
Which class should ComplexObject extend? Is there something that maintains the list of listeners and has something like fireValueChangedEvent() so I can make it notify all listeners?
Everything I see in JavaFX seems to be geared towards properties, which don't seem the right choice here.
Not really sure what you meant by swapping, and not really sure if I understood you right.
class ComplexObject {
private IntegerProperty value1 = new SimpleIntegerProperty();
private IntegerProperty value2 = new SimpleIntegerProperty();
private BooleanProperty internalChanged = new SimpleBooleanProperty(false);
public ComplexObject() {
this.internalChanged.bind(Bindings.createBooleanBinding(() ->
this.internalChanged.set(!this.internalChanged.get()), this.value1, this.value2));
}
public IntegerProperty value1Property() { return this.value1; }
public int getValue1() { return this.value1.get(); }
public void setValue1(int value) { return this.value1.set(value); }
public IntegerProperty value2Property() { return this.value2; }
public int getValue2() { return this.value2.get(); }
public void setValue2(int value) { return this.value2.set(value); }
public void setNewValue1(int newValue) { /* What value is this??? */ }
public BooleanProperty internalChangedProperty() { return this.internalChanged; }
}
class ComplexRenderer extends Canvas implements InvalidationListener {
private ComplexObject complexObject;
public void setComplexObject(ComplexObject complexObject) {
this.complexObject = complexObject;
complexObject.internalChangedProperty().addListener(this);
}
#Override public void invalidated(Observable observable) {
// Something inside complex object changed
}
public void draw() { ... }
}
Maybe you can have a look at the Interface ObjectPropertyBase<T> and the classes ObjectPropertyBase<T> and SimpleObjectProperty<T> which implements Observable.
However you have to define when your object changes and listening logic.
I'm sorry it's just a trace of work, but I hope it may be useful.

Simple button code using interface

I'll write the code first and ask my question below
Below is my main class
public class Application {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
runApp();
}
});
}
public static void runApp() {
Model model = new Model();
View view = new View(model);
Controller controller = new Controller(view, model);
view.setLoginListener(controller);
}
}
Below is my another class
public class LoginFormEvent {
private String name;
private String password;
public LoginFormEvent(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Below is my controller class
public class Controller implements LoginListener {
private View view;
private Model model;
public Controller(View view, Model model) {
this.view = view;
this.model = model;
}
#Override
public void loginPerformed(LoginFormEvent event) {
System.out.println("Login event received: " + event.getName() + "; " + event.getPassword());
}
}
Below is my LoginListener interface
public interface LoginListener {
public void loginPerformed(LoginFormEvent event);
}
Lastly below is my view class which I have just deleted the JFrame code for simplicity.
public class View extends JFrame implements ActionListener {
private Model model;
private JButton okButton;
private JTextField nameField;
private JPasswordField passField;
private LoginListener loginListener;
#Override
public void actionPerformed(ActionEvent e) {
String password = new String(passField.getPassword());
String name = nameField.getText();
fireLoginEvent(new LoginFormEvent(name, password));
}
public void setLoginListener(LoginListener loginListener) {
this.loginListener = loginListener;
}
public void fireLoginEvent(LoginFormEvent event) {
if(loginListener != null) {
loginListener.loginPerformed(event);
}
}
}
It is a standard button coordinating code so you guys probably won't even need to read my code to answer my question.
So I know how to write this code and this is how I write it when I want a button to do call some action. But when I try to get my logic around it to understand 'why' it works, I get very confused.
so when I call view.setLoginListener(controller) I'm obviously expecting some kind of LoginFormEvent.
Then when I click the button, in the view class, new LoginFormEvent is constructed.
But then how is the constructed LoginFormEvent within the view class be set as the parameter of expected LoginFormEvent in controller class when there's not really any connection between the two classes except that I have defined view.setLoginListener(controller) in the Application class. This just makes setLoginListener of particular instance of view to expect some kind of LoginListener, meaning it doesn't really have to be the one that I set up in the view class upon a click of a button? But obviously it does have to be because that's how the code is run. but why?
You can see the flow as below
Lets start withApplication.java. lets see the method runApp(). It does below things.
Objects of View.java and Controller.java are created.
Controller.java implements LoginListener.java
view.setLoginListener(controller); // this sets the object of
Controller.java in the object of View.java, both these objects are
same as created in step-1.
Now lets move to View.java
It has a field private LoginListener loginListener; and method public void setLoginListener(LoginListener loginListener). This method sets the field loginListener As we see above in step 2 loginListener refers to the same object of Controller.java created in step 1 above.
Now lets move to public void actionPerformed(ActionEvent e) defined in View.java.
It calls fireLoginEvent(new LoginFormEvent(name, password)); See now Object of LoginFormEvent.java is created and it is passed as a parameter to the method fireLoginEvent(LoginFormEvent event).
Now moving to public void fireLoginEvent(LoginFormEvent event)
It has code : loginListener.loginPerformed(event);. From above we know loginListener refers to the one and only object of Controller.java
method public void loginPerformed(LoginFormEvent event) on that very object of Controller.java is called and same object of (again one and only one) LoginEvent.java is passed as parameter.
For such type of scenarios, I would recommend you to note the objects created of each type and connect the flow of calls. Hope above helps you understand the code.

Using GWT Editor Framework with CellList

I want to use the GWT Editor framework with a CellList. My data model looks like this:
public class CarDto {
private String name;
private List<String> features;
// getter and setter
}
Using GWTP here is part of my presenter:
public class Presenter {
public interface MyView extends View, Editor<CarDto> {
}
private final SimpleBeanEditorDriver<CarDto, ?> editorDriver;
public Presenter(...) {
editorDriver = getView().createEditorDriver();
}
...
#Override
public void saveButtonClicked() {
CarDto carDto = editorDriver.flush();
int size = carDto.getFeatures().size(); // result is 0
}
}
My View class:
public class CarView implements Presenter.MyView {
public interface EditorDriver extends SimpleBeanEditorDriver<CarDto, CarView> {
}
#Path(value="name")
#UiField
TextBox nameInput; // editor works fine with this
#Path(value="features") // this editor is not working !!!
ListEditor<String, LeafValueEditor<String>> featuresEditor;
#UiField
CellList<String> cellList;
ListDataProvider<String> dataProvider;
public CarView() {
dataProvider = new ListDataProvider<String>();
dataProvider.addDataDisplay(cellList);
featuresEditor = HasDataEditor.of(cellList);
}
// create the editor driver
#Override
public SimpleBeanEditorDriver<CarDto, ?> createEditorDriver() {
EditorDriver driver = GWT.create(EditorDriver.class);
driver.initialize(this);
return driver;
}
#UiHandler("save")
protected void saveClicked(ClickEvent e) {
List<String> dtos = dataProvider.getList();
dtos.add("test");
getUiHandlers().saveButtonClicked();
}
}
When I hit save button and do editorDriver.flush() in my presenter than I only get the name property from the view's CarDto. The list of features is always empty.
I have to change the value of the featuresEditor manually like this:
featuresEditor.getList().add(...);
in order to get a change in the List after I flush it. This would mean that I have to set two lists to maintain the data:
featuresEditor.getList().add(...);
dataProvider.getList().add(...);
this does not seems to be correct.
How can I achieve that the ListEditor is updated correctly when the dataProvider list changes? How do I setup an Editor correctly to work with the List<String> which is handled by a CellList?

How to make addValueChangeHandler act just like addChangeHandler

I made a wrap widget that implements interface HasChangeHandlers
But i just can't fit events to each other.
public HandlerRegistration addChangeHandler( final ChangeHandler handler ) {
HandlerRegistration registration1 = dateFrom.addValueChangeHandler( handler );// Compile error
HandlerRegistration registration2 = dateTo.addValueChangeHandler( new ValueChangeHandler<Date>() {
#Override
public void onValueChange( ValueChangeEvent<Date> dateValueChangeEvent ) {
//have to fire handler ??
}
} );
return null; // what i should return here?
}
Thanks in advance !
You return the handler of the member object that you want the event to be associated to. For example I have a textbox+label widget and I couldnt create #UiHandler event on it from somewhere because it is not standard so what i did was:
public class TextBoxAndLabel implements HasKeyUpHandlers {
private TextBox myTextBox;
private Label myLabel;
#Override
public HandlerRegistration addKeyUpHandler(KeyUpHandler keyUpHandler) {
return myTextBox.addKeyUpHandler(keyUpHandler);
}
}
and now I can implement
#UiHandler("myClassObject")
A ChangeHandler is not a ValueChangeHandler. You have to make another wrapper class which implements ValueChangeHandler and takes a ChangeHandler as an instance variable. You can then write...
HandlerRegistration registration1 = dateFrom.addValueChangeHandler(new ChangeHandlerWrapper(handler));
Where ChangeHandlerWrapper is a class that implements ValueChangeHandler. For example,
class ChangeHandlerWrapper<T> implements ValueChangeHandler<Date>
{
private ChangeHandler handler;
public void onValueChange( ValueChangeEvent<T> changeEvent) {
handler.onChange(null);
}
}
Of course, this assumes that you don't need the actual event in your handler. If you do then things will get more complicated.

Categories