I have created a class which extends JavaFX's MenuBar that creates a menu bar for my application.
By default I won't specialized operations, like opening/saving a file and running a simulation, to be disabled (and they are). When a user runs the app they can select an item in the menu File>New>, and based on which component they select it will toggle on the appropriate menu options.
I was planning on doing this by having each component give a list of which items it toggles on, and then activating the appropriate items when the component is created.
However, I cannot access the list of menus from within in a function (am trying to do it with this.getMenus() but from within the function the only function that is recognized it this.getClass()).
Does anyone know why I cannot call getMenus() and how I could get access to it?
Alternatively, if you have a better idea for how I can toggle these menu items, I'd love to hear. I don't think this is a good way to do it, but it is the best idea we have come up with.
private void fileNew()
{
Menu fileNew = new Menu("New");
menuFile.getItems().add(fileNew);
for(String k: CLHM.keySet())
{
CComponent comp = CLHM.get(k);
if(comp.supportedFeatures().contains((new SupportsNew())))
{
MenuItem i = new MenuItem(comp.getName());
fileNew.getItems().add(i);
i.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
CComponent ctemp = CLHM.get(i.getText());
ArrayList<String> menuItems = (ArrayList) ctemp.getMenuItems();
for (String s : menuItems)
{
Scanner scanner = new Scanner(s).useDelimiter("\\s>\\s");
String menu = scanner.next();
//Menu temp = this.getMenus();
/*
Here the program will parse the string of the
Menu path (e.g. File>Open) and activate the
relevant item, if it exists.
*/
}
borderPane.setCenter((Node) ctemp);
}
});
}
}
}
When you use this inside an anonymous class, it actually refers to the anonymous class instance. So in your case, this is an instance of EventHandler, which is why there are so little methods that you can call (because it is an interface type).
What you are looking for is YourExtendedMenuBar.this.getMenus(). This will tell the compiler that you are looking for the enclosing instance. Alternatively, you can simply drop the this keyword (i.e. getMenus()). Doing so will allow you to use/call any accessible members of the anonymous class and its enclosing class.
On the side note, if you replaced that anonymous class with a lambda expression, then this would have meant YourExtendedMenuBar. It is not possible to access any members of the class that the lambda expression represents, at least not directly.
P.S. I have no idea what your toggling is all about, so I can't answer until I figured out what you mean.
Related
I use Vaadin 14 and would know whether it is possible to report changes in the nested list to objects in the main view.
A rough example is shown in the picture. Above you can see the sum as size (here 2), if I press Delete it should change to 1.
Is that possible and how?
concept
I don't have any code yet, it's a thought where I would like to have a hint about what would be possible, e.g. Observer Pattern or something, but code could look something like this
code:
#Rout("")
public class MainView extends VerticalLayout {
private List<CustomDetails> customDetails = new ArrayList<>();
public MainView(){
final var form = new FormLayout();
customDetails.forEach(form::add);
add(H1("Header"), form)
}
}
public class CustomDetails extends Details{
private CustomForm customForm;
private final Service service;
public CustomDetails(){
customForms = new CustomForm(service.getListOfObjects());
this.setContent(customForms)
}
}
public class CustomForm extend FormLayout{
private FormLayout formLayout = new FormLayout();
private List<Object> objects = new LinkedList<>();
public CustomForm(List<Object> list){
this.objects = list;
setUp();
add(new Paragraph("SUM: "+ list.size()), layout);
}
private void setUp(){
objects.forEarch(o->{
....
layout.add(...)
})
}
}
In Vaadin there is an utility class Binder which is used to bind data to forms. If your use case is related to this, i.e. your so called nested layout is in fact a form and objects you refer to are data beans you want bind into that form. I recommend to study that first.
If you have list editor, I would also investigate if it fits your application to implement it with Grid or IronList/VirtualList, which is backed by DataProvider. Say you edit one item, and after saving the item, you can call dataProvider.refreshItem(item) to update the view.
Observer Pattern or something...
Yes, that is a solution. It is a lot of work and has been done before.
One such library is Beanbag.
Note: I wrote this (or rather, I started writing it a day ago).
EDIT:
As of this edit, we have the ObservableCollection interface. You can use it like so:
// You have a collection called "strings".
// Wrap it in an ObservableCollection.
final ObservableCollection<String, Collection<String>, BasicObservableCollection.Default<String, Collection<String>>> observableStrings = ObservableCollections.observableCollection(strings);
// Add a removed observer.
observableStrings.addElementRemovedObserver(observation -> System.out.println("\"" + observation.getValue() + "\" was removed.");
// Remove an element.
observableStrings.remove("hello");
If you need the wrapper to have List methods, just wait until tomorrow evening EST. I'll have the code up by then and will update this post accordingly.
I am in the process of refactoring my application and my teacher recommended that I replace the GUI builder generated code with a more generic one.
Right now every JMenuItem has its own action listener. What I'm trying to achieve is a sort of generic control function for every menu item by using enums in a single action listener. The code below should give you a general idea. clE is the enum key and I believe the enum should implement an interface for reading its label.
I've been doing a bit of research and I'm sure it's something simple, but I can't get fully grasp it yet. Thanks in advance!
public class JECheckBox<E extends ENUM_Label_INTF<?>> extends JCheckBox {
private final E clE;
// +++++++ CONSTRUCTOR +++++++++
public JECheckBox(final E clE) {
super( ((GetLabelINTF) clE).GetLabel() );
this.clE = clE;
}
public E GetKey() {
return clE;
}
}
I believe the enum should implement an interface for reading its label.
If you want to read the text of the check box, then you create a generic listener by doing something like:
Action action = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
JCheckBox checkbox = (JCheckBox)e.getSource();
System.out.println( checkbox.getText() );
}
};
Now you can add the Action to each check box.
Note an Action is a more versatile ActionListener. Read the section from the Swing tutorial on How to Use Actions for more information and examples.
Not suew what you mean by generic enums. Try giving every menu item (or any component) it's own name using component.setName(SomeEnum.soneValue.toString()). Then get the name in the action listener and do a switch(SomeEnum.valueOf(name).
I am currently developing a javafx desktop application. It contains two observableList<Item>s and two HashMap<String,Double>s. I am currently develop the menuBar , which contains these menuItem s, i.e. Open, New, Save and Save As.
Consider the case where I have started the desktop application and added a few Item to the observableList<Item>. Then all of a sudden, I want to hit any one of the menuItems listed above. First thing I want to check in my program is whether the current workflow needs to be saved before proceeding to start a new workflow (New menuitem).
I have the following method in place at the moment but I think it looks very clumsy and inefficient.
The method I developed is to set a variable private static final boolean isSaved = false;
And then within the two observableLists, I added a Listener to them:
obslist1.addListener(new ListChangeListener<Item>(){
#Override
public void onChanged(ListChangeListener.Change change) {
isSaved = false;
}
});
The code for obslist2 is identical. And the isSaved variable is set to true only if the user actually presses the Save or Save As menuItem.
I find my method very clumsy and inefficient. Is there a better way to do this?
You can do something like
BooleanProperty saved = new SimpleBooleanProperty();
InvalidationListener savedListener = obs -> saved.set(false);
and then
private void save() {
// save the data...
// mark data as saved:
saved.set(true);
}
with
obslist1.addListener(savedListener);
obslist2.addListener(savedListener);
anythingElseThatMightChangeAndIsImportant.addListener(savedListener);
Your save button and menu item, etc can do
saveButton.disableProperty().bind(saved);
I have an application which uses GXT and contains ±30 forms. I would like to make these forms so that when the user hits enter in a text field, the form gets submitted, like a regular browser form would.
I know I can add a key press listener to every text field, which would invoke the submit after enter is pressed, but since I want to apply this to every field in every form I am not sure if this is ideal.
Is there a simpler way to implement this in the entire application?
If not, which pattern should I use to add this functionality to every field? I can extend the TextField class, add the functionality in the child class and use the child class in the application. Or I can create a factory for the text field class which would also add the listener to the field. Or is there some other way, Decorator perhaps? I was wondering which of these approaches, if any, is generally preferred.
I would try something like this:
Event.addNativePreviewHandler(new NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
if (event.getNativeEvent().getEventTarget() != null) {
Element as = Element.as(event.getNativeEvent().getEventTarget());
if (as.getTagName().toLowerCase().equals("input") ||
as.getTagName().toLowerCase().equals("textarea")) {
// TODO submit data;
}
}
}
}
});
Every time someone hits the Enter Key and the cursor is placed on a input- or textarea-tag, you will get the control and can submit your data.
I don't think there is a way to do what you're asking directly in the GXT library. I do want to stress that extending the TextField class just to add an event handler to it is not the correct way to handle this. Event handlers are based on the composition of a class. It would be like extending a class with a List field just to add another element into the list.
A singleton factory class that created and initialises the Textfield for you would be the cleanest solution, in my opinion. It would allow you to effectively change defaults and add other handlers as required at a later time in a single place if requirements change.
You can try it with GWT JSNI also.
Steps to follow:
define a function in JavaScript that is called on Enter key press
call GWT JSNI from above JavaScript function that is exported at the time of onModuleLoad using GWT JSNI
get the Element from where this event is triggered and finally submit the form based on its tag name or Id
Sample code:
HTML/JSP:
<script>
window.onkeydown = keydown;
function keydown(event) {
if (event.which == 13) {
formSubmit(event.target);
}
}
</script>
JAVA(Entry Point):
import com.google.gwt.dom.client.Element;
public void onModuleLoad() {
exportFormSubmit();
...
}
public static void formSubmit(Element element) {
Window.alert("element tag name:" + element.getTagName() + "form ID:"
+ element.getParentElement().getId());
}
public static native void exportFormSubmit() /*-{
$wnd.formSubmit = $entry(#com.x.y.z.client.GWTTestProject::formSubmit(Lcom/google/gwt/dom/client/Element;));
}-*/;
I've problem regarding GUI with one Menu and one Order Class.
I've created a variable to store how many items have been selected in the Menu Class.
private int totalSelected;
The var totalSelected is live updated. It can be changed anytime depending on actionPerformed() function.(Exp: totalSelected will add up all the selected items)
In the Order Class, how can I access to the live update variable totalSelected in order to retrieve the live update value? When I invoke getTotalSelected() function inside the Menu Class, I will only obtain a 0 value.
Thanks for your help ^^!
Please allow me to specify my question clearer.
public class MenuTab extends JPanel
{
private JLabel display;
private int totalSelected;
public MenuTab()
{
....
}
}
public getTotalSelected(){
return totalSelected;
}
private class SelectedListener implements ActionListener
{
public void actionPerformed()
{
.......
//Assume that totalSelected has been updated!
display = new JLabel("Total: " + totalSelected);
// OK to display totalSelected live value here.
}
}
// A new class is the confirmation of order
public class OrderConfirmedTab extends JPanel{
private JLabel displayTotal;
private MenuTab order = new MenuTab();
public OrderConfirmedTab()
{
......
int totalSelected = order.getTotalSelected();
displayTotal = new JLabel("Total: " + totalSelected);
// Problem to display totalSelected live value here.
// Will obtain 0;
// How can I obtain the live updated value from class MenuTab? Thanks!
}
}
If I read your code right, you need to make your variable be private static int totalSelected; You need to make it static so that it stays the same for all instances of the class.
I looks like your not updating the private int totalSelected; variable when a user makes a selection, so it is always 0.
Ya! I just realized that my JLabel
will not update the value
automatically. So how can I fix it?
Thanks! – Christine
If I understand you correctly you have two GUIs where changes in one (the MenuTab) will update the other (OrderConfirmedTab) in real time?
If so, you will need to increase the coupling between the two objects. If MenuTab has a reference back to OrderConfirmedTab then it can call methods to update the value as it changes.
For example, pass OrderConfirmedTab into MenuTabs constructor
MenuTab mt = new MenuTab(this); // from within OrderConfirmTabs costructor
Then when MenuTab has an actionPerformed event it can call back to OrderConfirmTab
orderConfirmTab.setTotalSelected(totalSelected); // you have to create this method in OrderConfirmTab
I hope this helps a little
You can use PropertyChangeListener and PropertyChangeSupport mechanisms to dispatch an event when the value is updated and to be notified when the variable has changed. Your JLabel is not going to update on its own; even if you were to use an object other than a primitive (note that primitives are merely values, while objects are actually implicit pointers); you will need to update your JLabel when the variable changes, since the JLabel simply stores a string, not a reference to the variables from which the string was constructed.
This is the concept of model-view-controller; your variable should be in some sort of class or classes that represent the model (the information) and which allow changes to be observed via property change events. Your view classes should simply provide display logic and no business or application-specific logic. It is the controller in which your application logic should reside; your controller should register for events on the model, and it should update the view whenever the model has changed, and it should likewise update the model when the view dispatches events that should result in the model being changed.