本文介绍了Java。如何在JTable中绘制特定的单元格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 好吧,我处于这种情况下。我的班级中有渲染器,但不知道如何使用它来使特定单元格的背景变成红色。这是一个房间出租应用,我将Jtable用作日历,因此我希望将油漆单元出租为红色。因此,它应该以某种方式采用特定的列和行并使该单元格变为红色。我的渲染器如下图所示,但是正如我所说,自从Java新手以来,我就不知道如何使用它。真正的问题是如何传递该列和行,我对此有疑问。单元格渲染可以与其他代码一起使用,但这并不是我需要的。Ok I'm in this situation... I have Renderer in my class but have no idea how to use it to make certain cell's background red. It's a room renting app and I have Jtable as calendar so I want paint cells which are rent red. So It should somehow take specific column and row and make that cell red. My renderer down bellow but as I said no Idea how to use it since Im new to java. Real question how do I pass that column and row, I have problem with that. Cell rendered worked with some other code but that wasnt what I need.ublic class TableColour extends javax.swing.table.DefaultTableCellRenderer {@Overridepublic 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;}}推荐答案您的 TableModel 应该为该数据建模,这非常重要,因为它允许API的其余部分围绕它旋转Your TableModel should be modeling this data, this is very important, as it allows the rest of the API to revolve around it这就是为什么 TableModel 包装数据,因为表API将传递行和列信息到 TableCellRenderer ,但它还将传递单元格值!This is why it's important to have the TableModel wrap the data, as the table API will pass the row and column information to the TableCellRenderer, but it will also pass the cell value!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); } }}我们现在可以设置单元格渲染器以显示所需的信息This means we can now setup the cell renderer to display the information we need公共静态类RoomTableCellRenderer扩展DefaultTableCellRenderer {public static class RoomTableCellRenderer extends 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; }}别忘了,如果您想要表格使用您的渲染器,您需要注册...Don't forget, if you want the table to use your renderer, you need to register it...table.setDefaultRenderer(Room.class, new RoomTableCellRenderer()); 已更新... 基于可用的数据存储在2D String 数组中(您真的不喜欢我)。Updated...Based on the available data been stored in 2D String array (you really don't like me).这是一个有点脏。实际上,应该将数据设置在可以传递给 TableModel 的地方,并让它处理细节。您还将要特别注意如何更新数组,因为在强制您刷新表之前,更新不会在表中反映出来。This is a little dirty. In reality, the data should be setup in such away as it could be passed to the TableModel and let it take care of the details. You're also going to have be careful in how you update the array, as updates won't be reflected by the table until you can force it to refresh ... and that won't be pretty.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 并不是您真正应该做的,但是要对其进行重大的结构调整就可以了Basically, this allows you to pass the booking information to the TableCellRenderer, as I've stated, this is NOT how you really should be doing this, but it would require a significant restructure of your code to make it work properly.现在,我创建一个 TableModel ,它基本上需要一个年月值,并返回一个 LocalDate (如果单元格不在月份范围内,则为 null )Now, I create a TableModel which basically takes a year and month value and returns a LocalDate for each cell (or null if the cell is out of the month range)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 被传递为 null 值为 LocalDate 值,然后使用此信息,您需要在数组中搜索指定日期的所有可能的预订。This means that the TableCellRenderer is been passed either a null value of LocalDate value, with this information, you then need to search your array for any possible bookings for the specified date.这将达到惊人的规模,这就是为什么我避免这样做的原因并一直试图让您更改数据的管理方式,但这就是This will scale horribly, which is why I've avoided doing and kept trying to get you to change how you manage your data, but here it is最后是一个非常粗糙的示例...And finally a really rough example...此示例并不真正关心您将要管理的所有信息,而仅关心月和日信息This example doesn't really care for all the information you'll be managing, it will only care about the month and day informationimport 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); } }); }} 这篇关于Java。如何在JTable中绘制特定的单元格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-21 00:56