簡體   English   中英

JTable上的自定義單元格返回錯誤值(並且無法正確顯示)

[英]Custom cells on a JTable returning wrong values (and not displaying correctly)

我正在編寫一個自定義POS系統,允許用戶直接在桌子上更改數量,而不是生成對話框。 這是表中包含虛擬數據的第一行。 (我尚未將其鏈接到數據庫。) 在此處輸入圖片說明

Price和Amt都有自定義單元格渲染器(不是任何人都可以告訴他們,因為它們渲染不正確)以顯示貨幣格式。 編輯:我取消了自定義編輯器 (不是渲染器,謝謝),下面的問題仍然存在

計划是,當用戶在數量框中鍵入一個數量時,它將更新amt單元(以及屏幕頂部的運行總計)。 為此,我創建了一個驗證器,該驗證器將驗證數據是否為整數,並將其附加到自定義單元格編輯器中,該編輯器將驗證器添加到JTextField中。

我的驗證程序嵌套在屏幕本身中,因此可以訪問屏幕的字段和表本身。 我想將其放入表模型中,但發現無法分辨出用戶選擇了哪個單元格。 (Verify()有效,因此我省略了)

class QtyVerifier extends InputVerifier
{
    private int qty = 0;
    private BigDecimal pricePerUnit;
    private BigDecimal prevamt;

    @Override
    public boolean shouldYieldFocus(JComponent input) 
    {
        //reset quantity
        this.qty = 0;

        //verify the results
        boolean ok2go = this.verify(input);

        if (ok2go)
        {
            //grab all the current values
            this.qty = new Integer(
                    (String)salesOrderFormTable.getValueAt(rowselected, colselected));
            this.pricePerUnit = new BigDecimal(
                    (String)salesOrderFormTable.getValueAt(rowselected, colselected));
            this.prevamt = new BigDecimal( 
                    (String)salesOrderFormTable.getValueAt(rowselected, colselected));


            //remove previous amount from the total
            addLineCostToRunningTotal(this.prevamt.negate());
            //update sales order total
            addLineCostToRunningTotal(amt);

            //update line total cell
            salesOrderFormTable.setValueAt(actualTotal, rowselected, 6);
            salesOrderFormTable.validate();
        }
        else { ... }
        return ok2go;
    }

    ....
};

這真的很奇怪。 我告訴數量,數量仍然為1。它從單元格中提取所有正確的數據。

Selected: 0,1
Quantity in cell 0,1 is 1
Line price is 1.0
Previous amt is 1.0
New amt is 1.0

好的。 因此,我將值更改為5,然后按Enter。 在此處輸入圖片說明 它將值更改為25 (解決了此問題),還從單元格中提取了錯誤的數據。

Quantity in cell 0,1 is 5 //this is correct
Line price is 5.0 //this is incorrect. It should be 1.
Previous amt is 5.0 //also incorrect. This also should be 1.
New amt is 25.0 //this WOULD be correct if the previous data was.

我的桌子怎么了?! 為什么這會在兩個單元格中給我完全錯誤的信息, 並將qty單元格更改為我未鍵入的內容 有沒有更簡單的方法(使用或不使用驗證程序)來做到這一點? 我不能在訂單上有錯誤的費用。 我考慮過將所有值從double更改為BigDecimals以防止舍入錯誤,但這甚至不是舍入錯誤。 這是完全錯誤的。 我現在完全迷路了。

鑒於您的代碼是高度定制的並且很難在沒有所有內容的情況下進行調試,因此我將從頭開始呼吁基本概念,並說使用TableModel可以滿足這些要求:

  • 驗證數字列的輸入:如果表模型中的getColumnClass(...)返回適當的類,則可以將其委托給正確的編輯器。 無需自定義編輯器!
  • 更新qtyprice列上的amt列更新:也可以使用表模型完成此操作,只需要正確覆蓋setValueAt(...)
  • 顯示priceamt與貨幣格式列:這是可以做到提供自定義渲染器(未編輯)。

由於沒有有關您的表模型的信息,因此我將使用DefaultTableModel來說明上述幾點:

String[] header = new String[] { "qty", "price", "amt" };
DefaultTableModel model = new DefaultTableModel(header, 1) {

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0: return Integer.class;
            case 1: 
            case 2: return Double.class;
        }
        throw new ArrayIndexOutOfBoundsException(columnIndex);
    }

    @Override
    public boolean isCellEditable(int row, int column) {
        return column < 2;
    }

    @Override
    public void setValueAt(Object aValue, int row, int column) {
        super.setValueAt(aValue, row, column);
        if (column < 2) {
            Integer qty = (Integer)getValueAt(row, 0);
            Double price = (Double)getValueAt(row, 1);
            Double amt = (qty != null && price != null) 
                       ? (Double)(qty * price)
                       : null;
            super.setValueAt(amt, row, 2);
        }
    }
};

有關示例的一些注意事項:

  1. 在此示例中,我僅設置了實際上很重要的三列: qtypriceamt
  2. 只有qtyprice列是可編輯的,而amt是不可編輯的(它是在更新其他列時計算的)。
  3. 給定getColumnClass()實現,默認的編輯器將不允許任何數字列都為無效輸入:列類是否為Integer,它將僅允許整數值。 Double類也是如此。
  4. 如果修改了qtyprice列,則會調用setValueAt(...)並相應地更新amt列。

最后,要在渲染單元格(不對其進行編輯)時應用貨幣格式,我們需要提供一個自定義渲染器。 例如:

class CurrencyRenderer extends DefaultTableCellRenderer {

    private final NumberFormat currencyFormat;

    public CurrencyRenderer() {
        currencyFormat = NumberFormat.getCurrencyInstance();
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        Component renderer = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        if (value instanceof Number) {
            setText(currencyFormat.format((Number)value));
        }
        return renderer;
    }
}

現在,有多種提供渲染器的方法,下面對所有方法進行了說明: 概念:編輯器和渲染器

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM