I have a method (shown below) which works fine. The purpose of this method is to confirm if a specific item is available in a shop, with a return value of true or false.
I have a second method, which returns a description, but I can't see to work out how to get this method to pull through the first method response with 'true' showing as 'Yes' or 'false' showing as 'No'. I'm assuming it is something to do with method calling and string concatenation.
My overall problem pulls through 2 methods, but I wanted to just try and understand how to pull one method first and then I'll hopefully work out the rest!
Method 1
public void isFree()
{
if (sweet.isEmpty()){
System.out.println("True");
}
else {
System.out.println("False");
}
}`
Method 2
public void information()
{
System.out.println (isFree+ " this item is available for purchase.");
}
Return type of your first method is void so you are not returning anything, you are just printing Yes or False in new line. To concatanate "True" or "False" to another String you need to return String from isFree method
You may try something like this
public String isFree(){
return sweet.isEmpty() ? "True" : "False";
}`
public void information(){
System.out.println (isFree() + " this item is available for purchase.");
}
In second method message doesnt make much sense with False but this is up to you to adjust it
You can also reutrn boolean directly
public boolean isFree() {
return sweet.isEmpty();
}
Keep in mind that in this case it will be revolved to "true" or "false" and not "True"/"False"
Of course if "true"/"false" is ok in your case you can remove isFree method completly and just use sweet.isEmpty() directly in information
Is there any specific reason to use two methods, rather isEmpty in the collection will return the boolean (true, false) for you and you can directly use the second method removing the first completely.
public void information() {
String customText=", this item is available for purchase.";
System.out.println (sweet.isEmpty() ? "YES"+customText : "NO"+customText);}
You can achieve this from several ways:
Call first isFree from information, and then print the second string. For this, you would have to edit both methods, since you are using println.
public void isFree() {
sweet.isEmpty() ? System.out.printf("True") : System.out.printf("False");
}
public void information() {
isFree();
System.out.printf(" this item is available for purchase.\n");
}
Make isFree return a String.
public String isFree() {
sweet.isEmpty() ? "True" : "False";
}
public void information() {
System.out.println(isFree() + " this item is available for purchase.");
}
Linking in from Sort rows in JFace Treeviewer where I asked #greg-449 why my comparator doesn't work when (like the question on that page) I just wanted to sort by the label provider.
My TreeViewer is somewhat extended with some generic features used in my application. There are then at 3 derivations extending it, but essentially the example below of it being an abstract class is because it's not intended to be directly instantiated, and the rest of the Eclipse plugin code must choose a concrete implementation for various view parts. However, I need sorting functionality in all of them, so this is probably where it should go.
I anonymized the code below, but it is in essence the abstract wrapper around TreeViewer which in all derivations has 3 columns. The first column (index 0) is always a tree of some type, so the nodes are expandable and this produces more visible rows of data in the 2nd and 3rd columns (indexes 1 and 2). These columns contain text data only.
As such, what I hope to achieve is a sortable control, where clicking header column with index 0 will clear any sorting and render the data as it was initially loaded, while clicking any other headers will do the following:
Sort Ascending (UP) if it was NOT already the sort column
Invert sort direction if same sort column is repeatedly clicked
Here's what I have tried, starting with the ViewerComparator class mentioned in the link at he top of this post:
public abstract class MyTreeViewer extends TreeViewer {
public static final int ACTIVE_TOTAL_COLUMN_WIDTH = 120;
public static final int FIRST_COLUMN_WIDTH = 180;
private static final String SPECIAL_FIELD = "specialField";
private TreeColumn sortColumn = null;
final RMService rmService;
final PService pService;
public MyTreeViewer(Composite parent) {
this(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION);
}
public MyTreeViewer(Composite parent, int style) {
super(parent, style);
this.rmService = UIActivator.getDefault().getInjector().getInstance(RMService.class);
this.pService = UIActivator.getDefault().getInjector().getInstance(PService.class);
this.setUseHashlookup(true);
this.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(SelectionChangedEvent event) {
if (!event.getSelection().isEmpty()) {
Tree tree = getTree();
if (tree != null) {
List<MyTreeItem> treeItems = Lists.newArrayList();
for (int i = 0; i < tree.getSelectionCount(); i++) {
TreeItem item = tree.getSelection()[i];
Object obj = item.getData();
if (obj instanceof MyTreeItem) {
treeItems.add((MyTreeItem) obj);
}
}
handleSelectionChanged(treeItems);
}
}
}
});
this.setComparator(new ViewerComparator());
}
protected abstract void handleSelectionChanged(Collection<MyTreeItem> treeItemList);
public void initTree(List<ViewField> fields, IMemento memento) {
TableLayout tableLayout = new TableLayout();
Tree tree = getTree();
for (ViewField field : fields) {
TreeViewerColumn column = new TreeViewerColumn(this, SWT.NONE);
if (SystemPropertiesLoader.OPERATING_SYSTEM_NAME.equalsIgnoreCase(IConstants.LINUX_OS)) {
column.getColumn().setResizable(false);
column.getColumn().setMoveable(false);
} else {
column.getColumn().setResizable(true);
column.getColumn().setMoveable(true);
}
column.getColumn().setData(SPECIAL_FIELD, field);
column.getColumn().setText(field.getFieldName());
tableLayout.addColumnData(new ColumnPixelData(field.getWidth(), false));
column.getColumn().addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent selectionEvent) {
if (selectionEvent.getSource() instanceof TreeColumn) {
TreeColumn column = (TreeColumn)selectionEvent.getSource();
Tree tree = getTree();
if (column.getText().equalsIgnoreCase("") && sortColumn != null) {
// file column clicked - use it to clear any sort order
sortColumn = null;
tree.setSortColumn(sortColumn);
tree.setSortDirection(0);
refresh();
} else {
sortColumn = column;
tree.setSortColumn(sortColumn);
tree.setSortDirection(invertSortDirection(tree.getSortDirection()));
refresh();
}
}
}
#Override
public void widgetDefaultSelected(SelectionEvent selectionEvent) {
// not currently used, but required as part of implementation of SelectionListener interface
}
});
}
tree.setLayout(tableLayout);
tree.setLinesVisible(false);
tree.setHeaderVisible(true);
tree.layout(true);
// prevent expanding/collapsing tree item on dbl click
tree.addListener(SWT.MeasureItem, new Listener() {
#Override
public void handleEvent(Event event) {
// nothing
}
});
}
private int invertSortDirection(int sortDirection) {
if (sortDirection != SWT.UP && sortDirection != SWT.DOWN) {
return SWT.UP;
} else if (sortDirection == SWT.UP) {
return SWT.DOWN;
}
return SWT.UP;
}
#Override
public void refresh() {
super.refresh();
}
#Override
public void refresh(boolean updateLabels) {
super.refresh(updateLabels);
}
}
I inherited this code, so there are some peculiar things that fixed bugs that I won't touch without knowing it won't produce a regression in QA, such as the crude way preventing expanding/collapsing tree item on double-click is implemented. In fact, the only part of this particular code I amended thus far is the insertion of the addSelectionListener closure for handling column header clicks, and the invertSortDirection method.
What happens when I run this and click on the headers is as I expect. I see the UI caret indicating the sort direction on column index 1 or 2, but I do not see the data sorted. Clicking the header of column index 0 will clear the sort column and the order. If the data was sorted, I'd like the viewer to refresh in the UI to its original loaded state before any column ordering is requested.
On the prior question (linked at top), I interpreted that if sorting by label text was required, I should just add the this.setComparator(new ViewerComparator()); line. I've no idea what I would override or change if I have to write a class that extends ViewComparator.
None of the derived classes from the above code implement a listener on a column. I can trace the code, and the above code for handling header clicks does execute.
So, do I need to extend ViewComparator and what should I be changing in it to get the desired behaviour, if I do?
(I can also probably do away with the TreeColumn sortColumn field since the tree itself 'remembers' this. The Google Guice injected services are used by derivations of this abstract tree viewer)
UPDATE 1:
My intention was to show a derived class of this generic viewer defined above, but after I examined this, it was clear it shows little of use for the current issue of why the sort does not occur.
I had found what I thought was the 'smoking gun' of why the sort does not occur in the custom label provider itself from one of my predecessors that I've inherited the project from. Here's the label provider:
public class MyCustomLabelProvider extends LabelProvider implements ITableLabelProvider {
final IDecoratorManager decorator;
public MyCustomLabelProvider() {
decorator = PlatformUI.getWorkbench().getDecoratorManager();
}
#Override
public Image getImage(Object element) {
return super.getImage(element);
}
#Override
public String getText(Object element) {
return null;
}
#Override
public Image getColumnImage(Object element, int columnIndex) {
if (element instanceof MyTreeItem) {
if (columnIndex == 0) {
final MyTreeItem item = (MyTreeItem)element;
switch (item.getType()) {
// snipped cases returning different images
}
}
}
return null;
}
#Override
public String getColumnText(Object element, int columnIndex) {
if (element instanceof MyTreeItem) {
return showColumns((MyTreeItem) element, columnIndex);
}
return null;
}
private String showColumns(MyTreeItem element, int columnIndex) {
if (columnIndex == 0) {
return element.getName();
}
if (columnIndex == 1) {
return String.valueOf(element.getCustomProperty1());
}
if (columnIndex == 2) {
return String.valueOf(element.getCustomProperty2());
}
return "";
}
}
Via tracing the ViewerComparator code, the program eventually calls getText which always returning null.
The ViewerComparator transpires only to attempt to grab the label text, which due to the above is null, which it amends to an empty String. It then uses the Java String compareTo method for the comparison. Since both are "", there is no comparison result to signal the elements order needs to be swapped.
I wondered about changing the getText method to somehow obtain the original column index of the clicked column and to have logic in it to determine which property to read from my underlying data object used to populate a row in the viewer. For me, this transpired to not work because the underlying object I used has non-String properties that are used to populate 2 of the 3 columns.
User greg-449 had indicated in comments I would need to extend and override the ViewerComparator to make my own version, but until I got this far, or until he stated ...
The standard ViewerComparator only supports one column
... it had not been clear why. The originally linked post doesn't have that clarification. Or at least, not at time of writing this.
At the point he mentioned that, I had not indicated the issue as resolved, just that I thought I had found the issue. I had simply started with the ViewerComparator, traced running code, and found the reason the existing comparator could not re-order the items, assuming that would likely be the end of it once I update code.
I would go further to what greg-449 said, in that even if you have a single column, the default ViewerComparator will not support comparing elements where the property of the underlying data object is not a Java String. You need to implement your own comparator for that. Thus is became clear why greg-449 suggested that at the outset of me stating I had 3 columns - but I remained confused because I simply thought I had text data on the 2 columns I wanted to be sortable, even if that text is actually converted from an int. I just thought the linked post I read was probably apt because it mentioned sorting on text, without mentioning the limitation of a single column, or Java String data types.
So moving on, I have now got my code working as I wanted. More importantly, I did not have to change the getText method, since this was called specifically by the default ViewerComparator and I found an approach to follow where this wasn't needed. I shall be posting these in the answer.
So in addition to my updates in the question...
I tried to find the example of a different comparator that greg-449 referenced, but the specific package was not available in my environment if I tried to import it.
I then searched for a means to writing a custom comparator and found a Vogella post:
https://www.vogella.com/tutorials/EclipseJFaceTable/article.html#sort-content-of-table-columns
I noticed that the column index issue I mentioned above was handled by creating a handler per column in the Vogella code. I mostly copied it, with slight changes to how it performs the comparison to meet my requirements:
public class MyCustomViewerComparator extends ViewerComparator {
private int propertyIndex;
private static final int DESCENDING = 1;
private int direction;
public MyCustomViewerComparator() {
this.propertyIndex = 0;
direction = DESCENDING;
}
public int getDirection() {
return direction == 1 ? SWT.DOWN : SWT.UP;
}
public void setColumn(int column) {
if (column == this.propertyIndex) {
// Same column as last sort; toggle the direction
direction = 1 - direction;
} else {
// New column; do an ascending sort
this.propertyIndex = column;
direction = DESCENDING;
}
}
#Override
public int compare(Viewer viewer, Object e1, Object e2) {
MyTreeItem p1 = (MyTreeItem) e1;
MyTreeItem p2 = (MyTreeItem) e2;
int rc = 0;
switch (propertyIndex) {
case 1:
rc = p1.getCustomProperty1() - p2.getCustomProperty1();
break;
case 2:
rc = p1.getCustomProperty2() - p2.getCustomProperty2();
break;
default:
rc = 0;
}
// If descending order, flip the direction
if (direction == DESCENDING) {
rc = -rc;
}
return rc;
}
}
As can be seen, we have a standard compare function that returns a negative number, zero when matching, or a positive number, that indicates which order two items should be in. Or as the standard JavaDoc states:
the value {#code 0} if the argument string is equal to
* this string; a value less than {#code 0} if this string
* is lexicographically less than the string argument; and a
* value greater than {#code 0} if this string is
* lexicographically greater than the string argument.
Just in my version, the compare is using int values from my data object instead.
In addition to this, if the user clicked the column header of the column that by default is column index 0, I wanted it to clear any sort and return to the format the viewer was initially loaded as.
To achieve this, I simply changed the SelectionListener I originally used in MyTreeViewer (see second code listing in question) for each column, and made it use the following from the Vogella example (again tweaked):
private SelectionAdapter getSelectionAdapter(final TreeColumn column,
final int index) {
SelectionAdapter selectionAdapter = new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
comparator.setColumn(index);
if (index == 0) {
viewer.getTree().setSortDirection(0);
viewer.getTree().setSortColumn(null);
} else {
int dir = comparator.getDirection();
viewer.getTree().setSortDirection(dir);
viewer.getTree().setSortColumn(column);
}
viewer.refresh();
}
};
return selectionAdapter;
}
The if (index == 0) check in the above, clears the sorting for me when true, otherwise sorts on the whichever other column header has been clicked. Since the column index pertains to how the columns were set up, they are not affected by having movable columns in the UI. You can change the visible column ordering without deleterious effects.
From what I've learnt, it's only the logic for comparing elements that is instrumental and would need overriding in a custom comparator. Outside of this, the only thing to recognize is you then want the comparator specifically wired to each column, by implementing the SelectionAdapter interface and adding this to the column, while also being able to track the column indexes. The Vogella link does show this. Basically you will see on the comparator that there exists a setColumn method, and this is used in the SelectionAdapter to set the column index to be tested in the compare.
I've a native function called get, I'm checking the returned value in while loop by this function. If this returned value is 1, I continue to get different returned value. However, as you predict it cause infinite loop in this way. So that, I also want to check the stop button is pressed to break infinite while loop. How can I do that?
My Native Function
int rValue = get(); // I get returned value here from native get() function
while(rValue == 1)
{
rValue = get(); // I'm trying to get different returned value here
if(stopButton.getModel().isPressed() == true) // I tried something like this but didn't work
break;
}
if(rValue == -1)
{
// do something
}
You have to use Action Listener to achieve this
Something like this,
stopButton.addActionListener( new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println("Stop Button Clicked");
}
});
I am trying to display an arraylist in a gui. However I am getting some troubles. I need to check if my game is legal, if it is not legal then it calls getProblems which displays the arraylist. I tried to call getProblems directly in the GUI class however it will show the array as empty. (Since it's not checking if it's legal). I also tried to call isLegal then getProblems but you cannot do this in a JOptionPane. Any tips on how I can call it accross?
GetProblems class
protected List < String > getProblems() {
return displayOutput;
}
IsLegal Class
public boolean isLegal() {
boolean legality;
if (checkRowConstraints().isEmpty()) {
legality = true;
} else {
getProblems();
legality = false;
}
return legalCheck;
}
GUI:
public void actionPerformed(ActionEvent e) {
if (!(puzzle.isLegal())) {
JOptionPane.showMessageDialog(FutoshikiFrame.this,
puzzle.getProblems(),
"You made a mistake!",
JOptionPane.INFORMATION_MESSAGE);
Here is difference between Actual display of GUI result and result i'm trying to get.
Further Problem found:
I need to return the arraylist then empty it. Fixed
Presently, there is an implicit call to the List's toString() method when you call puzzle.getProblems() within the JOptionPane. So rather than get the contents of the List, which is what you want, you're getting whatever toString() is giving you.
You're not going to get the contents of the List unless you iterate over it first.
You could try something like this. (Note, this is untested code. For demo purposes.)
String formattedString = "";
//let's iterate over our List and build a formatted string for output
for(String element : puzzle.getProblems())
{
formattedString += element;
}
Then you can output this formatted String
public void actionPerformed(ActionEvent e) {
if (!(puzzle.isLegal())) {
JOptionPane.showMessageDialog(FutoshikiFrame.this,
formattedString,
"You made a mistake!",
JOptionPane.INFORMATION_MESSAGE);
This is an listener for a list component. I get a null pointer error from when people select it, but I am still able to get the information I need from the array. The problem is the compiler still throws a null pointer event every time I click on the list item. How I am able to correctly access the array, while it still throws this error?
class facebookListListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
moodSetter.setEnabled(true);
String name = thePeople[facebookList.getSelectedIndex()].getName();
String mood = thePeople[facebookList.getSelectedIndex()].getMood();
Color lightGrey = new Color(160,160,160);
if(mood == null){
thePersonsMood.setText("default_mood");
thePersonsMood.setBackground(lightGrey);
}
if(mood.equalsIgnoreCase("happy")){
thePersonsMood.setText(name+"'s mood is " + mood);
thePersonsMood.setBackground(Color.RED);
}else{
thePersonsMood.setText(name+"'s mood is " + mood);
thePersonsMood.setBackground(lightGrey);
}
}
}
Ah, change this:
}
if(mood.equalsIgnoreCase("happy")){
to this:
} else // **** note the else!!!
if(mood.equalsIgnoreCase("happy")){
Otherwise you'll go into the if block even if the if (mood == null) test is true.