好的哇哦,我可能有一些麻煩搞清楚了這一點。但也許不知何故。你說你不知道我的代碼是怎麼樣的,我有一些基本的渲染器。有一件事要記住,我有2維數組ReservedOne,它保存所佔用的房間的行索引和列索引,房間號碼日期,時間,直到它保留。所以現在我看看你的例子如何使用我的數組來設置顏色時有點困惑。我希望我不會有精神崩潰
你TableModel
應模擬這種數據,這是非常重要的,因爲它允許API的其餘部分是圍繞着它
真正的問題我怎麼傳那列和行,我有問題。單元格與其他一些代碼一起工作,但那不是我需要的。
這就是爲什麼有TableModel
包裝數據,作爲表API將通過row
和column
信息到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](https://i.stack.imgur.com/Bmk5Z.png)
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);
}
});
}
}
評論是不適合擴展討論;這個對話已經[轉移到聊天](http://chat.stackoverflow.com/rooms/142389/discussion-on-answer-by-madprogrammer-java-how-to-paint-a-specific-cell-in-一個-JT)。 –