如何在摇摆中的假if语句后连续闪烁表格单元格

Posted

技术标签:

【中文标题】如何在摇摆中的假if语句后连续闪烁表格单元格【英文标题】:how to blink table cell continuously after false if statement in swing 【发布时间】:2014-04-02 14:01:37 【问题描述】:

在swing应用程序中,当单元格时间等于系统时间时,我使用DefaultTableCellRenderer来刷新表格单元格。我写了 if 语句来比较单元格时间与 hh:mm ,如果两个时间相等,时间单元格背景将在表格行上闪烁。如果语句为真,它只会闪烁 60 秒,但我想在错误的 if 语句后继续闪烁 same cell

我得到了闪烁单元格的位置值,例如 (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;       
       
  

【问题讨论】:

如果您没有很快得到合适的答案,请考虑创建并发布minimal example program,它不需要数据库来为我们展示您的问题。 你能重新提出这个问题吗,很难理解你到底在问什么。一些一般提示(确定问题后)是将 () 添加到颜色和 color1 的计算中,如果您可以在循环外声明它,请尝试在循环中创建新对象,如“new TableModelEvent(table.getModel())” ,因为你在这里有很多事情要做,而且看起来它可能是使可重用的好代码,我会在你解决你的问题后把它放在一个单独的线程类中,它也会使代码更干净。 (您可能希望稍后在线程中添加条件以根据表属性更改停止它) 我有一个包含三列名称、电话号码和时间的表格。当表格时间和系统时间相等时,表格行上的时间单元格背景会闪烁。只有当陈述为真时,它才会闪烁一分钟。这意味着我在 if 语句中比较时间hh:mm,所以它只闪烁 60 秒。如果在 false 之后,如何继续闪烁相同的单元格,没有其他单元格或行。 这个问题与 JDBC (myslq & sql) 无关,而是关于 Timer & JTable & XxxTableCellRenderer 请重新阅读@Hovercraft Full Of Eels 的评论 【参考方案1】:

代码确实相当混乱。例如,不清楚闪烁的条件应该是什么。目前,条件似乎是特定单元格显示当前时间(从日历实例中获得)。然而,在CellRenderer 中做出这个决定是非常可疑的。相反,这个决定应该从外部做出,因为它实际上取决于模型数据。

控制实际闪烁的线程的实现不是很优雅。使用 Swing Timer 可以更轻松地解决这个问题。 (无论如何,线程只将任务放在事件队列中)。

此外,更改表格单元格渲染器组件的背景完全独立于组件本身。

但是,我创建了一个小示例来说明如何解决此问题。我试图尽可能地模仿您的初衷:该示例创建了一个表,其中包含未来几秒钟的时间字符串(日历实例),随机排列。它创建一个计时器,定期检查是否超过了任何时间限制。超过时间后,相应的表格单元格开始闪烁。

闪烁本身由特殊的BlinkCellRenderer 处理。由于这个单元格渲染器only 需要切换单元格的背景颜色,它只是使用了一个委托单元格渲染器,它提供了实际的单元格渲染器组件,并根据当前闪烁设置该组件的背景颜色状态。它还允许添加和删除当前应该闪烁的单元格。

当然,这可以以更复杂、更通用的方式进行扩展和实现,但至少可以作为一种灵感。

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 是单元格闪烁的持续时间,以毫秒为单位)

【讨论】:

谢谢,我短为一个单元格,如何在更改时间后停止单元格闪烁。 您可以稍后拨打blinkCellRenderer.removeBlinkingCell(r, c)。这可以通过另一个计时器或updateBlinkingState 方法来控制。目前,此调用已被注释掉,但您可以简单地添加此行,并修改shouldBlink 方法,使其在当前时间在范围内时返回true(timeInCell,timeInCell+10 秒) 我在updateBlinkingstate方法中启用了blinkCellRenderer.removeBlinkingCell(r, c),但它只闪烁一分钟我将hh:mm:ss a更改为hh:mm ashouldBlink如何更改? @NagarajRaju 您必须描述指定单元格是否应该闪烁的标准,具体取决于您的实际数据。但是,我稍微编辑了代码:现在,有一个值 blinkDurationInMS 允许指定闪烁持续时间。对于您的数据,您可能必须采用当前时间与单元格中显示的时间之间的差异计算。【参考方案2】:

创建另一列数据以存储在包含布尔值的 TableModel 中。数据只应在模型中,但列不应显示在 JTable 中。

然后,只要时间相同,您的逻辑就可以将布尔值设置为 Boolean.TRUE。一旦值为真,您就永远不会将其设置为假。渲染器现在可以检查布尔值以对单元格进行闪烁,并且闪烁应该永远持续下去。

【讨论】:

以上是关于如何在摇摆中的假if语句后连续闪烁表格单元格的主要内容,如果未能解决你的问题,请参考以下文章

带有闪烁边框的表格单元格

swift - 快速滚动时如何阻止tableview单元格出现故障和闪烁的图像?

Swing:在表格中闪烁特定单元格的计算效率最高的方法

输出文本字符串的多个单元格的电子表格 IF 语句

Google 表格中的 IF 语句

如何连续更新一堆表格单元格上的滑块?