Попытка создания JTable с правильным заголовком строки
Я пытаюсь создать JTable, который имеет заголовок строки, который выглядит так же, как заголовок столбца, и я потратил на это слишком много времени:/
Моя ситуация похожа на этот вопрос: JTable Row Header Implementation
и, возможно, это:
настройка jtable cellrenderer с цветом заголовка ячейки таблицы
Кажется, они все еще не дошли до меня. Я искал много примеров, и все не хватает. Даже нет примеров таблиц с заголовками строк от Oracle/Sun. Кажется, что такая таблица не должна быть такой редкой.
Этот формат только форматирует первый столбец, но он не совсем выглядит или действует как заголовок столбца:
http://java-swing-tips.blogspot.com/2011/01/jtable-rowheader.html
Этот, кажется, использует JList для заголовка строки, и у него есть проблемы с выравниванием (выключено на +1 пиксель в каждой строке) и не выглядит лучше, когда я устанавливаю Look and Feel.
http://www.java2s.com/Code/Java/Swing-Components/TableRowHeaderExample.htm
Это похоже на идею, которую мне нужно использовать (заголовок строки является отдельным JTable, но затем загружается в JScrollPane в качестве заголовка строки), но мне нужно адаптировать его к моему коду, а затем убедитесь, что заголовок строки получает правильный внешний вид заголовка.
http://www.chka.de/swing/table/row-headers/JTable.html
Вот что я сделал минус последний бит. Я пытаюсь заставить рендеринга заголовка таблицы быть рендерером для заголовка строки. Заголовок заголовка/первый столбец теперь серый, а не белый, как это было тогда, когда это был только другой столбец данных, но по-прежнему не похож на заголовок столбца. Это правильно? Или я должен придерживаться его как регулярного столбца в главной таблице и делать с ним что-то еще?
Итак, вот мой код для обновления таблицы. Этот метод просто принимает массив String для заголовка столбца, массив String для заголовка строки и массив 2D String для основных данных. У меня есть JTable dispTableRowHeader для заголовка строки и JTable dispTable для основной таблицы данных.
private void updateDispTable(String[][] graphicalTable, String[] graphicalTableColumnHeader, String[] graphicalTableRowHeader) {
//set model for the main data table, put in data. Also prevent editing cells
dispTable.setModel(new javax.swing.table.DefaultTableModel(
graphicalTable,
graphicalTableColumnHeader
){
@Override
public boolean isCellEditable(int rowIndex, int mColIndex) {
return false;
}
});
//some mods for main data table
dispTable.getTableHeader().setReorderingAllowed(false);//Was also able to do this within NetBeans GUI Builder by doing Table Contents from Jtable inspector item
dispTable.getTableHeader().setResizingAllowed(false);
//load main table to scrollpane
jScrollPane2.setViewportView(dispTable);
//get model for JTable that will be used as the row header, fill in values
DefaultTableModel rowHeaderTableModel = new DefaultTableModel(0, 1);//one column
for (int i = 0; i < graphicalTable.length; i++)
rowHeaderTableModel.addRow(new Object[] { graphicalTableRowHeader[i] } );
//set model for row header, put in data. Alter renderer to make it like col header
dispTableRowHeader.setModel(rowHeaderTableModel);
dispTableRowHeader.setDefaultRenderer(Object.class, dispTableRowHeader.getTableHeader().getDefaultRenderer());//makes it gray but not like the header :/
//dispTableRowHeader.setDefaultRenderer(Object.class, jScrollPane2.getColumnHeader().getDefaultRenderer());
//load row header to scrollpane row header
jScrollPane2.setRowHeaderView(dispTableRowHeader);
//set the table corner and disallow reordering and resizing
JTableHeader corner = dispTableRowHeader.getTableHeader();
corner.setReorderingAllowed(false);
corner.setResizingAllowed(false);
jScrollPane2.setCorner(JScrollPane.UPPER_LEFT_CORNER, corner);//load to scrollpane
}
Я очень благодарен за любую помощь!
ИЗМЕНИТЬ НИЖЕ ИЗМЕНИТЬ НИЖЕ
Я создал совершенно новый проект для эксперимента и попробовал метод trashgod (хотя и делал это для заголовка строки, а не как для второй строки), и я обнаружил, что он дал мне тот же результат, что и только в стиле серого, а не в стиле, подобном заголовку. Затем я попытался удалить настройку Look and Feel
// Set System L&F
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
а затем заголовок строки выглядел так же, как заголовок столбца!.. но что в Нимбусе или что-то по-умолчанию выглядят и чувствуют. См. Изображения ниже. Во-первых, мой Look and Feel установлен в систему, как указано выше (в Win7), а второй по умолчанию.
Системный взгляд и чувство (Win7) - ![I adjusted look and feel, set to system look and feel]()
Java Nimbus Look and Feel- ![default look and feel]()
Конечно же, с моей программой происходит то же самое. Итак, теперь моя проблема связана с Look and Feel. Я хочу, чтобы это выглядело как первое изображение (внешний вид системы), но с левым стилем тоже.
Кстати, вот пример в Win7 из MySQL Workbench, который имеет правильно оформленные заголовки строк и столбцов, и они оба даже затеняют ячейки синеватой на мыши. Жаль, что это не сделано на Java, поэтому я могу попытаться проверить, как они это сделали.
Скриншот MySQL Workbench- ![MySQL Workbench screenshot]()
ИЗМЕНИТЬ НИЖЕ ИЗМЕНИТЬ НИЖЕ
Код SSCCE
package mytableexample2;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
public class MyTableExample2 extends javax.swing.JFrame {
public MyTableExample2() {
initComponents();
}
@SuppressWarnings("unchecked")
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable(){
@Override
public Component prepareRenderer(
TableCellRenderer renderer, int row, int col) {
if (col == 0) {
return this.getTableHeader().getDefaultRenderer()
.getTableCellRendererComponent(this,
this.getValueAt(row, col), false, false, row, col);
} else {
return super.prepareRenderer(renderer, row, col);
}
}
};
jTable1.setAutoCreateRowSorter(false);
final JTableHeader header = jTable1.getTableHeader();
header.setDefaultRenderer(new HeaderRenderer(jTable1));
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{"Row 1", "Data 2", "Data 3", "Data 4", "Data 5"},
{"Row 2", "Data 6", "Data 7", "Data 8", "Data 9"},
{"Row 3", "Data 10", "Data 11", "Data 12", "Data 13"}
},
new String [] {
"", "Col 1", "Col 2", "Col 3", "Col 4"
}
));
jScrollPane1.setViewportView(jTable1);
//Netbeans generated layout
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}
public static void main(String args[]) {
try {
//THIS SETS TO SYSTEM LOOK AND FEEL
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
//THIS SETS TO OTHER JAVA LOOK AND FEEL
//UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
//UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MyTableExample2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MyTableExample2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MyTableExample2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MyTableExample2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MyTableExample2().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTable1;
}
class HeaderRenderer implements TableCellRenderer {
TableCellRenderer renderer;
public HeaderRenderer(JTable jTable1) {
renderer = jTable1.getTableHeader().getDefaultRenderer();
}
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int col) {
return renderer.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, col);
}
}
Ответы
Ответ 1
Используя этот HeaderRenderer
в качестве первого рендерера столбца строки , вы можете получить нужный эффект:
Приложение: я обновил этот пример, чтобы отразить ваш sscce с макетом. Моя платформа getSystemLookAndFeelClassName()
равна com.apple.laf.AquaLookAndFeel
, поэтому я не вижу того же результата. Два наблюдения. У вас уже есть setAutoCreateRowSorter(false)
, чтобы предотвратить размножение виджета сортировки, а Nimbus сохраняет переменную выделение строки.
![enter image description here]()
import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
public class MyTableExample3 extends JFrame {
private JScrollPane scrollPane;
private JTable table;
public MyTableExample3() {
initComponents();
}
@SuppressWarnings("unchecked")
private void initComponents() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
table = new javax.swing.JTable() {
@Override
public Component prepareRenderer(
TableCellRenderer renderer, int row, int col) {
if (col == 0) {
return this.getTableHeader().getDefaultRenderer()
.getTableCellRendererComponent(this, this.getValueAt(
row, col), false, false, row, col);
} else {
return super.prepareRenderer(renderer, row, col);
}
}
};
table.setAutoCreateRowSorter(false);
final JTableHeader header = table.getTableHeader();
header.setDefaultRenderer(new HeaderRenderer(table));
table.setModel(new javax.swing.table.DefaultTableModel(
new Object[][]{
{"Row 1", "Data 2", "Data 3", "Data 4", "Data 5"},
{"Row 2", "Data 6", "Data 7", "Data 8", "Data 9"},
{"Row 3", "Data 10", "Data 11", "Data 12", "Data 13"}
},
new String[]{
"", "Col 1", "Col 2", "Col 3", "Col 4"
}));
scrollPane = new JScrollPane(table);
this.add(scrollPane);
pack();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new MyTableExample3().setVisible(true);
}
});
}
private static class HeaderRenderer implements TableCellRenderer {
TableCellRenderer renderer;
public HeaderRenderer(JTable table) {
renderer = table.getTableHeader().getDefaultRenderer();
}
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int col) {
return renderer.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, col);
}
}
}
Ответ 2
возможно
![enter image description here]()
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.UIManager.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class JTableRowHeader {
private JFrame frame = new JFrame("JTable RowHeader");
private JScrollPane scrollPane;
private JTable table;
private DefaultTableModel model;
private TableRowSorter<TableModel> sorter;
private JTable headerTable;
public JTableRowHeader() {
table = new JTable(4, 4);
for (int i = 0; i < table.getRowCount(); i++) {
table.setValueAt(i, i, 0);
}
sorter = new TableRowSorter<TableModel>(table.getModel());
table.setRowSorter(sorter);
model = new DefaultTableModel() {
private static final long serialVersionUID = 1L;
@Override
public int getColumnCount() {
return 1;
}
@Override
public boolean isCellEditable(int row, int col) {
return false;
}
@Override
public int getRowCount() {
return table.getRowCount();
}
@Override
public Class<?> getColumnClass(int colNum) {
switch (colNum) {
case 0:
return String.class;
default:
return super.getColumnClass(colNum);
}
}
};
headerTable = new JTable(model);
for (int i = 0; i < table.getRowCount(); i++) {
headerTable.setValueAt("Row " + (i + 1), i, 0);
}
headerTable.setShowGrid(false);
headerTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
headerTable.setPreferredScrollableViewportSize(new Dimension(50, 0));
headerTable.getColumnModel().getColumn(0).setPreferredWidth(50);
headerTable.getColumnModel().getColumn(0).setCellRenderer(new TableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable x, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
boolean selected = table.getSelectionModel().isSelectedIndex(row);
Component component = table.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table, value, false, false, -1, -2);
((JLabel) component).setHorizontalAlignment(SwingConstants.CENTER);
if (selected) {
component.setFont(component.getFont().deriveFont(Font.BOLD));
component.setForeground(Color.red);
} else {
component.setFont(component.getFont().deriveFont(Font.PLAIN));
}
return component;
}
});
table.getRowSorter().addRowSorterListener(new RowSorterListener() {
@Override
public void sorterChanged(RowSorterEvent e) {
model.fireTableDataChanged();
}
});
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
model.fireTableRowsUpdated(0, model.getRowCount() - 1);
}
});
scrollPane = new JScrollPane(table);
scrollPane.setRowHeaderView(headerTable);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(scrollPane);
frame.add(new JButton(new AbstractAction("Toggle filter") {
private static final long serialVersionUID = 1L;
private RowFilter<TableModel, Object> filter = new RowFilter<TableModel, Object>() {
@Override
public boolean include(javax.swing.RowFilter.Entry<? extends TableModel, ? extends Object> entry) {
return ((Number) entry.getValue(0)).intValue() % 2 == 0;
}
};
@Override
public void actionPerformed(ActionEvent e) {
if (sorter.getRowFilter() != null) {
sorter.setRowFilter(null);
} else {
sorter.setRowFilter(filter);
}
}
}), BorderLayout.SOUTH);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
try {// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (info.getName().equals("Nimbus")) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
//e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JTableRowHeader TestTableRowHeader = new JTableRowHeader();
}
});
}
}
Вот он с системой Look and Feel-
![enter image description here]()