ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java swing:Jtable包含许多模型和自定义渲染器

2019-07-15 00:04:02  阅读:129  来源: 互联网

标签:java swing model jtable


我有一个jtable,我根据模型的值重新着色行,如下所示:

resultTable = new javax.swing.JTable(){
    private Border outside = new MatteBorder(1, 0, 1, 0, Color.BLACK);
    private Border inside = new EmptyBorder(0, 1, 0, 1);
    private Border highlight = new CompoundBorder(outside, inside);
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);
        JComponent jc = (JComponent) c;
        //  Color row based on a cell value
        if (!isRowSelected(row)) {
            c.setBackground(getBackground());
            int modelRow = convertRowIndexToModel(row);
            if (getStatus().equals("status1")) {
                myFirstTableModel model = (myFirstTableModel ) resultTable.getModel();                    
                if ((model.getObjectAtRow(modelRow).getMsg().getRegNumIn() == 3)) {
                    c.setBackground(new Color(255, 244, 148));//YELLOW - needs attension
                } 
            } else if (getStatus().equals("status2")) {
                mySecondTableModel model = (mySecondTableModel) resultTable.getModel();

                if (model.getObjectAtRow(modelRow).getMsg().getTask() == 2) {
                    c.setBackground(new Color(210, 245, 176));//GREEN - got attension
                } 
            } 
        } else if (isRowSelected(row)) {
            jc.setBorder(highlight);
            c.setBackground(new Color(201, 204, 196));
        }
        return c;
    }
};

我根据SwingWorker线程中的var状态设置了不同的模型(myFirstTableModel,mySecondTableModel),并显示“请等待”的模态对话框.

final WaitDialog dialog = new WaitDialog(new javax.swing.JFrame(), true);
    dialog.addWindowListener(new java.awt.event.WindowAdapter() {
});
SwingWorker worker = new SwingWorker() {
    @Override
    protected Object doInBackground() throws Exception {
        setStatus("status2");
        Refresh();
        return 0;
    }
    @Override
    public void done() {
        dialog.dispose();
    }
};

worker.execute();
dialog.setVisible(true);

在Refresh()方法中更改模型:

if (getMainFrameStatus().equals("status2")) {
     @Override
                public void run() {
                    //Update the model here

                    resultTable.setModel(new mySecondTableModel(data));
                }
            });

但是我认为在等待对话框混淆我的表时会调用prepareRendere.但是还没有应用不同的模型.

显然我明白了

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: myFirstTableModel cannot be cast to mySecondTableModel at mySecondTableModel model = (mySecondTableModel) resultTable.getModel();

我可以允许表调用prepareRenderer吗?
如何使这个混乱正常工作?

解决方法:

最好不要将数据(业务)域的详细信息涂抹到视图中.在你的背景下,你可以f.i.实现清洁分离

>定义一个具有状态概念的界面(需要注意,注意……)
>让您的自定义模型实现该接口
>在视图中,通过该界面访问模型的状态

像(未编译,只是一个伪代码片段)

public interface StatusAware {

      enum Status {

           NORMAL,
           GOT_ATTENTION,
           NEEDS_ATTENTION,
           ...

      }
      public Status getStatus(int modelIndex);
} 

public class MyFirstTableModel extends AbstractTableModel implements StatusAware {

       public Statuc getStatus(int modelRow) {
           boolean needsAttention = getObjectAtRow(modelRow).getMsg().getRegNumIn() == 3;
           return needsAttention ? NEEDS_ATTENTION : NORMAL;
       }

       ....
}


public class MySecondTableModel extends AbstractTableModel implements StatusAware {

       public Statuc getStatus(int modelRow) {
           return // the status of the given row
       }

       ....
}

public class MyTable extends JTable { // if you insist on not using JXTable 


      public Component prepareRenderer(...) {
            Component comp = super(...)
            if (getModel() instanceof StatusAware {
                 Status status = ((StatusAware) getModel()).getStatus(convertRowIndexToModel(row));
                 if (NEEDS_ATTENTION == status) {
                       ...
                 } else if (...) {
                      ...
                 } 
            }
            return comp;
       }
}

编辑

类似于SwingX(咳嗽……没有教程,只有api doc,wiki,snippets,swinglabs-demo):

>实现自定义HighlightPredicate:这决定了给定单元格是否应该在视觉上“装饰”.它只有一种实现方法,允许通过ComponentAdapter对数据进行读访问
>使用谓词配置一个预定义的荧光笔(有一大堆)
>将荧光笔添加到表格中

摘录自ComponentAdapter api doc

     HighlightPredicate feverWarning = new HighlightPredicate() {
         int temperatureColumn = 10;

         public boolean isHighlighted(Component component, ComponentAdapter adapter) {
             return hasFever(adapter.getValue(temperatureColumn));
         }

         private boolean hasFever(Object value) {
             if (!value instanceof Number)
                 return false;
             return ((Number) value).intValue() > 37;
         }
     };

     Highlighter hl = new ColorHighlighter(feverWarning, Color.RED, null);
     table.addHighlighter(hl);

编辑2

不直接支持访问不属于模型的数据.虽然它潜伏了一段时间,它似乎永远不足以跳过它:)它有点违反了基本思想:有一个共同的抽象来访问数据而不知道底层组件的类型和模型(荧光笔) / -Predicate和StringValue对于表,列表,树完全相同).

考虑到这一点,您可以通过适配器的目标组件间接获取它:

  if (adapter.getComponent() instanceof JTable) {
      JTable table = (JTable) adapter.getComponent();
      TableModel model = table.getModel();
      if (model instanceof MyModel) {
          int modelRow = adapter.convertRowIndexToModel(adapter.row);
          MyObject object = ((MyModel).getRowObjectAt(modelRow));
          ... // check the object
      }
  }

标签:java,swing,model,jtable
来源: https://codeday.me/bug/20190714/1462184.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有