2013-01-21 14 views
5

Chcę dodać do mojego systemu inny wzór/model JTable. Jest to prosty projekt, ale dla mnie (jako nowicjusza) mam trudności z ustawianiem tego rodzaju stołu. Chcę, aby tabela wyglądała tak: table design with bold last columnJak utworzyć inny model JTable?

Czy jest możliwe zaprojektowanie takiej tabeli w Javie? Proszę, podziel się swoim pomysłem.

+1

Pewnie, że tak. Ale co próbowaliście? – Logan

+0

Zawsze kończyłem na wspólnym/tradycyjnym modelu jTable. nagłówek tabeli, komórki i wspólna granica. –

+0

Och, mówisz o wyglądzie tego. Według modelu myślałem, że mówisz o 'JTableModel' dla niestandardowych nazw kolumn i typów komórek i tym podobnych. – Logan

Odpowiedz

9

Istnieje wiele różnych sposobów można osiągnąć ten wynik ...

enter image description here

Tutaj mam zastąpić nagłówek z własnej implementacji, ustawić domyślny mechanizm renderujący komórki dla typu Double do mój własny TableCellRenderer i dostosować niektóre z wbudowanych właściwości tabeli.

public class FancyTable { 

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

    public FancyTable() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JTable table = new JTable(new LoanModel()); 
       table.setTableHeader(new SingleColumnTableHeader()); 
       table.setFillsViewportHeight(true); 
       table.setShowHorizontalLines(true); 
       table.setShowVerticalLines(false); 
       table.setGridColor(Color.LIGHT_GRAY); 
       table.setDefaultRenderer(Double.class, new CurrencyRenderer()); 

       JScrollPane scrollPane = new JScrollPane(table); 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(scrollPane); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 

     }); 
    } 

    public class LoanModel extends AbstractTableModel { 

     private List<Loan> loans; 

     public LoanModel() { 
      loans = new ArrayList<Loan>(25); 
      loans.add(new Loan("Davies S.J", 2500000)); 
      loans.add(new Loan("Lucas M.M", 1700000)); 
      loans.add(new Loan("Smith R.B", 600000)); 
      loans.add(new Loan("Jones T.T", 435000)); 
      loans.add(new Loan("Brown R.B", 600000)); 
      loans.add(new Loan("Walls T.T", 435000)); 
      loans.add(new Loan("Healy R.B", 600000)); 
      loans.add(new Loan("Taylor T.T", 435000)); 
      loans.add(new Loan("Ginns R.B", 600000)); 
      loans.add(new Loan("Murphy H", 435000)); 
     } 

     @Override 
     public int getRowCount() { 
      return loans.size(); 
     } 

     @Override 
     public int getColumnCount() { 
      return 2; 
     } 

     @Override 
     public Class<?> getColumnClass(int columnIndex) { 
      Class clazz = String.class; 
      switch (columnIndex) { 
       case 1: 
        clazz = Double.class; 
        break; 
      } 
      return clazz; 
     } 

     @Override 
     public Object getValueAt(int rowIndex, int columnIndex) { 
      Object value = null; 
      Loan loan = loans.get(rowIndex); 
      switch (columnIndex) { 
       case 0: 
        value = loan.getName(); 
        break; 
       case 1: 
        value= loan.getAmount(); 
        break; 
      } 
      return value; 
     } 

    } 

    public class Loan { 

     private String name; 
     private double amount; 

     public Loan(String name, double amount) { 
      this.name = name; 
      this.amount = amount; 
     } 

     public String getName() { 
      return name; 
     } 

     public double getAmount() { 
      return amount; 
     } 

    } 

    public class CurrencyRenderer extends DefaultTableCellRenderer { 

     private Font boldFont; 

     public CurrencyRenderer() { 
      setHorizontalAlignment(JLabel.RIGHT); 
      boldFont = getFont().deriveFont(Font.BOLD); 
     } 

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

      if (value instanceof Double) { 
       value = NumberFormat.getCurrencyInstance().format(value); 
      } 

      super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
      setFont(boldFont); 

      return this; 
     } 

    } 

    public class SingleColumnTableHeader extends JTableHeader { 

     private JLabel renderer; 

     public SingleColumnTableHeader() { 
      setBackground(Color.WHITE); 
      renderer = new JLabel("Top Ten Loan Balances"); 
      renderer.setBorder(new EmptyBorder(4, 0, 4, 0)); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return renderer.getPreferredSize(); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      FontMetrics fm = g2d.getFontMetrics(); 

      Insets insets = getInsets(); 
      int width = getWidth() - (insets.left + insets.right); 
      int height = getHeight() - (insets.top + insets.bottom); 

      renderer.setBounds(insets.left, insets.top, width, height); 
      renderer.paint(g2d); 

      g2d.setColor(Color.LIGHT_GRAY); 
      g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 
      g2d.drawLine(insets.left, insets.top + height - 1, insets.left + width, insets.top + height - 1); 

      g2d.dispose(); 
     } 

    } 

} 

Po prostu jak łatwo stworzyć swój własny JTable i zastąpić configureEnclosingScrollPane ustawić własny komponent nagłówku tabeli, ale osobiście uważam, że to koniec zabić.

Będąc w stanie dostarczyć własne renderujące jest znacznie bardziej elastyczne podejście i promuje ponowne wykorzystanie elementów składowych, z obecnie produkuje kod szczelnie para ...

może okazać się przydatny do odczytu przez How to use Tables

Updated

Przyszło mi do głowy, po coś Guillaume powiedział, można po prostu ustaw JTable s nagłówek null.Następnie po dodaniu tabeli do okienka przewijania można po prostu ustawić użytkownika jako JScrollPane#setColumnHeaderView, tak aby ustawić nagłówek na coś podobnego do JLabel.

Byłoby łatwiej konieczności wdrożenia jesteś właścicielem JTableHeader

+0

+1 To znacznie lepszy wybór. –

+0

+1 za odpowiedź. Więc muszę użyć ** getTableCellRendererComponent **. Dziękuję bardzo. – Amarnath

5

Zastąpić metodę prepareRendere przy JTable. Dla kolumny 1, która zawiera tekst, użyj jednej czcionki, a dla kolumny 2 użyj innej czcionki.

enter image description here

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Font; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.table.TableCellRenderer; 

public class JTableExample { 
public static void main(String[] args) { 

    Object[] column = {"Column One", "Column Two"}; 
    Object[][] data = {{"One", "Two"}, {"Three", "Four"}, {"Five", "Five"}}; 

    JTable toDoTable = new JTable(data, column) { 
     @Override 
     public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, 
       int columnIndex) { 
      if(columnIndex == 1) { 
       setFont(new Font("Arial", Font.BOLD, 12)); 
      } else { 
       setFont(new Font("Arial", Font.ITALIC, 12)); 
      } 

      return super.prepareRenderer(renderer, rowIndex, columnIndex); 
     } 
    }; 
    JScrollPane jpane = new JScrollPane(toDoTable); 
    JPanel panel = new JPanel(); 
    JFrame frame = new JFrame(); 
    frame.setSize(new Dimension(400, 100)); 
    frame.setTitle("JTable Font Setting Example"); 
    panel.add(jpane); 
    frame.add(new JScrollPane(panel)); 
    frame.setVisible(true); 
} 
} 

UPDATE:

Jak MadProgrammer i Guillaume Polet zasugerował. I zmodyfikowane moje podejście z wykorzystaniem DefaultTableCellRenderer (przy użyciu kodu Guillaume Polet jako odniesienie.)

enter image description here

import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Font; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.table.DefaultTableCellRenderer; 

public class JTableExample { 
public static void main(String[] args) { 

    Object[] column = {"Column One", "Column Two"}; 
    Object[][] data = {{"One", "Two"}, {"Three", "Four"}, {"Five", "Five"}}; 

    JTable table = new JTable(data, column); 

    table.getColumnModel().getColumn(1).setCellRenderer(new CustomTableCellRenderer()); 
    table.setShowGrid(false); 
    table.setTableHeader(null); 
    JLabel label = new JLabel("Top 10 by Loan Balance"); 
    label.setFont(label.getFont().deriveFont(15.0f)); 
    JScrollPane scroll = new JScrollPane(table); 
    JFrame frame = new JFrame(); 
    frame.setSize(new Dimension(400, 100)); 
    frame.setTitle("JTable Font Setting Example"); 
    frame.add(label, BorderLayout.NORTH); 
    frame.add(scroll, BorderLayout.CENTER); 
    frame.setVisible(true); 
} 
} 

class CustomTableCellRenderer extends DefaultTableCellRenderer { 
    @Override 
    public Component getTableCellRendererComponent(JTable table, Object aValue, 
      boolean isSelected, boolean hasFocus, int rowIndex, int columnIndex) { 
     Component component = super.getTableCellRendererComponent(table, aValue, isSelected, hasFocus, rowIndex, columnIndex); 
     component.setFont(component.getFont().deriveFont(Font.BOLD)); 
     return component; 
    } 
} 

PS:

table.setTableHeader (null): => do ukrywania kolumn posługiwać się.

DefaultTableCellRenderer: => Zwraca domyślną komórkę tabeli renderer. Użyj tego, aby stworzyć styl czcionki kolumny 1.

table.setShowGrid (fałsz); => To spowoduje, że linie w JTable jako będą niewidoczne.

+0

powyższy przykład nie ma nagłówka tabeli, prawda? czy to możliwe w java? –

+1

Jeśli masz na myśli etykietę "Top 10 by Loan Balance", umieściłbym ją nad tabelą za pomocą 'JLabel'. –

+0

tak to oczywiste, że to jest etykieta. Liczy się tylko górna i dolna linia graniczna oraz ukryte nagłówki. Jak to zrobić w 'jTable'. –

3

Jeszcze innym sposobem, aby to zrobić. Użyj odpowiedniego CellRenderera, aby uzyskać różne style i zarządzać wyrównaniem tekstu. Jeśli chodzi o wyłączanie TableHeadera, po prostu ustaw go na null na JTable.

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Font; 
import java.util.Random; 
import java.util.Vector; 

import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.table.DefaultTableCellRenderer; 

public class TestTableHeader { 

    public static class BoldTableCellRenderer extends DefaultTableCellRenderer { 

     public BoldTableCellRenderer() { 
      setHorizontalAlignment(RIGHT); 
     } 

     @Override 
     public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
      Component renderer = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
      renderer.setFont(renderer.getFont().deriveFont(Font.BOLD)); 
      return renderer; 
     } 
    } 

    protected void initUI() { 
     Vector<Vector<Object>> datas = new Vector<Vector<Object>>(); 
     Vector<String> colNames = new Vector<String>(); 
     for (int i = 0; i < 2; i++) { 
      colNames.add("Col-" + (i + 1)); 
     } 
     for (int i = 0; i < 15; i++) { 
      Vector<Object> data = new Vector<Object>(); 
      data.add("John Smith (" + (i + 1) + ")"); 
      data.add(new Random().nextInt(4000)); 
      datas.add(data); 
     } 

     table = new JTable(datas, colNames); 
     table.setShowGrid(false); 
     table.getColumnModel().getColumn(1).setCellRenderer(new BoldTableCellRenderer()); 
     table.setFillsViewportHeight(false); 
     table.setTableHeader(null); 
     table.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.GRAY)); 
     JLabel label = new JLabel("Top 10 by Loan Balance"); 
     label.setFont(label.getFont().deriveFont(15.0f)); 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     scrollpane = new JScrollPane(table); 
     scrollpane.setRowHeaderView(null); 
     frame.add(label, BorderLayout.NORTH); 
     frame.add(scrollpane, BorderLayout.CENTER); 
     frame.setSize(300, 200); 
     frame.setVisible(true); 
    } 

    private JTable table; 
    private JScrollPane scrollpane; 

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, 
      UnsupportedLookAndFeelException { 
     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new TestTableHeader().initUI(); 
      } 
     }); 
    } 

} 
+0

+1 Jeśli wszystko, co chciał OP, to wyświetlić 'JLabel' jako nagłówek, powinni (powinni) być w stanie dodać tabelę do' JScrollPane', a następnie ustawić widok nagłówka przewijania, używając tam własnego 'JLabel' - +1 dla pustego nagłówka! – MadProgrammer