如何在false之后连续闪烁表格单元格

时间:2014-03-01 12:23:21

标签: java swing animation jtable tablecellrenderer

在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;       
    }   
  }

2 个答案:

答案 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。渲染器现在可以检查布尔值以对单元格进行闪烁,并且闪烁应该继续进行。