2017-04-11 90 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

相關問題