在swing应用程序中,当单元格时间等于系统时间时,我使用DefaultTableCellRenderer
来刷新表格单元格。我写了if语句来比较单元格时间和hh:mm
,如果时间相等,时间单元格背景将在表格行上闪烁。如果声明为真,它仍然只闪烁60秒,但我想在false if语句之后继续闪烁相同的单元格。
我得到了闪烁单元格的位置值,如(0,2)和(1,2)。从这个整数,我如何设置继续在false if语句后闪烁或是否有其他方式?谢谢。
我的代码在这里:
我添加了表方法和内部类。
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;
}
}
答案 0 :(得分:2)
代码确实令人困惑。例如,不清楚闪烁的条件应该是什么。目前,似乎条件是特定单元格显示当前时间(从日历实例获得)。但是,在CellRenderer
中做出这个决定是非常可疑的。相反,这个决定应该来自外部,因为它实际上取决于模型数据。
控制实际闪烁的线程的实现不是很优雅。使用Swing Timer
可以更轻松地解决这个问题。 (无论如何,线程只将任务放在事件队列中)。
此外,更改表格单元格渲染器组件的背景与组件本身完全无关。
但是,我创建了一个如何解决这个问题的小例子。我试图尽可能地模仿你的初衷:该示例创建了一个表,其中包含未来几秒钟的时间字符串(日历实例),随机置换。它会创建一个计时器,定期检查是否已超出任何时间限制。超过时间后,相应的表格单元格开始闪烁。
闪烁本身由特殊BlinkCellRenderer
处理。由于此单元格渲染器仅必须切换单元格的背景颜色,因此它只使用委托单元格渲染器提供实际的单元格渲染器组件,并根据当前闪烁设置此组件的背景颜色州。它还允许添加和删除当前应闪烁的单元格。
当然,这可以通过更复杂和多功能的方式进行扩展和实施,但至少可以作为灵感。
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;
}
}
}
编辑:添加了一项功能,用于指定单元格应保持闪烁的持续时间(blinkDurationInMS
是单元格闪烁的持续时间,以毫秒为单位)
答案 1 :(得分:0)
创建另一列数据以存储在包含布尔值的TableModel中。数据应仅在模型中,但该列不应显示在JTable中。
然后,只要时间相同,您的逻辑就可以将布尔值设置为Boolean.TRUE。一旦值为true,您永远不会将其设置为false。渲染器现在可以检查布尔值以对单元格进行闪烁,并且闪烁应该继续进行。