Possible thread issue? - java

I have 2 classes, one class is a datamodel class and the other is a gui class.
class datamodel .........
Takes user selected data and creates a arraylist
class gui .........
Has a tableviewer that is using the array from the datamodel class
My issue is I need to fresh the tableviewer when the user has added more data to the array.
I created a updateTableViewer method in the gui class.
public void updateTableViewer() {
if(getViewer() != null) {
viewer.refresh();
{
Then I made a reference to the gui class in the datamodel class.
AplotBaseDialog abd = new AplotBaseDialog(null, null);
Then I added the method call to the method adding more data to the array
public void add(TCComponentItemRevision tcRevision, TCComponentDataset selectedDataset) {
AplotDatasetData pp = new AplotDatasetData(tcRevision, selectedDataset);
if (!dataArrayList.contains(pp)) {
dataArrayList.add(pp);
}
abd.updateTableViewer();
}// end add()
This does not work. The getViewer() call always returns null, even if the gui class is created and open.
So I create a boolean value;
Boolean hasViewerBeenCreated = false;
I am setting the value to true after the tableviewer is created.
viewer = new AplotDataTableViewer(parent, SWT.BORDER|SWT.V_SCROLL|SWT.FULL_SELECTION);
viewer.setInput(AplotDataModel.getInstance().getArrayData());
hasViewerBeenCreated = true;
Then I created a method to return the boolean value.
I am calling the method from a button on the dailog.
I also replaced the updateTableViewer method call in the datamodel class
if (!dataArrayList.contains(pp)) {
dataArrayList.add(pp);
}
abd.getBooleanValue();
}
Here are the results.
I execute the add method in the datamodel class -
It returns false - That makes sense because the dailog has not been created at this time
I execute and create the gui class
I click the button and it returns true - This makes sense because the viewer has been created
Here is where I get confused.
With the gui still open, I can execute the add method again and it stills returns a false value. Then I can click the button and see it is true value.
I would think that when the gui is created and the boolean value is set to true. I would be able to get the current value of the boolean in other classes.
I am not sure if I am not referencing the gui class correctly or when the gui is created I am not accessing the current thread or tableviewer?
I don't know if this is a thread issue or I am just not getting the current value from the gui correctly.
This is a big issue with my application right now. I have to be able to refresh the tableviewer any time new data is added to the array. I can not have the user having to manually refresh the table every time that select new data

Related

ListView unable to add and edit cell when empty

I'm trying to use a ListView as an Editor for Strings, that come out of a custom data model. I use TextFieldListCells with an appropriate StringConverter for the cells.
There is an add button next to the ListView that calls this method on action:
#FXML
private void addElement() {
WordListItem newItem = new WordListItem(-1, "");
wordListItems.add(newItem);
wordListView.setEditable(true);
wordListView.getSelectionModel().select(wordListItems.indexOf(newItem));
wordListView.edit(wordListItems.indexOf(newItem));
wordListView.setEditable(false);
}
Where wordListView is the ListView and wordListItems is the ObservableList containing the data for the wordListView.
This does work, except for when the list is empty (not null), and I couldn't quite explain why, so I inspected the Java source code for help.
Here's what I found out so far: the edit(int) call on ListView changes the ListViews internal editIndex value, which is supposed to call the EDIT_START Event. The editIndex is an ReadOnlyIntegerWrapper in which I found some weird code that I can't quite understand and I'm not sure if thats actually producing a bug or I just can't see why they did it:
#Override
protected void fireValueChangedEvent() {
super.fireValueChangedEvent();
if (readOnlyProperty != null) {
readOnlyProperty.fireValueChangedEvent();
}
}
This method is called whenever the editIndex property of ListView is changed. The problem: readOnlyProperty is null, because it's not set anywhere. The only place I could find where it got set is in the getter:
public ReadOnlyIntegerProperty getReadOnlyProperty() {
if (readOnlyProperty == null) {
readOnlyProperty = new ReadOnlyPropertyImpl();
}
return readOnlyProperty;
}
(ReadOnlyIntegerImpl is an inner private class and readOnlyProperty is it's type)
Now to my actual question: Is this a bug or am I overseeing something? Is there a reason why I can't add and edit a newly created Element in my list like that when it's empty, or is it really just this getter not being called yet?
The source code you found just is code for lazy initializing the property.
Unless new value is assigned to the property or the property itself is requested, null can be used as the property to avoid unnecessary creation of property objects. This is not an issue here.
The issue seems to be the ListView cells not being updated before edit is called. This happens during layout, so "manually" calling layout before starting the edit should work:
private void addElement() {
WordListItem newItem = new WordListItem(-1, "");
wordListItems.add(newItem);
wordListView.setEditable(true);
wordListView.layout();
wordListView.edit(wordListItems.size()-1);
wordListView.setEditable(false);
}

GWT Custom Cell in CellList - render() not being called

I'm having trouble figuring out why my render method isn't being called. Here is my custom cell that extends AbstractCell, broken down to its simplest form.
public class FormHistoryCell<T> extends AbstractCell<T> {
#Override
public void render(com.google.gwt.cell.client.Cell.Context context, T value, SafeHtmlBuilder sb) {
System.out.println("Rendering customer cell...");
if (value == null) {
return;
}
}
}
Here is the snipet in my code which creates an instance of "FormHistoryCell" and attempts to add it to a CellList.
#UiFactory
CellList<FormHistoryCell> initList() {
FormHistoryCell formHistoryCell = new FormHistoryCell();
CellList historyList = new CellList<FormHistoryCell>(formHistoryCell);
return historyList;
}
I have tried different things like adding a constructor that takes a String argument, etc. The constructor is called, but the render method is not. Looking at that Abstract class it extends, it seems the render method is called within the "setValue" method, but didn't see where that is called in other custom cell extensions whose render methods seem to be getting called just fine. I'm sure I'm missing something obvious here but can't figure out what. Please help.
Based on the code you provided, there is no reason for a browser to call the render method of your cell. You simply passed a reference to an object FormHistoryCell to your CellList. The render method is only needed when a browser has to display a cell and its content. This happens when you add data to your CellList, as #outellou suggested.

Pass Unique JButton Data to Another Class on Click

I am making a program where clicking a custom JButton allows you to make your next click paint an image at the point on the screen. Members of this JButton class have certain data that is unique to each separate button. My question is if I can pass the JButton object when clicked on through a method into a class which would then extract the data. I was thinking something like this:
Click Method in JButton{
OutsideClass.setObject(this); //problem
}
OutsideClass{
Object obj = new Object();
public void setObject(Object Obj){
obj = Obj;
}
Click Method in OutsideClass{
place obj;
obj.getData;//Methods within JButton that retrieve specific data
}
My issue is the "setObject" part of the JButton. It doesn't recognize "this" as the specific Object clicked and thus doesn't work. Is there another way to get the desired effect? Thanks!

Walk-around to actionPerformed() returning void

I am trying to use the MVC design.
In the model I wanted a method like this
public boolean changeSomeData(...){
boolean b;
//create a dialog with an OK button
return b;
}
I want the method to return TRUE if the changes were actually made. The changes are done inside the actionPerformed method of the OK button.
My problem is that I can't write b=true; inside the actionPerform of the OK button, because I have to declare b as final in order to use it in the actionPerformed().
What I did is creating a class
private class MyBoolean {
boolean b;
}
and then
public boolean changeSomeData(...){
MyBoolean myBoolean;
//create a dialog with an OK button
actionPerformed(){
//make changes in the data
myBoolean.b=true;
}
boolean b = myBoolean.b;
return b;
}
But I don't feel good about this solution and I wanted to know if it is correct what I did and if there is a better solution.
Should I better throw an exception if the changes aren't made? (for example, if the user clicks "cancel" instead of "ok")
In the model I wanted a method like this ... //create a dialog with an OK button
I'd say this is a flaw already, since the model should not do anything with views directly.
A better approach would be to open the dialog (using the controller), register the controller for the ActionEvent of "OK" (and thus actionPerformed) and then do whatever changes should be done in that method.
Edit:
You might want to consider the following rough approach:
The views register themselves or associated classes to the model as listeners. Whenever the model is changed it fires events to notify the views of the change.
The controller registers itself on the views and is notified when the views change. If a user changes data, the controller then might open the dialog and only commit the changes of the user signals "OK". Thus the model has never to check itself if data needs to be changed. That is actually the controller's task and if the controller passes changes to the model, it should apply them.
A better way to achieve your task is to keep a variable on the dialog that indicates if a successful change was made. Then have a method that your model class calls to retrieve the value and return it.
Something like:
public boolean changeSomeData(...){
//create a dialog with an OK button
return dialog.isSuccess();
}
One way you could make this code a bit cleaner...
public boolean changeSomeData() {
// note that this is not a class boolean, no need to do extra autoboxing.
boolean dataChanged = false;
// check the old value against the new value
// for classes
if (oldvalue.equals(newValue)) {
oldValue = newValue;
dataChanged = true;
}
// for pimitives (built-ins)
if (oldvalue == newValue) {
oldValue = newValue;
dataChanged = true;
}
// odds are good that the above action performed was supposed to call this
// changeSomeData() and not the other way around.
// if you must fire actionPerformed() when data has changed, then do so
// like this, otherwise if it was added as part of the "solution" you can
// skip it.
if (dataChanged) {
actionPeformed();
}
return dataChanged;
}
Note that this code is Controller code, as it manipulates the model directly, and (possibly) updates views.

Regarding Multiple Tab-Class

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.

Categories