-
Bug
-
Resolution: Not an Issue
-
P5
-
None
-
1.4.0, 1.4.1
-
x86
-
windows_2000
dowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};
CalendarTableModel.java
-----------------------
import java.awt.*;
import java.lang.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
/**
* The custom <code>TableModel</code> for dealing with the calendar and dealing
with <code>Date</code>s
* and the <code>GregorianCalendar</code>.
*
* @version 1.0 28/06/2002
* @author Arron Ferguson
*/
public class CalendarTableModel extends AbstractTableModel
{
/**
* Column names for the calendar.
*/
final Vector columnNames = new Vector(7);
{
columnNames.add("Sun");
columnNames.add("Mon");
columnNames.add("Tue");
columnNames.add("Wed");
columnNames.add("Thu");
columnNames.add("Fri");
columnNames.add("Sat");
};
/**
* The actual data for the table. The data is in a dynamic list instead
of the usual 2D array.
*/
private Vector data;
// initial 2D table data ... hard coded but since a dynamic collection
we can
// change this.
{
data = new Vector(6);
for(int i = 0; i < 6; i++)
{
Vector v = new Vector(7);
for(int j = 0; j < 7; j++)
v.add("");
data.add(v);
}
};
/**
* Reference to the actual view and controller which is known as the
delegate in MVC speak.
*/
private JCalendar delegate;
/**
* The calendar that keeps track of dates, months and leap years. This
object is called upon
* many times to render the month.
*/
private GregorianCalendar calendar;
/**
* The date at which the calendar is currently pointing at. This value
will change as the calendar
* moves forward and backward through calendar months.
*/
private int currentDate;
/**
* The month at which the calendar is currently pointing at. This value
will change as the calendar
* moves forward and backward through calendar months.
*/
private int currentMonth;
/**
* The year at which the calendar is currently pointing at. This value
will change as the calendar
* moves forward and backward through calendar months.
*/
private int currentYear;
/**
* The time stamp to indicate the actual date as determined by the
system's clock.
*/
private int date;
/**
* The first day in the week at which the date starts at. For example,
the first of the month may
* be Wednesday.
*/
private int startday;
/**
* The time stamp to indicate the actual month as determined by the
system's clock.
*/
private int month;
/**
* The header information.
*/
private String[] months;
/**
* The time stamp to indicate the actual year as determined by the
system's clock.
*/
private int year;
/**
* Constructor for referencing the <code>JCalendar</code>.
*/
public CalendarTableModel(JCalendar caller)
{
delegate = caller;
// set up the calendar
months = new String[12];
months[0] = "Jan";
months[1] = "Feb";
months[2] = "Mar";
months[3] = "Apr";
months[4] = "May";
months[5] = "Jun";
months[6] = "Jul";
months[7] = "Aug";
months[8] = "Sep";
months[9] = "Oct";
months[10] = "Nov";
months[11] = "Dec";
calendar = new GregorianCalendar();
date = calendar.get(Calendar.DAY_OF_MONTH);
month = calendar.get(Calendar.MONTH);
year = calendar.get(Calendar.YEAR);
currentDate = date;
currentMonth = month;
currentYear = year;
}
/**
* Returns the column count of this <code>TableModel</code>.
*
* @return the number of columns for this <code>TableModel</code>.
*/
public int getColumnCount()
{
return columnNames.size();
}
/**
* Return the current date which is where the calendar is pointing at.
This current date
* may or may not be the actual real date as determined by the system
clock.
*
* @return the current date being pointed to.
*/
public int getCurrentDate()
{
return calendar.get(Calendar.DAY_OF_MONTH);
}
/**
* Return the current month which is where the calendar is pointing at.
This current date
* may or may not be the actual real date as determined by the system
clock.
*
* @return the current month being pointed to.
*/
public int getCurrentMonth()
{
return calendar.get(Calendar.MONTH);
}
/**
* Return the current year which is where the calendar is pointing at.
This current date
* may or may not be the actual real date as determined by the system
clock.
*
* @return the current year being pointed to.
*/
public int getCurrentYear()
{
return calendar.get(Calendar.YEAR);
}
/**
* Return the real date based on the system clock.
*
* @return the actual date based on the system clock.
*/
public int getDate()
{
return date;
}
/**
* Return the real month based on the system clock.
*
* @return the actual month based on the system clock.
*/
public int getMonth()
{
return month;
}
/**
* Return the real year based on the system clock.
*
* @return the actual year based on the system clock.
*/
public int getYear()
{
return year;
}
/**
* Return the number of rows in this table.
*
* @return the number of rows as an int.
*/
public int getRowCount()
{
return data.size();
}
/**
* Returns the column name based on the index <code>col</code>.
*
* @param col the column at which a name is being requested for.
* @return the <code>String</code> name of column <code>col</code>.
*/
public String getColumnName(int col)
{
String s = (String)columnNames.get(col);
return s;
}
/**
* Return the <code>Object</code> at a particular cell.
*
* @param row the row to index
* @param col the column to index.
* @return the <code>Object</code> returned from a particular cell.
*/
public Object getValueAt(int row, int col)
{
return ((Vector)data.elementAt(row)).elementAt(col);
}
/*
* JTable uses this method to determine the default renderer/editor for
each cell.
*
* @param col the column to index.
* @return the class of the object that is being used to render this
column.
*/
public Class getColumnClass(int col)
{
return getValueAt(0, col).getClass();
}
/*
* Allow for the ability to edit information in each cell of this table.
*
* @param value the actual value being passed int at a particular cell
in the table.
* @param row the row at which to add the <code>Object</code>.
* @param row the column at which to add the <code>Object</code>.
*/
public void setValueAt(Object value, int row, int col)
{
((Vector)data.elementAt(row)).set(col, value);
fireTableCellUpdated(row, col);
}
/**
* Format a date and return it as a <code>StringBuffer</code>.
*
* @return the date as a <code>String</code>.
*/
public String simpleDate()
{
Locale locale = new Locale("en", "CANADA");
DateFormat formatter = DateFormat.getDateInstance
(DateFormat.FULL, locale);
Date signoutDate = new Date();
String now = formatter.format(signoutDate);
return now;
}
/**
* Generates an entire month and populates the table/cell model with
the values. This method
* will start off with the present date which is based on the system
clock. In order to change
* the month that is being displayed, a roll value is given. If the
roll value is 1, then the
* calendar moves ahead one month. If the roll value is -1, then the
calendar moves back one
* month. If 0 is given as a roll value, then the current date that is
in the calendar is used.
*
* @param rollValue the value to move the calendar forwards or
backwards.
*/
public void generateCalendarMonth(int rollValue)
{
if(rollValue == 0 || rollValue < -1 || rollValue > 1)
; // don't do anything since that value is non-valid
else
calendar.set(Calendar.MONTH, (calendar.get
(Calendar.MONTH) + rollValue));
currentYear = calendar.get(Calendar.YEAR);
currentMonth = calendar.get(Calendar.MONTH);
// going to go to the first of the month to get where it falls
upon within the week.
// example: the 1st of the month is Monday?
int tempDate = calendar.get(Calendar.DATE);
calendar.set(Calendar.DATE, 1);
startday = calendar.get(Calendar.DAY_OF_WEEK);
// arrays start at 0 so decrement by 1
startday--;
// now put it back
calendar.set(Calendar.DATE, tempDate);
// populate the label in the JCalendar
delegate.label.setText(months[currentMonth] + ", " +
currentYear);
// precalculate vector sizes. This assumes that all vectors
// within the main vector will be of equal size.
int columnMax = ((Vector)data.elementAt(0)).size();
// all months start at 1 so this can be hard-coded
currentDate = 1;
// precalculate the maximum date number for the current month.
February may have
// 28 or 29 days if it's a leap year, July has 31 days, etc.
int maxMonthDate = calendar.getActualMaximum(Calendar.DATE);
// increment because we are dealing with arrays
maxMonthDate++;
// populate the cells in the table model
for(int i = 0; i < data.size(); i++)
{
for(int k = 0; k < columnMax; k++)
{
// we need to check if a it's the 1st row. If
it is, the 1st of the month
// may not start on the first column (column
0). We need to check for this.
if(i > 0)
{
setValueAt((currentDate + ""), i, k);
currentDate++;
} else
{
if(k >= startday)
{
setValueAt((currentDate + ""),
i, k);
currentDate++;
}
else
setValueAt("", i, k);
}
if(currentDate > maxMonthDate)
setValueAt("", i, k);
if(currentDate == date)
{
;
}
}
}
}
}
--------------------
---------- END SOURCE ----------
(Review ID: 163564)
======================================================================
Name: sv35042 Date: 10/18/2002
FULL PRODUCT VERSION :
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
A DESCRIPTION OF THE PROBLEM :
When using a DefaultTableCellRenderer and attempting to
call its setFont() method, calling it like:
setFont(new Font("Serif", Font.BOLD, 24));
It does not change the font. I tried this using both an
inner class as well as an anonymous subclassed innerclass
and neither seem to work.
I did check the bugparade and only found 1 entry stating
the same problem - but it was not reproducable. This one is.
If this is in fact a bug (and not user error), then you
really have my vote for this to be an urgent fix since
the ability to bold text inside of a table's cell is quite
important for any practical uses with a JTable.
I do apologize for the size of my example. I know that you
want "just the problem", but since this uses Swing's
JTable, I have to include all the other parts of it in
order for it to work. Just look at the line # 109 of file
JCalendar.java. You can pretty much ignore the rest.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run the program
2. View the current month and see the current date cell's
text not bolded.
EXPECTED VERSUS ACTUAL BEHAVIOR :
The text in the DefaultTableCellRenderer should conform to
the setFont() method's Font parameter.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
// USE Michael Martak's GRAPHPAPER LAYOUT FOR THIS .........
/////////////////////////////////////////////////////////////
JCalendar.java
--------------
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.JDialog;
import java.awt.Font;
public class JCalendar extends JPanel implements ActionListener
{
/**
* For clicking on to take the calendar to the next month.
*/
private JButton nextButton;
/**
* For clicking on to take the calendar to the previous month.
*/
private JButton previousButton;
/**
* Displays the month and the year inside of the calendar layout.
*/
protected JLabel label;
/**
* The set of rows and columns used to display dates.
*/
protected JTable table;
/**
* Layout that allows for a grid like layout pattern. Components do not
have to
* take up exactly one cell, instead they can take up more than one row
or column.
*/
private GraphPaperLayout gp;
/**
* A custom <code>TableModel</code> for dealing with specifically
calendar like cells.
*/
private CalendarTableModel model;
/**
*
*/
private Vector dateEntries = new Vector();
/**
* Default constructor
*/
public JCalendar()
{
super();
configUI();
nextButton.addActionListener(this);
previousButton.addActionListener(this);
}
/**
* Configures the UI and sets up the renderers.
*/
private void configUI()
{
gp = new GraphPaperLayout(new Dimension(8, 10));
setLayout(gp);
nextButton = new JButton("Next");
previousButton = new JButton("Back");
label = new JLabel("");
model = new CalendarTableModel(this);
table = new JTable(model)
{
// the renderer used for date entries
TableCellRenderer dateEntryRenderer = new
DefaultTableCellRenderer()
{
{
this.setBackground(new Color(47, 144,
212));
}
};
// the renderer used for date entries AND it is the
current date
TableCellRenderer currentDateRenderer = new
DefaultTableCellRenderer()
{
{
setBackground(new Color(217, 149, 83));
// make bold ...
setFont(new Font("Serif", Font.BOLD,
24));
}
};
class test extends DefaultTableCellRenderer
{
test()
{
super();
setBackground(new Color(217, 149, 83));
// make bold ...
setFont(new Font("Serif", Font.BOLD,
24));
}
};
/* a renderer that uses image icons to render ... here
for documentation
// purposes only ...
TableCellRenderer happyFaceRenderer = new
DefaultTableCellRenderer()
{
{
URL url = JCalendar.class.getResource
("media/clownface.gif");
this.setIcon(new ImageIcon(url));
this.setVerticalTextPosition
(JLabel.CENTER);
this.setHorizontalTextPosition
(JLabel.LEFT);
}
}; */
// the table cell renderer that uses different renderers
public TableCellRenderer getCellRenderer(int row, int
column)
{
try
{
if((model.getCurrentDate() ==
Integer.parseInt(((String)model.getValueAt(row, column))))
&& model.getCurrentMonth() ==
model.getMonth()
&& model.getCurrentYear() ==
model.getYear())
{
test t = new test();
return t;
}
// return
currentDateRenderer;
for(int i = 0; i < dateEntries.size();
i++)
{
DateEntry entry = (DateEntry)
dateEntries.get(i);
JLabel label = (JLabel)
dateEntryRenderer;
if(entry.getDate() ==
Integer.parseInt(((String)model.getValueAt(row, column)))
&& model.getCurrentMonth
() == entry.getMonth()
&& model.getCurrentYear
() == entry.getYear())
{
label.setToolTipText
(entry.getText());
return
dateEntryRenderer;
}
}
} catch(NumberFormatException e)
{
;
}
return super.getCellRenderer(row, column);
}
};
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// don't allow rows or columns to be selected ... just cells.
table.setCellSelectionEnabled(false);
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(false);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// ... as well, set up a listener each time a cell has been
selected.
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.addListSelectionListener(new
ListSelectionListener()
{
int theDate;
public void valueChanged(ListSelectionEvent e)
{
// ignore extra message.
if (e.getValueIsAdjusting())
return;
CalendarTableModel model =
(CalendarTableModel)table.getModel();
String value = (String)model.getValueAt
(table.getSelectedRow(), table.getSelectedColumn());
try
{
theDate = Integer.parseInt
(value);
} catch(NumberFormatException ne)
{
return;
}
// drill down and get the frame and
pass it to the dialog ...
new DateEntryDialog((JFrame)
table.getParent().getParent().getParent().getParent().getParent(),
dateEntries, theDate,
model.getCurrentMonth(), model.getCurrentYear());
}
});
// don't allow cells to be selected
table.setFocusable(false);
// little bit of customization of cell renderers
JLabel cell = (JLabel)table.getDefaultRenderer(JLabel.class);
cell.setHorizontalAlignment(SwingConstants.LEFT);
cell.setVerticalAlignment(SwingConstants.TOP);
table.getTableHeader().setReorderingAllowed(false);
// add buttons
add(previousButton, new Rectangle(0, 0, 2, 1));
add(nextButton, new Rectangle(6, 0, 2, 1));
// add label
add(label, new Rectangle(3, 0, 2, 1));
add(table.getTableHeader(), new Rectangle(0, 2, 8, 1));
add(table, new Rectangle(0, 3, 8, 7));
// now call it for a populate
model.generateCalendarMonth(0);
}
/**
* Handles the two <code>JButton</code>s events for going forward and
backward
* in the years.
*
* @param e the <code>ActionEvent</code> given.
*/
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == nextButton)
{
model.generateCalendarMonth(1);
} else if(e.getSource() == previousButton)
{
model.generateCalendarMonth(-1);
}
}
/**
* Custom paint to allow cells to change height based on the size of
the <code>Container</code>
* that the table is in.
*
* @param g the <code>Graphics</code> context used to paint the table.
*/
public void paint(Graphics g)
{
super.paint(g);
// make row height resize as the component is resized so that
rows fill up the space
float componentHeight = (float)table.getHeight();
float numberofRows = (float)table.getRowCount();
float tableCellHeight = (componentHeight / numberofRows);
int height = (int)tableCellHeight;
table.setRowHeight(height);
}
/**
* Returns the preferred size of this composite component.
*
* @return the width and height of this component as a
<code>Dimension</code> object and as
* its preferred size to be rendered.
*/
public Dimension getPreferredSize()
{
return new Dimension(310, 220);
}
/**
* Returns the minimum size that this composite component should be
drawn at.
*
* @return the minimum width and height that this component should be
rendered at.
*/
public Dimension getMinimumSize()
{
return new Dimension(260, 170);
}
/**
* For running this program.
*/
public static void main(String[] args)
{
JCalendar jc = new JCalendar();
JFrame frame = new JFrame("JCalendar 1.1");
frame.getContentPane().add(jc);
Dimension frameD = new Dimension(310, 220);
Dimension screenD = new Dimension();
screenD = Toolkit.getDefaultToolkit().getScreenSize();
if(frameD.width >= screenD.width)
frame.setLocation(1, 1);
frame.setLocation(((screenD.width - frameD.width)/2),
((screenD.height - frameD.height)/2));
frame.setSize(frameD.width, frameD.height);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
);
frame.setVisible(true);
}
}
-------------
DateEntry.java
---------------
public class DateEntry
{
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int DAILY = 0;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int WEEKLY = 1;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int BIWEEKLY = 2;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int MONTHLY = 3;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int YEARLY = 4;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int NEVER = 5;
/**
* The text representation of this DateEntry.
*/
private String text;
/**
*
*/
private int date;
/**
*
*/
private int month;
/**
*
*/
private int year;
/**
*
*/
public DateEntry(String newText, int newDate, int newMonth, int newYear)
{
text = newText;
date = newDate;
month = newMonth;
year = newYear;
}
/**
* Returns the text for this <code>DateEntry</code>.
*
* @return the text for this date entry which will be placed in a
<code>ToolTip</code>.
*/
public String getText()
{
return text;
}
/**
* Returns the year for this <code>DateEntry</code>.
*
* @return the year.
*/
public int getYear()
{
return year;
}
/**
* Returns the month for this <code>DateEntry</code>.
*
* @return the month.
*/
public int getMonth()
{
return month;
}
/**
* Returns the date for this <code>DateEntry</code>.
*
* @return the date.
*/
public int getDate()
{
return date;
}
/**
* Override the printout of this Object.
*/
public String toString()
{
return (super.toString() + " " + text + " Date (dd/mm/yy): " +
date + "/" + month + "/" + year);
}
}
-------------
DateEntryDialog.java
--------------------
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JComboBox;
/**
* A dialog that allows the user to enter in information for
<code>DateEntry</code>
* objects.
*/
class DateEntryDialog extends JDialog implements ActionListener, WindowListener
{
/**
* The current date.
*/
private int currentDate;
/**
* The current month.
*/
private int currentMonth;
/**
* The current year.
*/
private int currentYear;
/**
* The ok button that sends the date entry to the table's model.
*/
private JButton ok;
/**
* The textArea that allows the user to enter in information.
*/
private JTextArea textArea;
/**
* The combo box that shows the repeating value. Allowable repeating
values are:
* - dailyweekly
* - biweekly
* - monthly
* - yearly
* - never
*
*/
private JComboBox comboBox;
/**
*
*/
private Vector entries;
/**
* The cancel button that cancels the action.
*/
private JButton cancel;
/**
* Constructor.
*
* @param entries - the <code>Vector</code> of <code>DateEntry</code>
objects.
* @param date - the current date selected.
* @param month - the current month selected.
* @param year - the current year selected.
*/
public DateEntryDialog(Frame parent, Vector theEntries, int date, int
month, int year)
{
super(parent, true);
// set the date stuff ...
currentDate = date;
currentMonth = month;
currentYear = year;
this.entries = theEntries;
// add the buttons ....
ok = new JButton("Ok");
cancel = new JButton("Cancel");
textArea = new JTextArea();
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
JScrollPane sp = new JScrollPane(textArea);
sp.setVerticalScrollBarPolicy
(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
this.getContentPane().setLayout(new GraphPaperLayout(new
Dimension(7, 6)));
this.getContentPane().add(ok, new Rectangle(1, 1, 2, 1));
this.getContentPane().add(cancel, new Rectangle(4, 1, 2, 1));
this.getContentPane().add(sp, new Rectangle(1, 2, 5, 2));
// make the dialog position itself in the middle of the
desktop ...
Dimension dialogD = new Dimension(280, 200);
Dimension screenD = new Dimension();
screenD = Toolkit.getDefaultToolkit().getScreenSize();
if(dialogD.width >= screenD.width)
this.setLocation(1, 1);
this.setLocation(((screenD.width - dialogD.width)/2),
((screenD.height - dialogD.height)/2));
this.setSize(dialogD.width, dialogD.height);
this.addWindowListener(this);
ok.addActionListener(this);
cancel.addActionListener(this);
setResizable(false);
show();
}
/**
*
*/
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == ok)
{
// got the go ahead to put a date entry into the
collection
if(textArea.getText().length() < 1)
;
else
entries.add(new DateEntry(textArea.getText(),
currentDate, currentMonth, currentYear));
hide();
} else if(e.getSource() == cancel)
{
hide();
}
}
/**
* Hide this dialog when the window is told to close.
*
* @param e the <code>WindowEvent</code> event source.
*/
public void windowClosing(WindowEvent e)
{
this.hide();
}
public void win
public void windowClosed(WindowEvent e){}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};
CalendarTableModel.java
-----------------------
import java.awt.*;
import java.lang.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
/**
* The custom <code>TableModel</code> for dealing with the calendar and dealing
with <code>Date</code>s
* and the <code>GregorianCalendar</code>.
*
* @version 1.0 28/06/2002
* @author Arron Ferguson
*/
public class CalendarTableModel extends AbstractTableModel
{
/**
* Column names for the calendar.
*/
final Vector columnNames = new Vector(7);
{
columnNames.add("Sun");
columnNames.add("Mon");
columnNames.add("Tue");
columnNames.add("Wed");
columnNames.add("Thu");
columnNames.add("Fri");
columnNames.add("Sat");
};
/**
* The actual data for the table. The data is in a dynamic list instead
of the usual 2D array.
*/
private Vector data;
// initial 2D table data ... hard coded but since a dynamic collection
we can
// change this.
{
data = new Vector(6);
for(int i = 0; i < 6; i++)
{
Vector v = new Vector(7);
for(int j = 0; j < 7; j++)
v.add("");
data.add(v);
}
};
/**
* Reference to the actual view and controller which is known as the
delegate in MVC speak.
*/
private JCalendar delegate;
/**
* The calendar that keeps track of dates, months and leap years. This
object is called upon
* many times to render the month.
*/
private GregorianCalendar calendar;
/**
* The date at which the calendar is currently pointing at. This value
will change as the calendar
* moves forward and backward through calendar months.
*/
private int currentDate;
/**
* The month at which the calendar is currently pointing at. This value
will change as the calendar
* moves forward and backward through calendar months.
*/
private int currentMonth;
/**
* The year at which the calendar is currently pointing at. This value
will change as the calendar
* moves forward and backward through calendar months.
*/
private int currentYear;
/**
* The time stamp to indicate the actual date as determined by the
system's clock.
*/
private int date;
/**
* The first day in the week at which the date starts at. For example,
the first of the month may
* be Wednesday.
*/
private int startday;
/**
* The time stamp to indicate the actual month as determined by the
system's clock.
*/
private int month;
/**
* The header information.
*/
private String[] months;
/**
* The time stamp to indicate the actual year as determined by the
system's clock.
*/
private int year;
/**
* Constructor for referencing the <code>JCalendar</code>.
*/
public CalendarTableModel(JCalendar caller)
{
delegate = caller;
// set up the calendar
months = new String[12];
months[0] = "Jan";
months[1] = "Feb";
months[2] = "Mar";
months[3] = "Apr";
months[4] = "May";
months[5] = "Jun";
months[6] = "Jul";
months[7] = "Aug";
months[8] = "Sep";
months[9] = "Oct";
months[10] = "Nov";
months[11] = "Dec";
calendar = new GregorianCalendar();
date = calendar.get(Calendar.DAY_OF_MONTH);
month = calendar.get(Calendar.MONTH);
year = calendar.get(Calendar.YEAR);
currentDate = date;
currentMonth = month;
currentYear = year;
}
/**
* Returns the column count of this <code>TableModel</code>.
*
* @return the number of columns for this <code>TableModel</code>.
*/
public int getColumnCount()
{
return columnNames.size();
}
/**
* Return the current date which is where the calendar is pointing at.
This current date
* may or may not be the actual real date as determined by the system
clock.
*
* @return the current date being pointed to.
*/
public int getCurrentDate()
{
return calendar.get(Calendar.DAY_OF_MONTH);
}
/**
* Return the current month which is where the calendar is pointing at.
This current date
* may or may not be the actual real date as determined by the system
clock.
*
* @return the current month being pointed to.
*/
public int getCurrentMonth()
{
return calendar.get(Calendar.MONTH);
}
/**
* Return the current year which is where the calendar is pointing at.
This current date
* may or may not be the actual real date as determined by the system
clock.
*
* @return the current year being pointed to.
*/
public int getCurrentYear()
{
return calendar.get(Calendar.YEAR);
}
/**
* Return the real date based on the system clock.
*
* @return the actual date based on the system clock.
*/
public int getDate()
{
return date;
}
/**
* Return the real month based on the system clock.
*
* @return the actual month based on the system clock.
*/
public int getMonth()
{
return month;
}
/**
* Return the real year based on the system clock.
*
* @return the actual year based on the system clock.
*/
public int getYear()
{
return year;
}
/**
* Return the number of rows in this table.
*
* @return the number of rows as an int.
*/
public int getRowCount()
{
return data.size();
}
/**
* Returns the column name based on the index <code>col</code>.
*
* @param col the column at which a name is being requested for.
* @return the <code>String</code> name of column <code>col</code>.
*/
public String getColumnName(int col)
{
String s = (String)columnNames.get(col);
return s;
}
/**
* Return the <code>Object</code> at a particular cell.
*
* @param row the row to index
* @param col the column to index.
* @return the <code>Object</code> returned from a particular cell.
*/
public Object getValueAt(int row, int col)
{
return ((Vector)data.elementAt(row)).elementAt(col);
}
/*
* JTable uses this method to determine the default renderer/editor for
each cell.
*
* @param col the column to index.
* @return the class of the object that is being used to render this
column.
*/
public Class getColumnClass(int col)
{
return getValueAt(0, col).getClass();
}
/*
* Allow for the ability to edit information in each cell of this table.
*
* @param value the actual value being passed int at a particular cell
in the table.
* @param row the row at which to add the <code>Object</code>.
* @param row the column at which to add the <code>Object</code>.
*/
public void setValueAt(Object value, int row, int col)
{
((Vector)data.elementAt(row)).set(col, value);
fireTableCellUpdated(row, col);
}
/**
* Format a date and return it as a <code>StringBuffer</code>.
*
* @return the date as a <code>String</code>.
*/
public String simpleDate()
{
Locale locale = new Locale("en", "CANADA");
DateFormat formatter = DateFormat.getDateInstance
(DateFormat.FULL, locale);
Date signoutDate = new Date();
String now = formatter.format(signoutDate);
return now;
}
/**
* Generates an entire month and populates the table/cell model with
the values. This method
* will start off with the present date which is based on the system
clock. In order to change
* the month that is being displayed, a roll value is given. If the
roll value is 1, then the
* calendar moves ahead one month. If the roll value is -1, then the
calendar moves back one
* month. If 0 is given as a roll value, then the current date that is
in the calendar is used.
*
* @param rollValue the value to move the calendar forwards or
backwards.
*/
public void generateCalendarMonth(int rollValue)
{
if(rollValue == 0 || rollValue < -1 || rollValue > 1)
; // don't do anything since that value is non-valid
else
calendar.set(Calendar.MONTH, (calendar.get
(Calendar.MONTH) + rollValue));
currentYear = calendar.get(Calendar.YEAR);
currentMonth = calendar.get(Calendar.MONTH);
// going to go to the first of the month to get where it falls
upon within the week.
// example: the 1st of the month is Monday?
int tempDate = calendar.get(Calendar.DATE);
calendar.set(Calendar.DATE, 1);
startday = calendar.get(Calendar.DAY_OF_WEEK);
// arrays start at 0 so decrement by 1
startday--;
// now put it back
calendar.set(Calendar.DATE, tempDate);
// populate the label in the JCalendar
delegate.label.setText(months[currentMonth] + ", " +
currentYear);
// precalculate vector sizes. This assumes that all vectors
// within the main vector will be of equal size.
int columnMax = ((Vector)data.elementAt(0)).size();
// all months start at 1 so this can be hard-coded
currentDate = 1;
// precalculate the maximum date number for the current month.
February may have
// 28 or 29 days if it's a leap year, July has 31 days, etc.
int maxMonthDate = calendar.getActualMaximum(Calendar.DATE);
// increment because we are dealing with arrays
maxMonthDate++;
// populate the cells in the table model
for(int i = 0; i < data.size(); i++)
{
for(int k = 0; k < columnMax; k++)
{
// we need to check if a it's the 1st row. If
it is, the 1st of the month
// may not start on the first column (column
0). We need to check for this.
if(i > 0)
{
setValueAt((currentDate + ""), i, k);
currentDate++;
} else
{
if(k >= startday)
{
setValueAt((currentDate + ""),
i, k);
currentDate++;
}
else
setValueAt("", i, k);
}
if(currentDate > maxMonthDate)
setValueAt("", i, k);
if(currentDate == date)
{
;
}
}
}
}
}
--------------------
---------- END SOURCE ----------
(Review ID: 163564)
======================================================================
Name: sv35042 Date: 10/18/2002
FULL PRODUCT VERSION :
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
A DESCRIPTION OF THE PROBLEM :
When using a DefaultTableCellRenderer and attempting to
call its setFont() method, calling it like:
setFont(new Font("Serif", Font.BOLD, 24));
It does not change the font. I tried this using both an
inner class as well as an anonymous subclassed innerclass
and neither seem to work.
I did check the bugparade and only found 1 entry stating
the same problem - but it was not reproducable. This one is.
If this is in fact a bug (and not user error), then you
really have my vote for this to be an urgent fix since
the ability to bold text inside of a table's cell is quite
important for any practical uses with a JTable.
I do apologize for the size of my example. I know that you
want "just the problem", but since this uses Swing's
JTable, I have to include all the other parts of it in
order for it to work. Just look at the line # 109 of file
JCalendar.java. You can pretty much ignore the rest.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run the program
2. View the current month and see the current date cell's
text not bolded.
EXPECTED VERSUS ACTUAL BEHAVIOR :
The text in the DefaultTableCellRenderer should conform to
the setFont() method's Font parameter.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
// USE Michael Martak's GRAPHPAPER LAYOUT FOR THIS .........
/////////////////////////////////////////////////////////////
JCalendar.java
--------------
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.JDialog;
import java.awt.Font;
public class JCalendar extends JPanel implements ActionListener
{
/**
* For clicking on to take the calendar to the next month.
*/
private JButton nextButton;
/**
* For clicking on to take the calendar to the previous month.
*/
private JButton previousButton;
/**
* Displays the month and the year inside of the calendar layout.
*/
protected JLabel label;
/**
* The set of rows and columns used to display dates.
*/
protected JTable table;
/**
* Layout that allows for a grid like layout pattern. Components do not
have to
* take up exactly one cell, instead they can take up more than one row
or column.
*/
private GraphPaperLayout gp;
/**
* A custom <code>TableModel</code> for dealing with specifically
calendar like cells.
*/
private CalendarTableModel model;
/**
*
*/
private Vector dateEntries = new Vector();
/**
* Default constructor
*/
public JCalendar()
{
super();
configUI();
nextButton.addActionListener(this);
previousButton.addActionListener(this);
}
/**
* Configures the UI and sets up the renderers.
*/
private void configUI()
{
gp = new GraphPaperLayout(new Dimension(8, 10));
setLayout(gp);
nextButton = new JButton("Next");
previousButton = new JButton("Back");
label = new JLabel("");
model = new CalendarTableModel(this);
table = new JTable(model)
{
// the renderer used for date entries
TableCellRenderer dateEntryRenderer = new
DefaultTableCellRenderer()
{
{
this.setBackground(new Color(47, 144,
212));
}
};
// the renderer used for date entries AND it is the
current date
TableCellRenderer currentDateRenderer = new
DefaultTableCellRenderer()
{
{
setBackground(new Color(217, 149, 83));
// make bold ...
setFont(new Font("Serif", Font.BOLD,
24));
}
};
class test extends DefaultTableCellRenderer
{
test()
{
super();
setBackground(new Color(217, 149, 83));
// make bold ...
setFont(new Font("Serif", Font.BOLD,
24));
}
};
/* a renderer that uses image icons to render ... here
for documentation
// purposes only ...
TableCellRenderer happyFaceRenderer = new
DefaultTableCellRenderer()
{
{
URL url = JCalendar.class.getResource
("media/clownface.gif");
this.setIcon(new ImageIcon(url));
this.setVerticalTextPosition
(JLabel.CENTER);
this.setHorizontalTextPosition
(JLabel.LEFT);
}
}; */
// the table cell renderer that uses different renderers
public TableCellRenderer getCellRenderer(int row, int
column)
{
try
{
if((model.getCurrentDate() ==
Integer.parseInt(((String)model.getValueAt(row, column))))
&& model.getCurrentMonth() ==
model.getMonth()
&& model.getCurrentYear() ==
model.getYear())
{
test t = new test();
return t;
}
// return
currentDateRenderer;
for(int i = 0; i < dateEntries.size();
i++)
{
DateEntry entry = (DateEntry)
dateEntries.get(i);
JLabel label = (JLabel)
dateEntryRenderer;
if(entry.getDate() ==
Integer.parseInt(((String)model.getValueAt(row, column)))
&& model.getCurrentMonth
() == entry.getMonth()
&& model.getCurrentYear
() == entry.getYear())
{
label.setToolTipText
(entry.getText());
return
dateEntryRenderer;
}
}
} catch(NumberFormatException e)
{
;
}
return super.getCellRenderer(row, column);
}
};
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// don't allow rows or columns to be selected ... just cells.
table.setCellSelectionEnabled(false);
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(false);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// ... as well, set up a listener each time a cell has been
selected.
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.addListSelectionListener(new
ListSelectionListener()
{
int theDate;
public void valueChanged(ListSelectionEvent e)
{
// ignore extra message.
if (e.getValueIsAdjusting())
return;
CalendarTableModel model =
(CalendarTableModel)table.getModel();
String value = (String)model.getValueAt
(table.getSelectedRow(), table.getSelectedColumn());
try
{
theDate = Integer.parseInt
(value);
} catch(NumberFormatException ne)
{
return;
}
// drill down and get the frame and
pass it to the dialog ...
new DateEntryDialog((JFrame)
table.getParent().getParent().getParent().getParent().getParent(),
dateEntries, theDate,
model.getCurrentMonth(), model.getCurrentYear());
}
});
// don't allow cells to be selected
table.setFocusable(false);
// little bit of customization of cell renderers
JLabel cell = (JLabel)table.getDefaultRenderer(JLabel.class);
cell.setHorizontalAlignment(SwingConstants.LEFT);
cell.setVerticalAlignment(SwingConstants.TOP);
table.getTableHeader().setReorderingAllowed(false);
// add buttons
add(previousButton, new Rectangle(0, 0, 2, 1));
add(nextButton, new Rectangle(6, 0, 2, 1));
// add label
add(label, new Rectangle(3, 0, 2, 1));
add(table.getTableHeader(), new Rectangle(0, 2, 8, 1));
add(table, new Rectangle(0, 3, 8, 7));
// now call it for a populate
model.generateCalendarMonth(0);
}
/**
* Handles the two <code>JButton</code>s events for going forward and
backward
* in the years.
*
* @param e the <code>ActionEvent</code> given.
*/
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == nextButton)
{
model.generateCalendarMonth(1);
} else if(e.getSource() == previousButton)
{
model.generateCalendarMonth(-1);
}
}
/**
* Custom paint to allow cells to change height based on the size of
the <code>Container</code>
* that the table is in.
*
* @param g the <code>Graphics</code> context used to paint the table.
*/
public void paint(Graphics g)
{
super.paint(g);
// make row height resize as the component is resized so that
rows fill up the space
float componentHeight = (float)table.getHeight();
float numberofRows = (float)table.getRowCount();
float tableCellHeight = (componentHeight / numberofRows);
int height = (int)tableCellHeight;
table.setRowHeight(height);
}
/**
* Returns the preferred size of this composite component.
*
* @return the width and height of this component as a
<code>Dimension</code> object and as
* its preferred size to be rendered.
*/
public Dimension getPreferredSize()
{
return new Dimension(310, 220);
}
/**
* Returns the minimum size that this composite component should be
drawn at.
*
* @return the minimum width and height that this component should be
rendered at.
*/
public Dimension getMinimumSize()
{
return new Dimension(260, 170);
}
/**
* For running this program.
*/
public static void main(String[] args)
{
JCalendar jc = new JCalendar();
JFrame frame = new JFrame("JCalendar 1.1");
frame.getContentPane().add(jc);
Dimension frameD = new Dimension(310, 220);
Dimension screenD = new Dimension();
screenD = Toolkit.getDefaultToolkit().getScreenSize();
if(frameD.width >= screenD.width)
frame.setLocation(1, 1);
frame.setLocation(((screenD.width - frameD.width)/2),
((screenD.height - frameD.height)/2));
frame.setSize(frameD.width, frameD.height);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
);
frame.setVisible(true);
}
}
-------------
DateEntry.java
---------------
public class DateEntry
{
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int DAILY = 0;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int WEEKLY = 1;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int BIWEEKLY = 2;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int MONTHLY = 3;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int YEARLY = 4;
/**
* The <code>DateEntry</code> occurs daily.
*/
public static final int NEVER = 5;
/**
* The text representation of this DateEntry.
*/
private String text;
/**
*
*/
private int date;
/**
*
*/
private int month;
/**
*
*/
private int year;
/**
*
*/
public DateEntry(String newText, int newDate, int newMonth, int newYear)
{
text = newText;
date = newDate;
month = newMonth;
year = newYear;
}
/**
* Returns the text for this <code>DateEntry</code>.
*
* @return the text for this date entry which will be placed in a
<code>ToolTip</code>.
*/
public String getText()
{
return text;
}
/**
* Returns the year for this <code>DateEntry</code>.
*
* @return the year.
*/
public int getYear()
{
return year;
}
/**
* Returns the month for this <code>DateEntry</code>.
*
* @return the month.
*/
public int getMonth()
{
return month;
}
/**
* Returns the date for this <code>DateEntry</code>.
*
* @return the date.
*/
public int getDate()
{
return date;
}
/**
* Override the printout of this Object.
*/
public String toString()
{
return (super.toString() + " " + text + " Date (dd/mm/yy): " +
date + "/" + month + "/" + year);
}
}
-------------
DateEntryDialog.java
--------------------
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JComboBox;
/**
* A dialog that allows the user to enter in information for
<code>DateEntry</code>
* objects.
*/
class DateEntryDialog extends JDialog implements ActionListener, WindowListener
{
/**
* The current date.
*/
private int currentDate;
/**
* The current month.
*/
private int currentMonth;
/**
* The current year.
*/
private int currentYear;
/**
* The ok button that sends the date entry to the table's model.
*/
private JButton ok;
/**
* The textArea that allows the user to enter in information.
*/
private JTextArea textArea;
/**
* The combo box that shows the repeating value. Allowable repeating
values are:
* - dailyweekly
* - biweekly
* - monthly
* - yearly
* - never
*
*/
private JComboBox comboBox;
/**
*
*/
private Vector entries;
/**
* The cancel button that cancels the action.
*/
private JButton cancel;
/**
* Constructor.
*
* @param entries - the <code>Vector</code> of <code>DateEntry</code>
objects.
* @param date - the current date selected.
* @param month - the current month selected.
* @param year - the current year selected.
*/
public DateEntryDialog(Frame parent, Vector theEntries, int date, int
month, int year)
{
super(parent, true);
// set the date stuff ...
currentDate = date;
currentMonth = month;
currentYear = year;
this.entries = theEntries;
// add the buttons ....
ok = new JButton("Ok");
cancel = new JButton("Cancel");
textArea = new JTextArea();
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
JScrollPane sp = new JScrollPane(textArea);
sp.setVerticalScrollBarPolicy
(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
this.getContentPane().setLayout(new GraphPaperLayout(new
Dimension(7, 6)));
this.getContentPane().add(ok, new Rectangle(1, 1, 2, 1));
this.getContentPane().add(cancel, new Rectangle(4, 1, 2, 1));
this.getContentPane().add(sp, new Rectangle(1, 2, 5, 2));
// make the dialog position itself in the middle of the
desktop ...
Dimension dialogD = new Dimension(280, 200);
Dimension screenD = new Dimension();
screenD = Toolkit.getDefaultToolkit().getScreenSize();
if(dialogD.width >= screenD.width)
this.setLocation(1, 1);
this.setLocation(((screenD.width - dialogD.width)/2),
((screenD.height - dialogD.height)/2));
this.setSize(dialogD.width, dialogD.height);
this.addWindowListener(this);
ok.addActionListener(this);
cancel.addActionListener(this);
setResizable(false);
show();
}
/**
*
*/
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == ok)
{
// got the go ahead to put a date entry into the
collection
if(textArea.getText().length() < 1)
;
else
entries.add(new DateEntry(textArea.getText(),
currentDate, currentMonth, currentYear));
hide();
} else if(e.getSource() == cancel)
{
hide();
}
}
/**
* Hide this dialog when the window is told to close.
*
* @param e the <code>WindowEvent</code> event source.
*/
public void windowClosing(WindowEvent e)
{
this.hide();
}
public void win