问题
In swing application, I am using DefaultTableCellRenderer
to flash the table cell when the cell time is equal to system time. I wrote if statement to compare cell time with hh:mm
, If both time are equal, time cells backgroung will blink on the table rows. It is blinking 60 secs only still if statement is true, But i want to continue blinking same cell after false if statement.
I got the position value of blinking cell like (0,2) and (1,2). from this integer, how can i set continues blink after false if statement or Is there any other way? Thank you.
My Code is here :
I added table method and inner class.
public void table() throws SQLException
{
Connection c=null;
PreparedStatement pre;
try
{
Class.forName("com.mysql.jdbc.Driver");
c=DriverManager.getConnection("jdbc:mysql://localhost:3306/telecaller_database", "root", "root");
Statement st= c.createStatement();
DateFormat df=new SimpleDateFormat(" dd/MM/yyyy");
Calendar cl=Calendar.getInstance();
Date dt1=cl.getTime();
String str1=df.format(dt1);
System.out.println("today date is "+str1);
pre=c.prepareStatement("Select name,phoneno,time from components where date=?");
pre.setString(1,str1);
ArrayList<String> arl=new ArrayList<String>();
ResultSet rs=pre.executeQuery();
ResultSetMetaData md=rs.getMetaData();
System.out.println("result set data "+pre);
int column=md.getColumnCount();
System.out.println(column);
for(int i=1;i<=column;i++)
{
columns.addElement(md.getColumnName(i));
}
while(rs.next())
{
arl.add(rs.getString(1));
System.out.println(arl);
Vector row=new Vector(column);
for(int j=1;j<=column;j++)
{
row.addElement(rs.getString(j));
}
rows.addElement(row);
}
rs.close();
st.close();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
final JTable table=new JTable(rows,columns);
Border bd2=BorderFactory.createLineBorder(Color.black,1);
table.setBorder(bd2);
table.setDefaultRenderer(Object.class, (TableCellRenderer) new MyFlashingCellRenderer2());
final long startTime = System.currentTimeMillis();
Thread thread = new Thread()
{
public void run()
{
while(true)
{
long now = System.currentTimeMillis();
long second = (now -startTime) / 1000;
// System.out.println(second);
color = second / 2 * 2 == second ? Color.red : Color.yellow;
color1= second / 2 * 2 == second ? Color.green : Color.blue;
// System.out.println(second/2*2);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
table.tableChanged(new TableModelEvent(table.getModel()));
//table.setBackground(color1);
}
});
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
};
thread.start();
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setBounds(14,20,345,400);
jp1.add(scrollPane);
}
public class MyFlashingCellRenderer extends DefaultTableCellRenderer
{
public int cellr;
public int cellc;
public Component getTableCellRendererComponent(JTable table, Object rows1, boolean isSelected, boolean hasFocus, int row, int column)
{
JLabel label = (JLabel)super.getTableCellRendererComponent(table, rows1, isSelected, hasFocus, row, column);
String timeformat = " h:mm a";
SimpleDateFormat obDateFormat = new SimpleDateFormat(timeformat);
Calendar time = Calendar.getInstance();
String time1=obDateFormat.format(time.getTime()).toString();
//System.out.println("metod "+cellr+cellc);
if (time1.equals(rows1))
{
cellr=row;
cellc=column;
System.out.println("time "+time1+" row "+rows1);
getTableCellRendererComponent2(table, rows1, isSelected, hasFocus, row, column);
}
else if(!time1.equals(rows1))
{
label.setBackground(null);
}
return label;
}
public Component getTableCellRendererComponent2(JTable table, Object rows1, boolean isSelected,
boolean hasFocus, int x, int y)
{
JLabel label = (JLabel)super.getTableCellRendererComponent(table, rows1, isSelected, hasFocus, x, y);
label.setBackground(color);
System.out.println("outer method "+cellr+cellc);
x=cellr; y=cellc; // potition of blinking cell
System.out.println("x and y "+x+y);
return label;
}
}
回答1:
The code is indeed rather confusing. For example, it is not clear what the condition for the blinking should be. At the moment, it seems like the condition is that a particular cell displays the current time (as obtained from a calendar instance). However, making this decision in the CellRenderer
is highly dubious. Instead, this decision should be made from outside, since it actually depends on the model data.
The implementation of the thread that controls the actual blinking is not very elegant. This could more easily be solved with a Swing Timer
. (The thread only puts a task on the event queue, anyhow).
Additionally, changing the background of a table cell renderer component is fairly independent of the component itself.
However, I created a small example of how I would tackle this problem. I tried to mimic your original intention as far as possible: The sample creates a table that contains Strings of time (Calendar instances) that are a few seconds in the future, randomly permuted. It creates a timer that regularly checks whether any time limits has been exceeded. When the time has beed exceeded, the corresponding table cell starts to blink.
The blinking itself is handled by a special BlinkCellRenderer
. Since this cell renderer only has to switch the background color of a cell, it just uses a delegate cell renderer which provides the actual cell renderer component, and sets the background color of this component according to the current blinking state. It also allows adding and removing cells that should currently be blinking.
Of course, this could be extended and implemented in a more sophisticated and versatile way, but maybe it serves as an inspiration, at least.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
public class BlingBlingTable
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(createMainPanel());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static JPanel createMainPanel()
{
JPanel mainPanel = new JPanel(new BorderLayout());
final JTable table = createTable();
TableCellRenderer delegate = new DefaultTableCellRenderer();
final BlinkCellRenderer blinkCellRenderer =
new BlinkCellRenderer(table, delegate);
table.setDefaultRenderer(Object.class, blinkCellRenderer);
mainPanel.add(table, BorderLayout.CENTER);
createBlinkChecker(table, blinkCellRenderer);
final JToggleButton blinkButton = new JToggleButton("Random blink");
blinkButton.addActionListener(new ActionListener()
{
int r;
int c;
@Override
public void actionPerformed(ActionEvent e)
{
if (blinkButton.isSelected())
{
r = (int)(Math.random() * table.getRowCount());
c = (int)(Math.random() * table.getColumnCount());
blinkCellRenderer.addBlinkingCell(r, c);
}
else
{
blinkCellRenderer.removeBlinkingCell(r, c);
}
}
});
mainPanel.add(blinkButton, BorderLayout.SOUTH);
return mainPanel;
}
// Creates a table that contains strings that represent
// points in time that are a few seconds in the future
private static JTable createTable()
{
Vector<Vector<String>> rowDatas = new Vector<Vector<String>>();
int rs = 3;
int cs = 3;
for (int r=0; r<rs; r++)
{
Vector<String> rowData = new Vector<String>();
for (int c=0; c<cs; c++)
{
Calendar time = Calendar.getInstance();
time.add(Calendar.SECOND, (c+(r * cs))*4);
rowData.add(createTimeString(time));
}
Collections.shuffle(rowData);
rowDatas.add(rowData);
}
Collections.shuffle(rowDatas);
Vector<String> columnData = new Vector<String>();
for (int c=0; c<3; c++)
{
columnData.add("Column "+c);
}
return new JTable(rowDatas, columnData);
}
// Creates a timer that regularly updates the blinking
// state of all cells of the given table
private static void createBlinkChecker(
final JTable table, final BlinkCellRenderer blinkCellRenderer)
{
Timer timer = new Timer(500, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
updateBlinkingState(table, blinkCellRenderer);
}
});
timer.setInitialDelay(0);
timer.start();
}
// Updates the blinking state of the specified cell
// in the given table, using the #shouldBlink
// method below
private static void updateBlinkingState(
JTable table, BlinkCellRenderer blinkCellRenderer)
{
for (int r=0; r<table.getRowCount(); r++)
{
for (int c=0; c<table.getColumnCount(); c++)
{
if (shouldBlink(table, r, c))
{
blinkCellRenderer.addBlinkingCell(r, c);
}
else
{
blinkCellRenderer.removeBlinkingCell(r, c);
}
}
}
}
// Returns whether the specified cell in the given
// table should currently blink
private static boolean shouldBlink(JTable table, int r, int c)
{
Object value = table.getValueAt(r, c);
Calendar cellTime = parseTime(String.valueOf(value));
Calendar currentTime = Calendar.getInstance();
cellTime.set(Calendar.YEAR,
currentTime.get(Calendar.YEAR));
cellTime.set(Calendar.MONTH,
currentTime.get(Calendar.MONTH));
cellTime.set(Calendar.DAY_OF_MONTH,
currentTime.get(Calendar.DAY_OF_MONTH));
long difference =
currentTime.getTimeInMillis() -
cellTime.getTimeInMillis();
// Blink for 10 seconds
long blinkDurationInMS = 10000;
return
difference >= 0 &&
difference < blinkDurationInMS;
}
// The time format that will be used for creating
// strings from calendar instances and for parsing
private static final String TIME_FORMAT = " h:mm:ss a";
private static final DateFormat DATE_FORMAT =
new SimpleDateFormat(TIME_FORMAT);
// Creates a string containing the given time
// in a particular format
private static String createTimeString(Calendar time)
{
String timeString = DATE_FORMAT.format(time.getTime());
return timeString;
}
// Parse the time from the given string
private static Calendar parseTime(String timeString)
{
Calendar calendar = Calendar.getInstance();
try
{
calendar.setTime(DATE_FORMAT.parse(timeString));
}
catch (ParseException e)
{
e.printStackTrace();
}
return calendar;
}
/**
* A TableCellRenderer which can let particular cells of
* a JTable blink. That is, it switches the background
* color at a regular interval and triggers a repaint
* of the table. The cell renderer components whose
* background is switched are provided by a delegate
* cell renderer
*/
public static class BlinkCellRenderer extends DefaultTableCellRenderer
{
/**
* Serial UID
*/
private static final long serialVersionUID = 6896646544236592534L;
/**
* Simple class storing the coordinates of a
* particular table cell
*/
static class Cell
{
final int r;
final int c;
Cell(int r, int c)
{
this.r = r;
this.c = c;
}
@Override
public int hashCode()
{
return 31 * c + r;
}
@Override
public boolean equals(Object object)
{
if (object instanceof Cell)
{
Cell cell = (Cell)object;
return r == cell.r && c == cell.c;
}
return false;
}
}
/**
* The delegate cell renderer that provides the
* cell renderer components
*/
private final TableCellRenderer delegate;
/**
* The set of cells that are currently blinking
*/
private final Set<Cell> blinkingCells = new HashSet<Cell>();
/**
* The current blinking state (that is, whether
* the cells should be highlighted or not)
*/
private boolean blinkingState = true;
/**
* Creates a BlinkCellRenderer that will let cells of
* the given table blink. The cell renderer components
* are provided by the given delegate
*
* @param table The table
* @param delegate The delegate
*/
BlinkCellRenderer(final JTable table, TableCellRenderer delegate)
{
this.delegate = delegate;
int delayMS = 250;
Timer blinkingTimer = new Timer(delayMS, new ActionListener()
{
boolean timerBlinkingState = true;
@Override
public void actionPerformed(ActionEvent e)
{
blinkingState = timerBlinkingState;
table.repaint();
timerBlinkingState = !timerBlinkingState;
}
});
blinkingTimer.setInitialDelay(0);
blinkingTimer.start();
}
/**
* Add the cell with the given coordinates to the
* set of cells that are currently blinking
*
* @param r The row
* @param c The column
*/
void addBlinkingCell(int r, int c)
{
blinkingCells.add(new Cell(r, c));
}
/**
* Remove the cell with the given coordinates from the
* set of cells that are currently blinking
*
* @param r The row
* @param c The column
*/
void removeBlinkingCell(int r, int c)
{
blinkingCells.remove(new Cell(r,c));
}
/**
* Removes all blinking cells
*/
void clearBlinkingCells()
{
blinkingCells.clear();
}
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column)
{
Component component =
delegate.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
Cell cell = new Cell(row, column);
if (blinkingState && blinkingCells.contains(cell))
{
component.setBackground(Color.RED);
}
else
{
component.setBackground(null);
}
return component;
}
}
}
EDIT: Added a functionality to specify the duration for which the cells should keep blinking (blinkDurationInMS
is the duration how long the cell will blink, in milliseconds)
回答2:
Create another column of data to store in the TableModel that contains a Boolean value. The data should only be in the model, but the column should NOT be displayed in the JTable.
Then your logic can set the Boolean value to Boolean.TRUE whenever the times are the same. Once the value is true you never set it false. The renderer can now check the Boolean value to do the blinking for the cell and the blinking should continue fore ever.
来源:https://stackoverflow.com/questions/22114292/how-to-blink-table-cell-continuously-after-false-if-statement-in-swing