加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 05:07:31 所属栏目:Java 来源:网络整理
导读:我有一个jtable,我根据模型的值重新着色行,如下所示: resultTable = new javax.swing.JTable(){ private Border outside = new MatteBorder(1,1,Color.BLACK); private Border inside = new EmptyBorder(0,1); private Border highlight = new CompoundBord
我有一个jtable,我根据模型的值重新着色行,如下所示:

resultTable = new javax.swing.JTable(){
    private Border outside = new MatteBorder(1,1,Color.BLACK);
    private Border inside = new EmptyBorder(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
      }
  }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读