簡體   English   中英

JTable:如何使用TableCellRenderer實現自定義翻轉效果

[英]JTable: how to achieve custom rollover effect with TableCellRenderer

我已經使用TableCellRenderer在我的JTable中添加了一張帶有JLabel的圖片。 但是當鼠標在特定列和行上移動時,如何在JLabel上添加邊框?

這是第一個渲染器類:

public class RenderTabel implements TableCellRenderer{
@Override
public Component getTableCellRendererComponent(JTable table, Object 
value,boolean isSelected, boolean hasFocus,int row, int column){

   JLabel gambar=new JLabel();
   String url="D:\\Kuliah Semester 4\\Pemrograman Berorientasi Objek\\DINUS BOOKSTORE\\image";
   ImageIcon img=scalegmbr(url+"\\"+table.getModel().getValueAt(row, 0)+".png");
   gambar.setIcon(img);
   gambar.setText("");
   gambar.setHorizontalAlignment(SwingConstants.CENTER);


        table.setRowHeight(row, 50);


        table.getColumnModel().getColumn(column).setPreferredWidth(80); 
 return gambar;       
 }
  public  ImageIcon scalegmbr(String file){
   Image image=new ImageIcon(file).getImage();
   return new ImageIcon(image.getScaledInstance(80,50,SCALE_SMOOTH));
 }
 }

這是第二個渲染器類:

public class RenderTabel1 implements TableCellRenderer{
@Override
public Component getTableCellRendererComponent(JTable table, Object 
value,boolean isSelected, boolean hasFocus,int row, int column){

   JLabel gambar=new JLabel();
   String url="D:\\Kuliah Semester 4\\Pemrograman Berorientasi Objek\\DINUS BOOKSTORE\\image";
   ImageIcon img=scalegmbr(url+"\\"+table.getModel().getValueAt(row, 0)+".png");
   gambar.setIcon(img);
   gambar.setText("");
   gambar.setHorizontalAlignment(SwingConstants.CENTER);
  gambar.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(200, 100, 52), 2));

        table.setRowHeight(row, 50);


        table.getColumnModel().getColumn(column).setPreferredWidth(80); 
  return gambar;       
  }
   public  ImageIcon scalegmbr(String file){
   Image image=new ImageIcon(file).getImage();
   return new ImageIcon(image.getScaledInstance(80,50,SCALE_SMOOTH));
 }
}

這就是我在JTable中設置鼠標輸入和鼠標單擊的方法:

private void tblbukuMouseEntered(java.awt.event.MouseEvent evt) {                                     
    // TODO add your handling code here: 



    tblbuku.getColumnModel().getColumn(6).setCellRenderer( new RenderTabel1());
}                                    

private void tblbukuMouseExited(java.awt.event.MouseEvent evt) {                                    
    // TODO add your handling code here:
    tblbuku.getColumnModel().getColumn(6).setCellRenderer( new RenderTabel());

}   

但是,當鼠標移動到該列的單元格時,這會為第6列中的所有單元格添加邊框。 當鼠標輸入該行和列時,如何將其僅更改為特定的行和列?

因此,對於表格的特定列,您希望在鼠標懸停的單元格上繪制邊框(僅限於懸停的單元格,僅在此列中)。

(編輯:澄清后,似乎之前已經問過這個問題 - 我將在下面留下我的答案,因為它可能仍然有幫助)

  • 不要動態更改單元格渲染器,該列只有一個渲染器,並在單個渲染器中處理該情況。

  • 不要在渲染器返回的Component上添加偵聽器:不會觸發此類偵聽器,因為該組件僅用於其paint() ing邏輯。

  • 相反,在表本身上添加一個鼠標移動偵聽columnAtPoint ,當鼠標在表格上移動或退出該區域時,使用JTable的方法rowAtPointcolumnAtPoint計算懸停單元格的坐標。

  • (與手頭的問題無關,但值得一提)避免為渲染器的每次調用創建一個新的JLabel ,這很浪費。 Swing是單線程的,重用同一個對象是安全的(前提是你不要忘記重置它在2次調用之間可能已經改變的所有屬性)

顯示效果的小型演示:

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class SimpleTableDemo extends JPanel {

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(SimpleTableDemo::createAndShowGUI);
    }

    private int
            hoveredRow = -1,
            hoveredColumn = -1;

    SimpleTableDemo() {
        super(new GridLayout(1,0));

        String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"};

        Object[][] data = {
                {"Kathy", "Smith", "Snowboarding", 5, Boolean.FALSE},
                {"John", "Doe", "Rowing", 3, Boolean.TRUE},
                {"Sue", "Black", "Knitting", 2, Boolean.FALSE},
                {"Jane", "White", "Speed reading", 20, Boolean.TRUE},
                {"Joe", "Brown", "Pool", 10, Boolean.FALSE}
        };

        final JTable table = new JTable(data, columnNames);
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);
        table.getColumn("Sport").setCellRenderer(new MyCellRenderer());

        table.addMouseMotionListener(new MouseAdapter() {
            public void mouseMoved(MouseEvent e) {
                Point p = e.getPoint();
                hoveredRow = table.rowAtPoint(p);
                hoveredColumn = table.columnAtPoint(p);
                table.repaint();
            }
            public void mouseExited(MouseEvent e) {
                hoveredRow = hoveredColumn = -1;
                table.repaint();
            }
        });

        JScrollPane scrollPane = new JScrollPane(table);

        add(scrollPane);
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("SimpleTableDemo");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        SimpleTableDemo newContentPane = new SimpleTableDemo();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    private class MyCellRenderer extends DefaultTableCellRenderer {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if (hoveredColumn == column && hoveredRow == row) {
                label.setBorder(BorderFactory.createLineBorder(Color.GREEN, 2));
            }
            else {
                label.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
            }
            return label;
        }
    }

}

注1:我使用默認的單元格渲染器,與您不同,但同樣的想法適用。 上面的演示是一個通用示例,作為示例保留在這里比您的案例的特定解決方案更有用(例如,在我對問題的解釋中,我理解有關圖標的細節是無關緊要的)。

注意2:在演示中,我每次重新繪制整個可見區域,但是如果你想要優化它,應該可以只重繪2個單元格,這是一個全新的問題,請看這里尋求幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM