2011-05-18 110 views
14

我有問題在我的應用程序中顯示等待光標。只要鼠標位於定義自己光標的面板上方,等待光標就不會出現。如果面板不改變光標,則會出現等待光標。java等待光標顯示問題

我附上一個SSCE來準確地解釋我的問題。

public class BusyCursorTest extends javax.swing.JFrame { 

public BusyCursorTest() { 

    javax.swing.JMenuBar menuBar = new javax.swing.JMenuBar(); 
    javax.swing.JMenu menu = new javax.swing.JMenu("Menu"); 
    javax.swing.JMenuItem wait1 = new javax.swing.JMenuItem("Wait 100 ms"); 
    javax.swing.JMenuItem wait2 = new javax.swing.JMenuItem("Wait 250 ms"); 
    javax.swing.JMenuItem wait3 = new javax.swing.JMenuItem("Wait 500 ms"); 
    javax.swing.JMenuItem wait4 = new javax.swing.JMenuItem("Wait 1000 ms"); 
    menu.add(wait1); 
    menu.add(wait2); 
    menu.add(wait3); 
    menu.add(wait4); 
    menuBar.add(menu); 
    setJMenuBar(menuBar); 
    wait1.addActionListener(getActionListener(this, delayActionListener(100))); 
    wait2.addActionListener(getActionListener(this, delayActionListener(250))); 
    wait3.addActionListener(getActionListener(this, delayActionListener(500))); 
    wait4.addActionListener(getActionListener(this, delayActionListener(1000))); 

    cursorPanel = new javax.swing.JPanel(); 
    cursorPanel.addMouseListener(new java.awt.event.MouseAdapter() { 

     public void mouseEntered(java.awt.event.MouseEvent e) { 
      cursorPanel.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.CROSSHAIR_CURSOR)); 
     } 

     public void mouseExited(java.awt.event.MouseEvent e) { 
      cursorPanel.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR)); 
     } 

    }); 

    javax.swing.JTabbedPane tabbedPane = new javax.swing.JTabbedPane(); 
    tabbedPane.addTab("Default", new javax.swing.JPanel()); 
    tabbedPane.addTab("Cursor change", cursorPanel); 
    getContentPane().add(tabbedPane); 

    setTitle("Cursor test"); 
    setSize(400, 400); 
    setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); 
    setVisible(true); 
} 

private java.awt.event.ActionListener delayActionListener(final int delay) { 
    java.awt.event.ActionListener listener = new java.awt.event.ActionListener() { 

     public void actionPerformed(java.awt.event.ActionEvent ae) { 
      try { 
       Thread.sleep(delay); 
      } catch (InterruptedException e) { 
      } 
     } 

    }; 
    return listener; 
} 

public static void main(String[] args) { 
    new BusyCursorTest(); 
} 

public static java.awt.event.ActionListener getActionListener(final java.awt.Component component, 
    final java.awt.event.ActionListener originalActionListener) { 

    java.awt.event.ActionListener actionListener = new java.awt.event.ActionListener() { 

     public void actionPerformed(final java.awt.event.ActionEvent e) { 

      java.util.TimerTask timerTask = new java.util.TimerTask() { 

       public void run() { 
        originalCursor = component.getCursor(); 
        component.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR)); 
       } 

      }; 
      java.util.Timer timer = new java.util.Timer(); 

      try { 
       timer.schedule(timerTask, DELAY_MS); 
       originalActionListener.actionPerformed(e); 
      } finally { 
       timer.cancel(); 
       component.setCursor(originalCursor); 
      } 
     } 

    }; 
    return actionListener; 
} 

private javax.swing.JPanel cursorPanel = null; 

public static java.awt.Cursor originalCursor = null; 

public static final int DELAY_MS = 250; 
} 

運行附加的SSCE。

當選擇第一個選項卡(「默認」)時,單擊1000ms菜單項將顯示忙狀態光標。

當選擇第二個選項卡(「光標更改」)時,單擊1000ms菜單項不會顯示繁忙光標。

我該如何解決這個問題?

我強烈希望我的代碼不必考慮任何面板,因爲要跟蹤哪些面板可能處於最前沿非常困難。而且,由於鼠標點擊,事件並不總是生成。

什麼是建議的解決方法,以便我可以修改頂層容器的行爲?

回答

5

搜索互聯網後,我找到了答案,我的問題。

關鍵是將光標設置在包含要顯示忙光標的組件的幀的玻璃窗格上。我從網上的以下文章中得到了這個想法。

Wait, Cursor, Wait!

An Automatic Wait Cursor: WaitCursorEventQueue

我修改了SSCE,使其爲案件工作時,在框架內的組件設置自己的光標。這是修改後的SSCE。

public class BusyCursorTest extends javax.swing.JFrame { 

private javax.swing.JPanel cursorPanel = null; 

public BusyCursorTest() { 

    javax.swing.JMenuBar menuBar = new javax.swing.JMenuBar(); 
    javax.swing.JMenu menu = new javax.swing.JMenu("Menu"); 
    javax.swing.JMenuItem wait1 = new javax.swing.JMenuItem("Wait 100 ms"); 
    javax.swing.JMenuItem wait2 = new javax.swing.JMenuItem("Wait 250 ms"); 
    javax.swing.JMenuItem wait3 = new javax.swing.JMenuItem("Wait 500 ms"); 
    javax.swing.JMenuItem wait4 = new javax.swing.JMenuItem("Wait 1000 ms"); 
    menu.add(wait1); 
    menu.add(wait2); 
    menu.add(wait3); 
    menu.add(wait4); 
    menuBar.add(menu); 
    setJMenuBar(menuBar); 
    wait1.addActionListener(getActionListener(this, delayActionListener(100))); 
    wait2.addActionListener(getActionListener(this, delayActionListener(250))); 
    wait3.addActionListener(getActionListener(this, delayActionListener(500))); 
    wait4.addActionListener(getActionListener(this, delayActionListener(1000))); 

    cursorPanel = new javax.swing.JPanel(); 
    cursorPanel.addMouseListener(new java.awt.event.MouseAdapter() { 

     public void mouseEntered(java.awt.event.MouseEvent e) { 
      cursorPanel.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.CROSSHAIR_CURSOR)); 
     } 

     public void mouseExited(java.awt.event.MouseEvent e) { 
      cursorPanel.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR)); 
     } 

    }); 

    javax.swing.JTabbedPane tabbedPane = new javax.swing.JTabbedPane(); 
    tabbedPane.addTab("Default", new javax.swing.JPanel()); 
    tabbedPane.addTab("Cursor change", cursorPanel); 
    getContentPane().add(tabbedPane); 

    setTitle("Cursor test"); 
    setSize(400, 400); 
    setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); 
    setVisible(true); 
} 

private java.awt.event.ActionListener delayActionListener(final int delay) { 
    java.awt.event.ActionListener listener = new java.awt.event.ActionListener() { 

     public void actionPerformed(java.awt.event.ActionEvent ae) { 
      try { 
       Thread.sleep(delay); 
      } catch (InterruptedException e) { 
      } 
     } 

    }; 
    return listener; 
} 

public static void main(String[] args) { 
    new BusyCursorTest(); 
} 

public static java.awt.event.ActionListener getActionListener(final javax.swing.JFrame frame, 
    final java.awt.event.ActionListener originalActionListener) { 

    java.awt.event.ActionListener actionListener = new java.awt.event.ActionListener() { 

     public void actionPerformed(final java.awt.event.ActionEvent e) { 

      java.util.TimerTask timerTask = new java.util.TimerTask() { 

       public void run() { 
        originalCursor = frame.getCursor(); 
        startWaitCursor(frame); 
       } 

      }; 
      java.util.Timer timer = new java.util.Timer(); 

      try { 
       timer.schedule(timerTask, DELAY_MS); 
       originalActionListener.actionPerformed(e); 
      } finally { 
       timer.cancel(); 
       stopWaitCursor(frame); 
      } 
     } 

    }; 
    return actionListener; 
} 

private static void startWaitCursor(javax.swing.JFrame frame) { 
    frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR)); 
    frame.getGlassPane().addMouseListener(mouseAdapter); 
    frame.getGlassPane().setVisible(true); 
} 

private static void stopWaitCursor(javax.swing.JFrame frame) { 
    frame.getGlassPane().setCursor(originalCursor); 
    frame.getGlassPane().removeMouseListener(mouseAdapter); 
    frame.getGlassPane().setVisible(false); 
} 

private static java.awt.Cursor originalCursor = null; 

private static final java.awt.event.MouseAdapter mouseAdapter = new java.awt.event.MouseAdapter() { 
}; 

public static final int DELAY_MS = 250; 

}

+0

上,繪製輪子滾動事件的jscrollpan效果非常好,只是想指出上面的代碼不能捕獲鼠標事件。如果我保持事件線程繁忙,則可能無法捕捉鼠標事件。 – 2011-05-19 22:19:43

+0

在阻塞EDT時正確可靠地捕獲鼠標事件的SSCE發佈在線程中:http://stackoverflow.com/questions/7085239/java-swing-clear-the-event-queue。 – 2011-12-20 22:34:32

1

嘗試將它設置在框架上,而不是給定組件的

+0

我確實設置在上述SSCE框架上的光標。 – 2011-05-19 13:48:46

+0

那麼:@ Santosh-Tiwari它現在如何,它的工作?我想我也遇到了類似的情況,因爲你...... – gumuruh 2011-08-15 09:39:08

+0

是忙遊標工作得很好。兩個問題:i)如果我阻止了EDT,我仍然無法捕捉鼠標事件。一旦EDT釋放,它就開始處理排隊的鼠標/鍵盤事件。 ii)忙狀態光標仍然不會出現在新的對話框/框架上。我知道如何解決這個問題,但尚未打擾。 – 2011-08-16 21:08:13

2

嗯,你的代碼有問題Concurency in Swing有兩個方面

取代了Thread.sleep(延遲);而java.util.Timer中與java.swing.Timer因爲塊EDT

但在其他手上有怎樣的方式(從OTN通過splungebob)故意塊EDT 注:對所有的Swing rulles這個例子中,並以這種形式的工作方式和作爲例子

import java.awt.*; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.event.*; 

public class DelayedComboBoxDemo implements Runnable { 

    private JCheckBox chkA = new JCheckBox("A"); 
    private JCheckBox chkB = new JCheckBox("B"); 
    private JCheckBox chkC = new JCheckBox("C"); 
    private JComboBox cboItems = new JComboBox(); 
    private JFrame frame; 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new DelayedComboBoxDemo()); 
    } 

    @Override 
    public void run() { 
     cboItems.addItem("-"); 
     JPanel p = new JPanel(); 
     p.add(chkA); 
     p.add(chkB); 
     p.add(chkC); 
     p.add(cboItems); 
     frame = new JFrame("Delayed ComboBox Test"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(p); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     cboItems.addPopupMenuListener(new PopupMenuListener() { 

      @Override 
      public void popupMenuCanceled(PopupMenuEvent e) { 
      } 

      @Override 
      public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 
      } 

      @Override 
      public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 
       int items = cboItems.getItemCount(); 
       rebuildList(); 
       if (items != cboItems.getItemCount()) { 
        cboItems.hidePopup(); 
        cboItems.showPopup(); 
       } 
      } 
     }); 
    } 

    private void rebuildList() { 
     frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 
     Vector<String> items = new Vector<String>(); 
     if (chkA.isSelected()) { 
      items.add("A"); 
     } else if (chkB.isSelected()) { 
      items.add("B"); 
     } else if (chkC.isSelected()) { 
      items.add("C"); 
     } else { 
      items.add("-"); 
     } 
     cboItems.setModel(new DefaultComboBoxModel(items)); 
     try { 
      Thread.sleep(3000); // simulate a long transaction 
     } catch (InterruptedException ex) { 
     } 
     frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
    } 
} 
+0

我不確定併發是否是問題(仍在探索這方面)。我正在使用Thread.sleep()來模擬長事務。它與這樣一個事實有關,即其中一個選項卡設置自己的光標,以某種方式覆蓋切換到繁忙的光標。 – 2011-05-19 13:57:25

+0

從setCursor()方法的javadoc中:具有非null遊標的任何組件都將覆蓋在其父容器上設置的遊標。我需要找出一種方法,只有當我必須顯示一個忙碌光標時,才能覆蓋該覆蓋。 – 2011-05-19 14:29:22

+1

如果你只創建一個例子,並且沒有任何輸出到GUI的BackGround任務,那麼你通過Thread.sleep(int)塊的GUI,如我發佈的例子,在其他情況下,你將冒這樣的風險到GUI不按預期工作,或直接凍結,在這種情況下,只是mousrHover重新繪製,我會給你另一個例子,證明正確性和使用Timer和Runnable,但我必須實現你的BusyCursor .. – mKorbel 2011-05-19 14:42:22

4
import java.awt.*; 
import java.awt.event.*; 
import java.text.SimpleDateFormat; 
import java.util.Random; 
import javax.swing.*; 
import javax.swing.UIManager.LookAndFeelInfo; 
import javax.swing.table.*; 

public class TableWithTimer implements ActionListener, Runnable { 

    private static final long serialVersionUID = 1L; 
    private JFrame frame = new JFrame(); 
    private JScrollPane scroll = new JScrollPane(); 
    private JTable myTable; 
    private JPanel buttonPanel = new JPanel(); 
    private JButton startButton = new JButton("Start Thread to Update Table"); 
    private JButton stopButton = new JButton("Stop Thread for Update Table"); 
    private JButton newButton = new JButton("Load new Data to Table"); 
    private int count = 0; 
    private int delay = 3; 
    private javax.swing.Timer timer = null; 
    private boolean runProcess; 
    private int row = 0; 
    private int column = 0; 
    private String value = "Amnd"; 
    private int amndValue = 0; 
    private String valueAt = ""; 
    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); 
    private String[] head = {"One", "Two", "Three", "Four", "Five", "Six"}; 
    private String[][] data = new String[25][6]; 

    public TableWithTimer() { 
     myTable = new TableBackroundPaint0(data, head); 
     myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     myTable.setGridColor(Color.gray); 
     myTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 
     final TableCellRenderer cellRendener = myTable.getTableHeader().getDefaultRenderer(); 
     myTable.getTableHeader().setDefaultRenderer(new TableCellRenderer() { 

      @Override 
      public Component getTableCellRendererComponent(JTable table, Object value, 
        boolean isSelected, boolean hasFocus, int row, int column) { 
       JLabel label = (JLabel) cellRendener.getTableCellRendererComponent(
         table, value, isSelected, hasFocus, row, column); 
       label.setBackground(Color.orange); 
       label.setForeground(Color.darkGray); 
       label.setFont(new Font("SansSerif", Font.BOLD, 12)); 
       label.setBorder(BorderFactory.createCompoundBorder(label.getBorder(), 
         BorderFactory.createEmptyBorder(0, 5, 0, 0))); 
       label.setHorizontalAlignment(SwingConstants.LEFT); 
       label.setHorizontalAlignment(SwingConstants.CENTER); 
       if ((label.getText().equals("First")) || (label.getText().equals("Second"))) { 
        label.setForeground(Color.red); 
       } 
       if ((label.getText().equals("Day")) || (label.getText().equals("Month")) || (label.getText().equals("Year"))) { 
        label.setForeground(Color.blue); 
       } 
       if ((label.getText().equals("Time"))) { 
        label.setForeground(Color.green); 
       } 
       return label; 
      } 
     }); 
     TableColumnModel cm = myTable.getColumnModel(); 
     for (int column1 = 0; column1 < cm.getColumnCount(); column1++) { 
      TableColumn colLeft1 = cm.getColumn(column1); 
      cm.getColumn(column1).setWidth(140); 
      cm.getColumn(column1).setPreferredWidth(140); 
     } 
     //myTable.setFillsViewportHeight(true); // apply paintComponent for whole Viewport 
     JButton cornerButtonTop = new JButton(); 
     cornerButtonTop.setBackground(scroll.getViewport().getBackground()); 
     JButton cornerButtonBottom = new JButton(); 
     cornerButtonBottom.setOpaque(false); 
     scroll.setCorner(JScrollPane.UPPER_RIGHT_CORNER, cornerButtonTop); 
     scroll.setCorner(JScrollPane.LOWER_RIGHT_CORNER, cornerButtonBottom); 
     scroll.setViewportView(myTable); 
     scroll.setMinimumSize(new Dimension(600, 400)); 
     scroll.setMaximumSize(new Dimension(900, 600)); 
     scroll.setPreferredSize(new Dimension(850, 430)); 
     frame.add(scroll, BorderLayout.CENTER); 
     buttonPanel.setLayout(new GridLayout(1, 4, 10, 10)); 
     startButton.addActionListener(this); 
     startButton.setEnabled(false); 
     stopButton.addActionListener(this); 
     stopButton.setEnabled(false); 
     JButton hideButton = new JButton(); 
     newButton.addActionListener(this); 
     newButton.setEnabled(false); 
     buttonPanel.add(startButton); 
     buttonPanel.add(stopButton); 
     buttonPanel.add(hideButton); 
     buttonPanel.add(newButton); 
     hideButton.setVisible(false); 
     frame.add(buttonPanel, BorderLayout.SOUTH); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocation(100, 100); 
     frame.pack(); 
     frame.setVisible(true); 
     start(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     if (e.getSource() == startButton) { 
      runProcess = true; 
      new Thread(this).start(); 
      myTable.requestFocus(); 
      startButton.setEnabled(false); 
      stopButton.setEnabled(true); 
     } else if (e.getSource() == stopButton) { 
      scroll.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
      runProcess = false; 
      startButton.setEnabled(true); 
      stopButton.setEnabled(false); 
      newButton.setEnabled(true); 
     } else if (e.getSource() == newButton) { 
      runProcess = false; 
      startButton.setEnabled(true); 
      stopButton.setEnabled(false); 
      newButton.setEnabled(false); 
      addNewData(); 
     } 
    } 

    public void addNewData() { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       TableModel model = myTable.getModel(); 
       for (int j = 0; j < model.getRowCount(); j++) { 
        int column = model.getColumnCount(); 
        for (int i = 0; i < column; i++) { 
         model.setValueAt("Deleted", j, i); 
        } 
       } 
       startNewData(); 
      } 
     }); 
    } 

    private void start() { 
     scroll.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 
     timer = new javax.swing.Timer(delay * 100, updateCol()); 
     timer.start(); 
    } 

    private void startNewData() { 
     scroll.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 
     count = 0; 
     timer = new javax.swing.Timer(1500, updateCol()); 
     timer.start(); 
    } 

    @Override 
    public void run() { 
     scroll.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 
     count = 0; 
     Random random = new Random(); 
     while (runProcess) { 
      row = random.nextInt(myTable.getRowCount()); 
      column = random.nextInt(myTable.getColumnCount()); 
      SwingUtilities.invokeLater(new Runnable() { 

       @Override 
       public void run() { 
        try { 
         amndValue++; 
         valueAt = ((myTable.getValueAt(row, column)).toString()); 
         if (!(valueAt.startsWith("A"))) { 
          count++; 
          if (count == ((25 * 6))) { 
           JOptionPane.showMessageDialog(myTable, " Update done "); 
           scroll.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
           runProcess = false; 
          } 
          java.util.Date date = new java.util.Date(); 
          String dateTime = sdf.format(date.getTime()); 
          myTable.setValueAt((value + " " + String.valueOf(amndValue) + " at: " + dateTime), row, column); 
          //myTable.setValueAt(new Integer(1), row, column); // please uncoment for generate misstype error on EDT 
          myTable.changeSelection(row, column, false, false); 
          System.out.println("update cycle with value :" 
            + (value + " " + String.valueOf(amndValue) + " at: " + dateTime) + ", table row :" + row 
            + ", table column " + column); 
         } 
        } catch (Exception e) { 
         runProcess = false; 
         System.out.println("Error for update JTable cell"); 
         e.printStackTrace(); 
        } 
       } 
      }); 
      try { 
       Thread.sleep(500); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    public Action updateCol() { 
     return new AbstractAction("text load action") { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 

       System.out.println("updating row " + (count + 1)); 
       TableModel model = myTable.getModel(); 
       int cols = model.getColumnCount(); 
       int row = 0; 
       for (int j = 0; j < cols; j++) { 
        row = count; 
        myTable.changeSelection(row, 0, false, false); 
        timer.setDelay(200); 
        Object value = "row " + (count + 1) + " item " + (j + 1); 
        model.setValueAt(value, count, j); 
       } 
       count++; 
       if (count >= myTable.getRowCount()) { 
        myTable.changeSelection(0, 0, false, false); 
        timer.stop(); 
        System.out.println("update cycle completed"); 
        myTable.clearSelection(); 
        startButton.setEnabled(true); 
        newButton.setEnabled(true); 
        scroll.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
       } 
      } 
     }; 
    } 

    public static void main(String args[]) { 
     try { 
      for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { 
       System.out.println(info.getName()); 
       if ("Nimbus".equals(info.getName())) { 
        UIManager.setLookAndFeel(info.getClassName()); 
        break; 
       } 
      } 
     } catch (UnsupportedLookAndFeelException e) { 
      // handle exception 
     } catch (ClassNotFoundException e) { 
      // handle exception 
     } catch (InstantiationException e) { 
      // handle exception 
     } catch (IllegalAccessException e) { 
      // handle exception 
     } 
     TableWithTimer tableWithTimer = new TableWithTimer(); 
    } 
} 

class TableBackroundPaint0 extends JTable { 

    private static final long serialVersionUID = 1L; 

    TableBackroundPaint0(Object[][] data, Object[] head) { 
     super(data, head); 
     setOpaque(false); 
     ((JComponent) getDefaultRenderer(Object.class)).setOpaque(false); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     Color background = new Color(168, 210, 241); 
     Color controlColor = new Color(230, 240, 230); 
     int width = getWidth(); 
     int height = getHeight(); 
     Graphics2D g2 = (Graphics2D) g; 
     Paint oldPaint = g2.getPaint(); 
     g2.setPaint(new GradientPaint(0, 0, background, width, 0, controlColor)); 
     g2.fillRect(0, 0, width, height); 
     g2.setPaint(oldPaint); 
     for (int row : getSelectedRows()) { 
      Rectangle start = getCellRect(row, 0, true); 
      Rectangle end = getCellRect(row, getColumnCount() - 1, true); 
      g2.setPaint(new GradientPaint(start.x, 0, controlColor, (int) ((end.x + end.width - start.x) * 1.25), 0, Color.orange)); 
      g2.fillRect(start.x, start.y, end.x + end.width - start.x, start.height); 
     } 
     super.paintComponent(g); 
    } 
} 
+0

+1 for'javax.swing.Timer';漸變也很有趣。 – trashgod 2011-05-29 16:34:50

+0

@trashgod這個漸變是一件藝術品,對於視口和SelectedRow(s)也是如此,Nimbus是非常冷酷的,但是這個http://stackoverflow.com/questions/1249278/how-to-disable-the-default-在Nimbus L&F, – mKorbel 2011-05-29 18:33:50