2017-04-11 57 views
0

好吧,我现在处于这种情况......我在课堂上有渲染器,但不知道如何使用它来使某个单元格的背景变红。这是一个房间租赁应用程序,我有Jtable作为日历,所以我想绘制红色的单元格。所以它应该以某种方式采取特定的列和行,并使该单元格变红。我的渲染器低吼,但正如我所说没有想法如何使用它,因为我新来的Java。真正的问题是如何通过该列和行,我有问题。单元格与其他一些代码一起工作,但那不是我需要的。Java。如何在JTable中绘制特定的单元格?

ublic class TableColour extends javax.swing.table.DefaultTableCellRenderer { 
@Override 
public java.awt.Component getTableCellRendererComponent(javax.swing.JTable table, java.lang.Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
    java.awt.Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
    cellComponent.setBackground(java.awt.Color.RED); 
    return cellComponent; 
} 

}

回答

1

好的哇哦,我可能有一些麻烦搞清楚了这一点。但也许不知何故。你说你不知道我的代码是怎么样的,我有一些基本的渲染器。有一件事要记住,我有2维数组ReservedOne,它保存所占用的房间的行索引和列索引,房间号码日期,时间,直到它保留。所以现在我看看你的例子如何使用我的数组来设置颜色时有点困惑。我希望我不会有精神崩溃

TableModel应模拟这种数据,这是非常重要的,因为它允许API的其余部分是围绕着它

真正的问题我怎么传那列和行,我有问题。单元格与其他一些代码一起工作,但那不是我需要的。

这就是为什么有TableModel包装数据,作为表API将通过rowcolumn信息到TableCellRenderer是很重要的,但它也将通过单元格的值!

public class RoomTableModel extends AbstractTableModel { 

    private Room[][] reservations; 

    public RoomTableModel(Room[][] reservations) { 
     this.reservations = reservations; 
    } 

    @Override 
    public int getRowCount() { 
     return reservations.length; 
    } 

    @Override 
    public int getColumnCount() { 
     return reservations[0].length; 
    } 

    @Override 
    public Object getValueAt(int rowIndex, int columnIndex) { 
     return reservations[rowIndex][columnIndex]; 
    } 

    @Override 
    public Class<?> getColumnClass(int columnIndex) { 
     return Room.class; 
    } 

    @Override 
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 
     if (aValue instanceof Room) { 
      Room room = (Room) aValue; 
      reservations[rowIndex][columnIndex] = room; 
      fireTableCellUpdated(rowIndex, columnIndex); 
     } 
    } 

} 

这意味着我们现在可以设置单元格渲染器中显示的信息,我们需要

公共静态类RoomTableCellRenderer扩展DefaultTableCellRenderer {

private static Color BOOKED_COLOR = Color.RED; 

    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
     if (value instanceof Room && value != null) { 
      if (isSelected) { 
       setBackground(table.getSelectionBackground()); 
       setForeground(table.getSelectionForeground()); 
      } else { 
       setBackground(table.getBackground()); 
       setForeground(table.getForeground()); 
      } 
      // Update the details based on the room properties 
     } else { //if (value == null) { 
      setBackground(BOOKED_COLOR); 
      setText(null); 
     } 
     return this; 
    } 

} 

不要忘了,如果你想表要使用您的渲染器,您需要注册它...

table.setDefaultRenderer(Room.class, new RoomTableCellRenderer()); 

更新...

基于可用数据存储在2D String数组(你真的不喜欢我)。

这有点脏。实际上,数据应该尽可能地设置,以便传递给TableModel并让它处理细节。你还要小心如何更新数组,因为更新不会被表反映出来,直到你可以强制它刷新......并且这不会很好。

public class LocalDateTableCellRenderer extends DefaultTableCellRenderer { 

    protected static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd"); 
    private String[][] bookings; 

    public LocalDateTableCellRenderer(String[][] bookings) { 
     this.bookings = bookings; 
    } 


    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
     super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
     setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); 
     setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); 
     if (value instanceof LocalDate) { 
      LocalDate date = (LocalDate) value; 
      if (hasBookingFor(date)) { 
       setForeground(Color.WHITE); 
       setBackground(Color.RED); 
      } 
      setText(formatter.format(date)); 
     } else { 
      setText(null); 
     } 
     return this; 
    } 

    protected boolean hasBookingFor(LocalDate date) { 
     for (String[] data : bookings) { 
      int day = Integer.parseInt(data[2]); 
      int month = Integer.parseInt(data[3]); 
      int year = 2017; // Because :P 

      LocalDate booking = LocalDate.of(year, month, day); 
      if (booking.isEqual(date)) { 
       return true; 
      } 
     } 
     return false; 
    } 

} 

基本上,这可以让你的预订信息传递给TableCellRenderer,正如我所说,这是不是你怎么真的应该这样做,但它需要你的代码的显著重组,使它正常工作。现在

,我创建了一个TableModel基本上需要一年和一个月值,(如果该细胞是从本月范围或null)返回每个小区的LocalDate

public class CalendarModel extends AbstractTableModel { 

    public static String[] COLUMN_NAMES = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 

    private int rows = 0; 

    private LocalDate startOfCalendar; 
    private LocalDate firstDayOfMonth; 
    private LocalDate lastDayOfMonth; 

    public CalendarModel(int year, Month month) { 
     firstDayOfMonth = LocalDate.of(year, month, 1); 

     startOfCalendar = firstDayOfMonth.minusDays(firstDayOfMonth.getDayOfWeek().getValue()); 
     lastDayOfMonth = firstDayOfMonth.with(TemporalAdjusters.lastDayOfMonth()); 

     System.out.println(startOfCalendar.getDayOfWeek()); 
     System.out.println(firstDayOfMonth); 
     System.out.println(lastDayOfMonth); 

     Duration between = Duration.between(startOfCalendar.atStartOfDay(), lastDayOfMonth.atStartOfDay()); 
     long days = between.toDays(); 
     rows = (int) Math.round(days/7d) + 1; 
    } 

    @Override 
    public int getRowCount() { 
     return rows; 
    } 

    @Override 
    public int getColumnCount() { 
     return 7; 
    } 

    @Override 
    public Class<?> getColumnClass(int columnIndex) { 
     return LocalDate.class; 
    } 

    @Override 
    public String getColumnName(int column) { 
     return COLUMN_NAMES[column]; 
    } 

    @Override 
    public Object getValueAt(int rowIndex, int columnIndex) { 

     LocalDate date = null; 

     if (startOfCalendar != null) { 
      int day = (rowIndex * 7) + columnIndex; 
      date = startOfCalendar.plusDays(day); 

      if (date.isBefore(firstDayOfMonth) || date.isAfter(lastDayOfMonth)) { 
       date = null; 
      } 
     } 

     return date; 

    } 

} 

这意味着TableCellRenderer已经通过值的LocalDate值,通过此信息,您需要搜索阵列以查找指定日期的任何可能的预订。

这可怕的规模,这就是为什么我一直避免这样做,并不断尝试让你改变你如何管理你的数据,但在这里它是

最后一个非常粗略的例子...

这个例子并不真正关心你会管理信息,它只会关心的月份和日期信息

Example

import java.awt.Color; 
import java.awt.Component; 
import java.awt.EventQueue; 
import java.time.Duration; 
import java.time.LocalDate; 
import java.time.Month; 
import java.time.format.DateTimeFormatter; 
import java.time.temporal.TemporalAdjusters; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.table.AbstractTableModel; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.TableModel; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       String[][] bookings = new String[7][6]; 
       bookings[0][2] = "5"; 
       bookings[0][3] = "4"; 
       bookings[1][2] = "10"; 
       bookings[1][3] = "4"; 
       bookings[2][2] = "15"; 
       bookings[2][3] = "4"; 
       bookings[3][2] = "20"; 
       bookings[3][3] = "4"; 
       bookings[4][2] = "25"; 
       bookings[4][3] = "4"; 
       bookings[5][2] = "30"; 
       bookings[5][3] = "4"; 
       bookings[6][2] = "5"; 
       bookings[6][3] = "5"; 

       TableModel model = new CalendarModel(2017, Month.APRIL); 
       JTable table = new JTable(model); 
       table.setDefaultRenderer(LocalDate.class, new LocalDateTableCellRenderer(bookings)); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new JScrollPane(table)); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

} 
+0

评论是不适合扩展讨论;这个对话已经[转移到聊天](http://chat.stackoverflow.com/rooms/142389/discussion-on-answer-by-madprogrammer-java-how-to-paint-a-specific-cell-in-一个-JT)。 –

0

您必须设置单元格渲染你的JTable的每列。 我希望这个例子可以帮助你:

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.SwingUtilities; 
import javax.swing.table.DefaultTableModel; 

public class JTableTest 
{ 

    public static void main(String[] args) 
    { 
    SwingUtilities.invokeLater(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
     buildUI(); 
     } 
    }); 
    } 

    public static void buildUI() 
    { 
    final int w = 500; 
    final int h = 200; 
    Object colNames[] = 
    { 
     "COL1", "COL2", "COL3" 
    }; 
    Object[][] data = 
    { 
    }; 
    DefaultTableModel dtm = new DefaultTableModel(data, colNames); 
    dtm.addRow(new Object[] 
    { 
     "a", "b", "c" 
    }); 
    dtm.addRow(new Object[] 
    { 
     "d", "e", "f" 
    }); 
    dtm.addRow(new Object[] 
    { 
     "g", "h", "i" 
    }); 
    dtm.addRow(new Object[] 
    { 
     "l", "m", "n" 
    }); 
    final JTable t = new JTable(dtm); 
    final TableColour tce = new TableColour(); 
    t.getColumnModel().getColumn(0).setCellRenderer(tce); 
    t.getColumnModel().getColumn(1).setCellRenderer(tce); 
    t.getColumnModel().getColumn(2).setCellRenderer(tce); 
    final JFrame f = new JFrame(); 
    f.setBounds(0, 0, w, h); 
    JScrollPane sp = new JScrollPane(t); 
    f.getContentPane().add(sp); 
    f.setVisible(true); 

    } 
} 

class TableColour 
    extends javax.swing.table.DefaultTableCellRenderer 
{ 

    @Override 
    public java.awt.Component getTableCellRendererComponent(javax.swing.JTable table, java.lang.Object value, boolean isSelected, boolean hasFocus, int row, int column) 
    { 
    java.awt.Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
    cellComponent.setBackground(java.awt.Color.RED); 
    return cellComponent; 
    } 

} 
+0

非常奇怪,我把这个按钮点击的动作,当按钮点击没有任何反应。日历是我的Jtable 最终的JTable的名称t = new JTable(Calendar.getModel()); final TableColour tce = new TableColour(); t.getColumnModel()。getColumn(0).setCellRenderer(tce); t.getColumnModel()。getColumn(1).setCellRenderer(tce); t.getColumnModel()。getColumn(2).setCellRenderer(tce); – JOE

+0

上面的代码是一个完整的运行类。如果你想使用按钮,我认为你应该在你的动作管理中调用metod buildUI()。 – storm87

相关问题