SpinnerModel functioning example Java Swing - java

I am trying allready to make custome model for JSpinner but it doesnt work.
the code looks like:
public class ModelJSpinner implements SpinnerModel
{
private long value;
private long min;
private long max;
private long increment;
private ChangeListener l;
private ArrayList<ChangeListener> listeners;
#Override
public Object getValue()
{
return null;
}
public ModelJSpinner(long min, long max, long increment)
{
super();
this.min = min;
this.max = max;
this.increment = increment;
setValue(min);
listeners = new ArrayList<>();
}
#Override
public void setValue(Object value)
{
if (value == null)
{
}else {
this.value = (Long) value;
}
//fireStateChanged();
}
private void fireStateChanged()
{
if (listeners == null)
return;
for (int a = 0; a < listeners.size(); a++)
{
ChangeListener l = (ChangeListener) listeners.get(a);
try
{
l.stateChanged(new ChangeEvent(this));
}
catch (RuntimeException e)
{
e.printStackTrace();
}
}
}
#Override
public Object getNextValue()
{
Long nextValue = value + increment;
if (nextValue > max)
{
return null;
}
else
{
return nextValue;
}
}
#Override
public Object getPreviousValue()
{
Long previousValue = value - increment;
if (previousValue < min)
{
return null;
}
else
{
return previousValue;
}
}
#Override
public void addChangeListener(javax.swing.event.ChangeListener l)
{
this.l = l;
listeners.add(l);
}
#Override
public void removeChangeListener(javax.swing.event.ChangeListener l)
{
if (this.l == l)
{
l = null;
}
listeners.add(l);
}
}
However when i run the following code i get...nothing much except JSpinner that doesnt do much...
public class Test
{
public static void main(String[] args)
{
ModelJSpinner model = new ModelJSpinner(10L, 20L, 5L);
JSpinner spinner = new JSpinner(model);
spinner.setModel(model);
spinner.setValue(15L);
JFrame frame = new JFrame("adasasd");
frame.setSize(350, 150);
frame.add(spinner);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
}
At the beginning, all i wanted was just to see that JSpinner can do something with above mentioned Model and later i wanted to implement Changelisteners.
As of now, i am not even able to have it drawn properly. Is there a chance that somebody could help me?
I need to use instance of Class implementing SpinnerModel as model for JSpinner and i just cannot make it work.
BR
DK

This is a guarantee to fail:
#Override
public Object getValue()
{
return null;
}
since this is the method that the JSpinner uses to determine what value to display.
Instead have this return the value held by your value field. Also, don't return null for the getNextValue() if next value is above max. Instead return the max. Similarly for the getPreviousValue(), return the min value if the calculated previous value is less than min.
For example,
public class SpinnerModel3 implements SpinnerModel {
private long value;
private long min;
private long max;
private long increment;
// using a set to avoid allowing addition of duplicate listeners
private Set<ChangeListener> listenerSet = new HashSet<>();
public SpinnerModel3(long value, long min, long max, long increment) {
super();
this.value = value;
this.min = min;
this.max = max;
this.increment = increment;
}
#Override
public void addChangeListener(ChangeListener l) {
listenerSet.add(l);
}
#Override
public Object getNextValue() {
long nextValue = value + increment;
nextValue = Math.min(nextValue, max);
return nextValue;
}
#Override
public Object getPreviousValue() {
long prevValue = value - increment;
prevValue = Math.max(prevValue, min);
return prevValue;
}
#Override
public Object getValue() {
return value;
}
#Override
public void removeChangeListener(ChangeListener l) {
listenerSet.remove(l);
}
#Override
public void setValue(Object value) {
this.value = (long) value;
fireStateChanged();
}
protected void fireStateChanged() {
// create a ChangeEvent object
ChangeEvent e = new ChangeEvent(this);
for (ChangeListener l : listenerSet) {
l.stateChanged(e); // notify all listeners
}
}
}
Note that it is usually better to use the extend the abstract model class if one is available (or even better, the default model class, but none is available for spinner model). So better still:
#SuppressWarnings("serial")
public class SpinnerModel2 extends AbstractSpinnerModel {
private long value;
private long min;
private long max;
private long increment;
public SpinnerModel2(long value, long min, long max, long increment) {
super();
this.value = value;
this.min = min;
this.max = max;
this.increment = increment;
}
#Override
public Object getNextValue() {
long nextValue = value + increment;
nextValue = Math.min(nextValue, max);
return nextValue;
}
#Override
public Object getPreviousValue() {
long prevValue = value - increment;
prevValue = Math.max(prevValue, min);
return prevValue;
}
#Override
public Object getValue() {
return value;
}
#Override
public void setValue(Object value) {
this.value = (long) value;
fireStateChanged();
}
}

Related

Custom JSpinner Model not working

I tried to implement my own JSpinner model to accept an enumeration (including I18N), so I did like that:
searchSpinner.setModel(new AbstractSpinnerModel() {
int index = 0;
int minIndex = 0;
int maxIndex = MY_ENUM.values().length - 1;
Object selected = MY_ENUM.values()[index];
#Override
public Object getValue() {
return selected;
}
#Override
public void setValue(Object value) {
selected = value;
fireStateChanged();
}
#Override
public Object getNextValue() {
if (index < maxIndex) {
index++;
}
fireStateChanged();
return MY_ENUM.values()[index];
}
#Override
public Object getPreviousValue() {
if (index > minIndex) {
index--;
}
fireStateChanged();
return MY_ENUM.values()[index];
}
#Override
public void addChangeListener(ChangeListener l) {
}
#Override
public void removeChangeListener(ChangeListener l) {
}
});
The problem is that did not work, and even the spinner list looks like disabled. What am I doing wrong?
UPDATE: Based on first answer
You should extend from AbstractSpinnerModel (note to folks new to his question -- note that his original question had the class implementing the SpinnerModel interface. He later changed his code to reflect my recommendation) and be sure to call the fireStateChanged() method when appropriately. Also you've not taken into account edge cases and beyond edge cases.
e.g.,
import javax.swing.*;
import javax.swing.JSpinner.DefaultEditor;
public class MySpinnerPanel extends JPanel {
public static void main(String[] args) {
JSpinner spinner = new JSpinner(new MyEnumSpinnerModel());
JSpinner.DefaultEditor editor = (DefaultEditor) spinner.getEditor();
editor.getTextField().setColumns(5);
JPanel panel = new JPanel();
panel.add(spinner);
JOptionPane.showMessageDialog(null, panel);
}
}
enum MyEnum {
FE, FI, FO, FUM, FOO, FUBAR, SPAM
}
class MyEnumSpinnerModel extends AbstractSpinnerModel {
private int index = 0;
#Override
public Object getValue() {
return MyEnum.values()[index];
}
#Override
public void setValue(Object value) {
if (value instanceof MyEnum) {
index = ((MyEnum) value).ordinal();
fireStateChanged();
} else {
String text = value.toString() + " is not a valid enum item";
throw new IllegalArgumentException(text);
}
}
#Override
public Object getNextValue() {
if (index >= MyEnum.values().length - 1) {
return null;
} else {
return MyEnum.values()[index + 1];
}
}
#Override
public Object getPreviousValue() {
if (index <= 0) {
return null;
} else {
return MyEnum.values()[index - 1 ];
}
}
}
Edit
Note that the model itself should not require a listener to notify the view (as per the other answer to this question) as that's what the AbstractSpinnerModel does internally. It's fireStateChange() method is what the model itself should call to trigger this notification, same as most all other similar model structures in Swing such as any TableModel object that you create that derives from the AbstractTableModel. For details, please see the source code for the SpinnerListModel. Your code should emulate this class.
You should use ChangeListener to notify the view of changes in the model.
spinner = new JSpinner(new SpinnerModel() {
private ChangeListener l;
#Override
public void setValue(Object value) {
...
if(l != null) {
l.stateChanged(new ChangeEvent(this));
}
}
...
#Override
public void addChangeListener(ChangeListener l) {
this.l = l;
}
#Override
public void removeChangeListener(ChangeListener l) {
if(this.l == l) {
this.l = null;
}
}
});
Edit: You can use List to register many listeners.

Java to C++ conversion

I am trying to convert some java code to c++, however, I am having an issue with java's list.add versus c++ list.insert. Here is the java code that I've started to convert:
public class SimulationQueue {
private String arrivalFilePath;
private int currentTime;
private class Event {
private boolean arrival;
private int start;
private int span;
public Event() {
this.arrival = true;
this.start = 0;
this.span = 0;
}
public Event(boolean isArrival, int startTime, int span) {
this.arrival = isArrival;
this.start = startTime;
this.span = span;
}
public int at() { return start; }
public boolean isArrival() { return arrival; }
public int duration() { return span; }
public void getArrivalEvent(Scanner arrivalFile) {
this.arrival = true;
this.start = arrivalFile.nextInt();
this.span = arrivalFile.nextInt();
}
}
public SimulationQueue(String arrivalFilePath) {
this.arrivalFilePath = arrivalFilePath;
this.currentTime = 0;
}
private void addEventToList(Event event, List<Event> eventList) {
if (eventList.isEmpty()) eventList.add(0, event);
else if (eventList.get(0).at() < event.at()) eventList.add(event);
else eventList.add(0, event);
}
And here is the so far converted c++ version:
struct EventList {
bool arrival;
int start, span, currentTime;
string arrivalFilePath;
EventList(bool isArrival, int startTime, int span);
void getArrivalEvent(istream& arrivalFile);
void simulationQueue (string arrivalFilePath);
void addEventToList(EventList& event, list<EventList> eventList);
void simulate();
EventList() {
this->arrival = true;
this->start = 0;
this->span = 0;
}
int at() {
return start;
}
bool isArrival() {
return arrival;
}
int duration() {
return span;
}
};
EventList::EventList(bool isArrival, int startTime, int span) {
this->arrival = isArrival;
this->start = startTime;
this->span = span;
}
void EventList::getArrivalEvent(istream& arrivalFile) {
this->arrival = true;
int first = this->start;
int duration = this->span;
arrivalFile >> first;
arrivalFile >> duration;
}
void EventList::simulationQueue (string arrivalFilePath) {
this->arrivalFilePath = arrivalFilePath;
this->currentTime = 0;
}
void EventList::addEventToList(EventList& event, list<EventList> eventList) {
if (eventList.empty())
}
I'm not very experienced so I know I'm probably approaching this wrong but it's compiling alright. The issue I have is with:
void EventList::addEventToList(EventList& event, list<EventList> eventList) {
if (eventList.empty())
}
I don't know how to convert this part to c++:
private void addEventToList(Event event, List<Event> eventList) {
if (eventList.isEmpty()) eventList.add(0, event);
else if (eventList.get(0).at() < event.at()) eventList.add(event);
else eventList.add(0, event);
}
If I write something like event.insert(event, 0) then it won't fit the parameters that insert takes.
You can just use list::push_back.
void EventList::addEventToList(EventList& event, list<EventList> eventList) {
eventList.push_back(event);
}
However, if you leave it just like that, the calling function won't see the new item in the list since you passed eventList to the function by value. You need to pass it by reference.
void EventList::addEventToList(EventList& event, list<EventList>& eventList) {
eventList.push_back(event);
}
list::push_back adds items to the end (back) of the list. If you'd rather add the item at the start (front) of the list, you can use list::push_front.
void EventList::addEventToList(EventList& event, list<EventList>& eventList) {
eventList.push_front(event);
}

Java LinkedList with Object

Trying to implement a LinkedList that simulates a Portfolio, consisting of Stock objects. I'm struggling to figure out how to properly iterate through the list and check if each stock contains certain parameters. the SHAREPRICE method is the one I'm having trouble with specifically, if someone could help with that, I'd be very grateful. What I have so far:
import java.util.*;
public class Portfolio<AnyType> implements Iterable<AnyType> {
public int balance, shares;
private Stock<AnyType> beginMarker, endMarker, temp;
LinkedList<Stock> Portfolio = new LinkedList<Stock>();
java.util.Iterator<Stock> iter = Portfolio.iterator();
public int CASHIN(int x) {
balance = x;
return balance;
}
public int CASHOUT(int y) {
balance = balance + (-y);
return balance;
}
public int CASHBALANCE() {
return balance;
}
public void BUY(String t, int s, float pp) {
temp = new Stock<AnyType>(t, s, pp, pp, 0, null, null);
Portfolio.add(temp);
shares = shares + s;
}
public void SELL(String t, int s, float pp) {
shares = shares - s;
}
public void SHAREPRICE(String t, float pp)
{
if(Portfolio.contains(Stock.)
{
}
}
public void QUERY(String t) {
}
public int COUNTPORTFOLIO() {
return shares;
}
public void PRINTPORTFOLIO() {
}
public java.util.Iterator<AnyType> iterator() {
return new Iterator();
}
private class Iterator implements java.util.Iterator<AnyType> {
private Stock<AnyType> current = beginMarker.next;
private boolean okToRemove = false;
public boolean hasNext() {
return current != endMarker;
}
public AnyType next() {
if (!hasNext())
throw new java.util.NoSuchElementException();
AnyType nextItem = (AnyType) current.getTicker();
current = current.next;
okToRemove = true;
return nextItem;
}
public void remove() {
if (!okToRemove)
throw new IllegalStateException();
Portfolio.this.remove(current.prev);
okToRemove = false;
}
}
private class Stock<AnyType> implements Comparable<Stock<AnyType>> {
public String getTicker() {
return ticker;
}
public void setTicker(String ticker) {
this.ticker = ticker;
}
public float getPurchasePrice() {
return purchasePrice;
}
public void setPurchasePrice(float purchasePrice) {
this.purchasePrice = purchasePrice;
}
public float getLatestPrice() {
return latestPrice;
}
public void setLatestPrice(float latestPrice) {
this.latestPrice = latestPrice;
}
public float getPctChange() {
return pctChange;
}
String ticker;
int sharesOwned;
float purchasePrice, latestPrice;
float pctChange = (latestPrice - purchasePrice) / purchasePrice;
Stock<AnyType> prev, next;
public Stock(String ticker, int sharesOwned, float purchasePrice,
float latestPrice, float pctChange, Stock<AnyType> prev,
Stock<AnyType> next) {
this.ticker = ticker;
this.sharesOwned = sharesOwned;
this.purchasePrice = purchasePrice;
this.latestPrice = latestPrice;
this.pctChange = pctChange;
this.prev = prev;
this.next = next;
}
public int compareTo(Stock<AnyType> pctChange) {
return ((Comparable) this.pctChange)
.compareTo(Stock.getPctChange());
}
}
}
class TestPortfolio {
public static void main(String[] args) {
}
}
Forward Direction:
while(itr.hasNext())
{
System.out.println(itr.next());
}
Reverse Direction
while(itr.hasPrevious())
System.out.println(itr.previous());
}

How to delete a specific element from a priority queue?

I have created a priority queue using the Java API and I want to remove a specific element from the priority queue at the end of the program. I know it has to do something with the comparator but I can't figure it out. Can someone help? Here's my code:
public static void main(String[] args)
{
PriorityQueue<Element> X = new PriorityQueue<Element>(100, new ElementComparator());
X.add(new Element(30, 3));
X.add(new Element(700, 4.5));
X.add(new Element(100, 6.2));
X.add(new Element(2, 8.1));
System.out.println(X.remove(new Element(100, 6.2)));
}
and here's my Element class:
private int index;
private double value;
public Element(int i, double v)
{
index = i;
value = v;
}
public int getIndex() { return index;};
public double getValue() { return value;};
public void setValue(double v) { value = v;};
And here's the comparator that I created:
public int compare(Element o1, Element o2)
{
int idx1 = o1.getIndex();
int idx2 = o2.getIndex();
if (idx1 < idx2) {
return -1;
} else if (idx1 > idx2) {
return 1;
} else {
return 0;
}
}
public boolean equals(Element o1, Element o2)
{
return o1.getIndex() == o2.getIndex();
}
I appreciate your help...
You need to define equals() and hashcode() on your Element object as such:
public class Element{
private int index;
private double value;
public Element(int i, double v)
{
index = i;
value = v;
}
public int getIndex() { return index;}
public double getValue() { return value;}
public void setValue(double v) { value = v;}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Element)) return false;
Element element = (Element) o;
if (index != element.index) return false;
return true;
}
#Override
public int hashCode() {
return index;
}
}
Defining equals() on the ElementComparator does not perform the same task.

GWT editors and get/set value

I have following editor class, and I'm curious what's wrong with it. When running, it does correctly set the right radio button as selected. However, when flushing the top level editor, getValue is never called, and my object's property never get updated. Here's the code (hint - modified ValueListBox):
public class ValueRadioList<T> extends FlowPanel implements
HasConstrainedValue<T>, LeafValueEditor<T>, ValueChangeHandler<Boolean> {
private final List<T> values = new ArrayList<T>();
private final Map<Object, Integer> valueKeyToIndex =
new HashMap<Object, Integer>();
private final String name;
private final Renderer<T> renderer;
private final ProvidesKey<T> keyProvider;
private T value;
public ValueRadioList(Renderer<T> renderer) {
this(renderer, new SimpleKeyProvider<T>());
}
public ValueRadioList(Renderer<T> renderer, ProvidesKey<T> keyProvider) {
super();
this.name = DOM.createUniqueId();
this.keyProvider = keyProvider;
this.renderer = renderer;
}
private void addValue(T value) {
Object key = keyProvider.getKey(value);
if (valueKeyToIndex.containsKey(key)) {
throw new IllegalArgumentException("Duplicate value: " + value);
}
valueKeyToIndex.put(key, values.size());
values.add(value);
RadioButton radio = new RadioButton(name, renderer.render(value));
radio.addValueChangeHandler(this);
add(radio);
assert values.size() == getWidgetCount();
}
#Override public HandlerRegistration addValueChangeHandler(
ValueChangeHandler<T> handler) {
return addHandler(handler, ValueChangeEvent.getType());
}
#Override public T getValue() {
return value;
}
#Override public void onValueChange(ValueChangeEvent<Boolean> event) {
int selectedIndex = -1;
for (int i = 0, l = getWidgetCount(); i < l; i++) {
if (((RadioButton) getWidget(i)).getValue()) {
selectedIndex = i;
break;
}
}
if (selectedIndex < 0) {
return; // Not sure why this happens during addValue
}
T newValue = values.get(selectedIndex);
setValue(newValue, true);
}
#Override public void setAcceptableValues(Collection<T> newValues) {
values.clear();
valueKeyToIndex.clear();
clear();
for (T nextNewValue : newValues) {
addValue(nextNewValue);
}
updateRadioList();
}
#Override public void setValue(T value) {
setValue(value, false);
}
#Override public void setValue(T value, boolean fireEvents) {
if (value == this.value
|| (this.value != null && this.value.equals(value))) {
return;
}
T before = this.value;
this.value = value;
updateRadioList();
if (fireEvents) {
ValueChangeEvent.fireIfNotEqual(this, before, value);
}
}
private void updateRadioList() {
Object key = keyProvider.getKey(value);
Integer index = valueKeyToIndex.get(key);
if (index == null) {
addValue(value);
}
index = valueKeyToIndex.get(key);
((RadioButton) getWidget(index)).setValue(true);
}
}
Solved it, my POJO missed a setter for that field.

Categories