java/TableModel объектов/Обновить объект"

У меня есть коллекция объектов Stock, для которых я обновляю около 10/15 переменных в режиме реального времени. Я получаю доступ к каждой акции по ее идентификатору в коллекции. Я также пытаюсь отобразить это в JTable и реализовал модель AbstractTable. Это не работает слишком хорошо.

У меня есть RowMap, к которому я добавляю каждый идентификатор, когда акции добавляются в TableModel. Чтобы обновить цены и переменные всех акций в TableModel, я хочу отправить объект Stock в метод updateModel(Stock s). Я могу найти соответствующую строку, выполнив поиск на карте, но как мне правильно с этим справиться, поэтому мне не нужно начинать итерацию по столбцам таблицы и сравнивать значения ячеек с переменными объекта, чтобы увидеть, есть ли какие-либо отличия??

По сути, я хочу отправить объект Stock в TableModel и обновить ячейки, если есть изменения, и ничего не делать, если их нет.

Любые идеи о том, как реализовать TableModel, которая может это сделать? Любые указатели вообще будут оценены.

Спасибо.

Редактировать:

'импортировать javax.swing.table.AbstractTableModel; импортировать ppwebsitemonitor.views.OrderTableModel.*;

общедоступный окончательный класс QuoteTableModel extends AbstractTableModel {

// Attributes
String[] columnName = new String[]{"Stock", "Quantity", "Price", "Side", "Status"};
Class[] columnClass =
        new Class[]{String.class, Integer.class, Double.class, String.class, String.class};
Object[][] rows = null;

public QuoteTableModel() {
}

public QuoteTableModel(Object[][] orders) {
    this.rows = orders;
}

public int getColumnCount() {
    return columnName.length;
}

public boolean isNew(int row) {
    return rows[row][4].equals(OrderStatus.NEW);
}

public boolean isFilled(int row) {
    return rows[row][4].equals(OrderStatus.FULLY_FILLED);
}

public boolean isCancelled(int row) {
    return rows[row][4].equals(OrderStatus.CANCELLED);
}

public void updateOrderPrice(int row, Double newPrice) {

    Object[] order = rows[row];
    order[2] = newPrice;
    super.fireTableRowsUpdated(row, row);
}

public void updateOrderStatus(int row, int status) {

    Object[] order = rows[row];
    order[4] = OrderStatus.States[status];
    super.fireTableRowsUpdated(row, row);
}

public Object getValueAt(int row, int col) {
    return rows[row][col];
}

public int getRowCount() {
    return rows.length;
}

public String getColumnName(int col) {
    return columnName[col];
}

public Class getColumnClass(int col) {
    return columnClass[col];
}

}'


person Community    schedule 24.06.2011    source источник


Ответы (1)


Вместо того, чтобы хранить идентификаторы акций в вашей модели таблицы, вы можете хранить сами объекты Stock. Те самые, которые вы держите в своей мастер-коллекции. Затем отправьте обновление в пользовательский интерфейс таблицы каждый раз, когда вы обновляете значение запаса (или устанавливаете его на синхронизированное обновление или что-то еще, что требуется вашей программе).

Изменить

Я включаю некоторый код, чтобы проиллюстрировать, что я имел в виду. Это чуть выше псевдокода, вам придется адаптировать его к вашей ситуации.

Это для имитации вашего объекта заказа на акции:

import java.io.Serializable;

public class StockOrder implements Serializable{
    public final class OrderStatus {
        public static final String NEW = "NEW";
        public static final String FULLY_FILLED = "FULLY_FILLED";
        public static final String SHIPPED = "SHIPPED";
        public static final String CANCELLED = "CANCELLED";
    }

    private static final long serialVersionUID = -3627357348101499053L;

    private String ticker;
    private Integer quantity;
    private Double price;
    private String side;
    private String status;

    public StockOrder() {
        super();
    }

    public StockOrder(String ticker, Integer quantity, Double price, String side, String status) {
        this();
        setTicker(ticker);
        setQuantity(quantity);
        setPrice(price);
        setSide(side);
        setStatus(status);
    }

    public Double getPrice() {
        return price;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public String getSide() {
        return side;
    }

    public String getStatus() {
        return status;
    }

    public String getTicker() {
        return ticker;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public void setSide(String side) {
        this.side = side;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public void setTicker(String ticker) {
        this.ticker = ticker;
    }
}

Ваша пользовательская модель будет выглядеть примерно так:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.table.AbstractTableModel;

import misc.test.StockOrder.OrderStatus;

public class QuoteTableModel extends AbstractTableModel {

    private static final long serialVersionUID = -8683294701374710538L;

    // Attributes
    String[] columnName = new String[] { "Stock", "Quantity", "Price", "Side",
            "Status" };
    Class<?>[] columnClass = new Class[] { String.class, Integer.class,
            Double.class, String.class, String.class };
    private List<StockOrder> rows = null;
    private Map<String, Integer> orderMap = null;

    public QuoteTableModel() {
        super();
        setRows(new ArrayList<StockOrder>(8));
    }

    public QuoteTableModel(Collection<StockOrder> orders) {
        super();
        if(orders != null) {
            setRows(new ArrayList<StockOrder>(orders));
        } else {
            setRows(new ArrayList<StockOrder>(8));
        }
    }

    public int getColumnCount() {
        return columnName.length;
    }

    public boolean isNew(int row) {
        StockOrder order = getRows().get(row);
        return OrderStatus.NEW.equals(order.getStatus());
    }

    protected List<StockOrder> getRows() {
        return rows;
    }

    protected void setRows(List<StockOrder> rows) {
        this.rows = rows;
        this.orderMap = new HashMap<String, Integer>((rows != null) ? rows.size() : 8);

        if(rows != null) {
            int i = 0;
            for(StockOrder order: rows) {
                orderMap.put(order.getTicker(), new Integer(i++));
            }
        }
    }

    public boolean isFilled(int row) {
        StockOrder order = getRows().get(row);
        return OrderStatus.FULLY_FILLED.equals(order.getStatus());
    }

    public boolean isCancelled(int row) {
        StockOrder order = getRows().get(row);
        return OrderStatus.CANCELLED.equals(order.getStatus());
    }

    public void updateOrderPrice(int row, Double newPrice) {
        StockOrder order = getRows().get(row);
        if( order != null ) {
            order.setPrice(newPrice);
            super.fireTableRowsUpdated(row, row);
        }
    }

    public void updateOrderPrice(String ticker, Double newPrice) {
        Integer idx = getOrderMap().get(ticker);
        if(idx != null) {
            updateOrderPrice(idx, newPrice);
        }
    }

    public void updateOrderPrice(String ticker, String newStatus) {
        Integer idx = getOrderMap().get(ticker);
        if(idx != null) {
            updateOrderStatus(idx, newStatus);
        }
    }

    public void updateOrderStatus(int row, String newStatus) {
        StockOrder order = getRows().get(row);
        if( order != null ) {
            order.setStatus(newStatus);
            super.fireTableRowsUpdated(row, row);
        }

    }

    public Object getValueAt(int row, int col) {
        StockOrder order = getRows().get(row);
        if(order != null) {

            switch(col) {
                case 0: return order.getTicker() ;
                case 1: return order.getQuantity() ;
                case 2: return order.getPrice() ;
                case 3: return order.getSide() ;
                case 4: return order.getStatus() ;
                default: return "";
            }
        }

        return "";
    }

    public int getRowCount() {
        return getRows().size();
    }

    public String getColumnName(int col) {
        return columnName[col];
    }

    public Class<?> getColumnClass(int col) {
        return columnClass[col];
    }

    protected Map<String, Integer> getOrderMap() {
        return orderMap;
    }

    protected void setOrderMap(Map<String, Integer> orderMap) {
        this.orderMap = orderMap;
    }

}

Вы можете использовать это для тестирования:

import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.TableModel;

import misc.test.StockOrder.OrderStatus;

public class QuoteTableApp {
    public static void main(String[] args) {
        QuoteTableApp app = new QuoteTableApp();
        System.out.println(app);
    }

    private JFrame frame = null;

    public QuoteTableApp() {
        super();
        setFrame(new JFrame("Quotes"));
        getFrame().setLocation(500, 300);
        getFrame().setSize(500, 400);

        List<StockOrder> orders = new ArrayList<StockOrder>(4);
        orders.add(new StockOrder("YHOO", 20, 73.50, "UP", OrderStatus.NEW));
        orders.add(new StockOrder("MSFT", 40, 42.00, "UP", OrderStatus.NEW));
        orders.add(new StockOrder("IBM", 100, 126.75, "UP", OrderStatus.NEW));
        orders.add(new StockOrder("CSCO", 5, 29.32, "UP", OrderStatus.NEW));

        TableModel model = new QuoteTableModel(orders);
        JTable table = new JTable(model);

        getFrame().getContentPane().add(table);
        getFrame().setVisible(Boolean.TRUE);

        ((QuoteTableModel) model).updateOrderPrice("CSCO", 31.20);
    }

    protected void setFrame(JFrame frame) {
        this.frame = frame;
    }

    protected JFrame getFrame() {
        return frame;
    }
}

Этот код не учитывает сортировку, которую вам может понадобиться выполнить. Но основные понятия есть. Надеюсь, это поможет.

person Perception    schedule 24.06.2011
comment
Спасибо за это. Но я не хочу каждый раз обновлять полную коллекцию. Что, если у меня есть 100 акций с 20 столбцами для каждой? Я бы предпочел, чтобы меня называли FireCellChanged, а не FireTableChanged. Я на правильном пути? - person ; 24.06.2011
comment
Что сейчас на вашей карте рядов? А что в вашей конкретной реализации AbstractTableMap? По какой-то причине у меня сложилось впечатление, что вы храните идентификаторы акций в карте таблицы, но теперь это звучит как будто наоборот - вы сохраняете идентификаторы строк в карте строк. - person Perception; 24.06.2011
comment
Ok. Я предполагаю, что вопрос, который я задаю, заключается в следующем: как мне реализовать AbstractTableModel, который использует HashTable, а не массив объектов? Мне нужно иметь возможность добавлять объекты в хеш-таблицу на лету, а также иметь возможность обновлять объекты в хэш-таблице, не зная номера строки. - person ; 29.06.2011