gpt4 book ai didi

Java Swing - Nimbus L&F 在应用排序后覆盖 JTable header 中的自定义图标

转载 作者:搜寻专家 更新时间:2023-11-01 01:45:50 24 4
gpt4 key购买 nike

我正在尝试创建一个自定义单元格渲染器,它将在 JTable 的标题单元格中显示图像。我已经获得了用于 Metal L&F 的源代码,但我在使用 Nimbus 时遇到了问题。在正常情况下,Nimbus 可以很好地显示图像。然而,当表格被排序时,Nimbus 将绘制排序图标而不是我指定的图标。这与 Metal L&F 不同,因为它始终会绘制我提供的图标。

Example image demonstrating error in Nimbus L&F vs Metal L&F

有谁知道即使列已排序也能让 Nimbus 绘制图像的方法?

我正在使用 Java 6.29 和 Nimbus。我无法更改 Java 版本或 L&F。

另外,我尝试过一些其他的解决方法,比如将标签更改为使用 HTML 和 img 标签来显示图像,但这会产生奇怪的视觉效果。编辑文本和图像没有很好地对齐(即使 img 标签上有 HTML 对齐标签)这是一张图片,请注意 Temp Hi 列中的文本如何不对齐:

example image of solution with HMTL and img tag

import java.awt.Component;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;


public class ImageChangeDemo extends JFrame {
public static void main(String args[]) {
//comment out the code below to try in Metal L&F
try {
for(javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.
getInstalledLookAndFeels()) {
if("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch(Exception ex) {
ex.printStackTrace();
}

java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ImageChangeDemo().setVisible(true);
}
});
}

public ImageChangeDemo(){
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
JScrollPane pane = new javax.swing.JScrollPane();
JTable table = new javax.swing.JTable();
table.setAutoCreateRowSorter(true);
table.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{"a", "q", "h", "v"},
{"b", "m", "l", "h"},
{"d", "c", "a", "d"},
{"j", "o", "y", "e"}
},
new String [] {
"Col 1", "Col 2", "Col 3", "Col 4"
}
) {
Class[] types = new Class [] {
String.class, String.class, String.class, String.class
};
@Override
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
});
pane.setViewportView(table);
this.add(pane);

table.getTableHeader().setDefaultRenderer(new ImageRenderer(table));

pack();
}

public class ImageRenderer extends DefaultTableCellRenderer{
TableCellRenderer orig;
ImageIcon icon;
ImageRenderer(JTable table){
orig = table.getTableHeader().getDefaultRenderer();
}
@Override
public Component getTableCellRendererComponent(final JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c =
orig.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
if(c instanceof JLabel){
if(true){
JLabel label = (JLabel)c;
label.setIcon(makeIcon());
}
}
return c;
}

public ImageIcon makeIcon(){
if(icon == null)
icon = new ImageIcon(
ImageChangeDemo.class.getResource("/resources/green_triangle_down.png"));
return icon;
}
}
}

编辑:这是我的实际应用程序应该执行的示例场景:如果表格列包含某些数据(例如任何以特定单词开头的字符串),则在表格标题中的列名称旁边显示一个警告图标。我已经让这个工作正常。现在,如果用户使用图像对列进行排序,Nimbus 会删除图像并将其替换为排序图标 - 我仍然希望显示原始警告图标。

最佳答案

  • 不要在 Renderer 中重新创建 Icon,在此之前做好准备,否则您将在疯狂时期重新创建 Icon

  • 不要将 Icon 添加到 Component/JComponent/JLabel 返回 Renderer

  • 放入Renderer

Darryl 或 Rob 编写的代码

protected Icon getIcon(JTable table, int column) {
SortKey sortKey = getSortKey(table, column);
if (sortKey != null && table.convertColumnIndexToView(
sortKey.getColumn()) == column) {
switch (sortKey.getSortOrder()) {
case ASCENDING:
return UIManager.getIcon("Table.ascendingSortIcon");
case DESCENDING:
return UIManager.getIcon("Table.descendingSortIcon");
}
}
return null;
}

编辑

感谢Renderer by @trashgod , UNSORTED 不需要覆盖渲染器,尝试并享受

初始 View

enter image description here

升序

enter image description here

降序

enter image description here

未排序

enter image description here

import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.UIManager;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class ImageChangeDemo extends JFrame {

private static final long serialVersionUID = 1L;
private JTable table = new javax.swing.JTable();

public static void main(String args[]) {
//comment out the code below to try in Metal L&F
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
java.awt.EventQueue.invokeLater(new Runnable() {

@Override
public void run() {
new ImageChangeDemo().setVisible(true);
}
});
}

public ImageChangeDemo() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
JScrollPane pane = new javax.swing.JScrollPane();



table.setModel(new javax.swing.table.DefaultTableModel(
new Object[][]{
{"a", "q", "h", "v"},
{"b", "m", "l", "h"},
{"d", "c", "a", "d"},
{"j", "o", "y", "e"}
},
new String[]{
"Col 1", "Col 2", "Col 3", "Col 4"
}) {

private static final long serialVersionUID = 1L;
Class[] types = new Class[]{
String.class, String.class, String.class, String.class
};

@Override
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
});
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()) {

@Override
public void toggleSortOrder(int column) {
if (column >= 0 && column < getModelWrapper().getColumnCount() && isSortable(column)) {
List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
if (!keys.isEmpty()) {
SortKey sortKey = keys.get(0);
if (sortKey.getColumn() == column && sortKey.getSortOrder() == SortOrder.DESCENDING) {
setSortKeys(null);
return;
}
}
}
super.toggleSortOrder(column);
}
};
table.setRowSorter(sorter);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.setDefaultRenderer(ImageChangeDemo.class, new HeaderRenderer(table));
pane.setViewportView(table);
add(pane);
pack();
}

class HeaderRenderer implements TableCellRenderer {

final 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);
}

public Icon getIcon(JTable table, int column) {
for (RowSorter.SortKey sortKey : table.getRowSorter().getSortKeys()) {
if (sortKey.getColumn() == column) {
switch (sortKey.getSortOrder()) {
case ASCENDING:
return (UIManager.getIcon("Table.ascendingSortIcon"));
case DESCENDING:
return (UIManager.getIcon("Table.descendingSortIcon"));
}
}
}
return null;
}
}
}

编辑 2

然后直接给UIManager设置Icon

enter image description here

enter image description here

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter.SortKey;
import javax.swing.SortOrder;
import javax.swing.UIManager;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class ImageChangeDemo extends JFrame {

private static final long serialVersionUID = 1L;
private JTable table = new javax.swing.JTable();

public static void main(String args[]) {
//comment out the code below to try in Metal L&F
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
UIManager.getLookAndFeelDefaults().put("Table.ascendingSortIcon", new BevelArrowIcon(BevelArrowIcon.UP, false, false));
UIManager.getLookAndFeelDefaults().put("Table.descendingSortIcon", new BevelArrowIcon(BevelArrowIcon.DOWN, false, false));
break;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
java.awt.EventQueue.invokeLater(new Runnable() {

@Override
public void run() {
new ImageChangeDemo().setVisible(true);
}
});
}

public ImageChangeDemo() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
JScrollPane pane = new javax.swing.JScrollPane();
//table.setAutoCreateRowSorter(true);
table.setModel(new javax.swing.table.DefaultTableModel(
new Object[][]{
{"a", "q", "h", "v"},
{"b", "m", "l", "h"},
{"d", "c", "a", "d"},
{"j", "o", "y", "e"}
},
new String[]{
"Col 1", "Col 2", "Col 3", "Col 4"
}) {

private static final long serialVersionUID = 1L;
Class[] types = new Class[]{
String.class, String.class, String.class, String.class
};

@Override
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
});
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()) {

@Override
public void toggleSortOrder(int column) {
if (column >= 0 && column < getModelWrapper().getColumnCount() && isSortable(column)) {
List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
if (!keys.isEmpty()) {

SortKey sortKey = keys.get(0);
if (sortKey.getColumn() == column && sortKey.getSortOrder() == SortOrder.DESCENDING) {
setSortKeys(null);
return;
}
}
}
super.toggleSortOrder(column);
}
};
table.setRowSorter(sorter);
//table.getTableHeader().setDefaultRenderer(new DefaultTableHeaderCellRenderer());
//table.setDefaultRenderer(ImageChangeDemo.class, new HeaderRenderer(table));
table.setPreferredScrollableViewportSize(table.getPreferredSize());
pane.setViewportView(table);
add(pane);
pack();
}

static class BevelArrowIcon implements Icon {

public static final int UP = 0; // direction
public static final int DOWN = 1;
private static final int DEFAULT_SIZE = 11;
private Color edge1;
private Color edge2;
private Color fill;
private int size;
private int direction;

public BevelArrowIcon(int direction, boolean isRaisedView, boolean isPressedView) {
if (isRaisedView) {
if (isPressedView) {
init(UIManager.getColor("controlLtHighlight"), UIManager.getColor("controlDkShadow"), UIManager.getColor("controlShadow"), DEFAULT_SIZE, direction);
} else {
init(UIManager.getColor("controlHighlight"), UIManager.getColor("controlShadow"), UIManager.getColor("control"), DEFAULT_SIZE, direction);
}
} else {
if (isPressedView) {
init(UIManager.getColor("controlDkShadow"), UIManager.getColor("controlLtHighlight"), UIManager.getColor("controlShadow"), DEFAULT_SIZE, direction);
} else {
init(UIManager.getColor("controlShadow"), UIManager.getColor("controlHighlight"), UIManager.getColor("control"), DEFAULT_SIZE, direction);
}
}
}

public BevelArrowIcon(Color edge1, Color edge2, Color fill, int size, int direction) {
init(edge1, edge2, fill, size, direction);
}

@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
switch (direction) {
case DOWN:
drawDownArrow(g, x, y);
break;
case UP:
drawUpArrow(g, x, y);
break;
}
}

@Override
public int getIconWidth() {
return size;
}

@Override
public int getIconHeight() {
return size;
}

private void init(Color edge1, Color edge2, Color fill, int size, int direction) {
edge1 = Color.red;
edge2 = Color.blue;
this.edge1 = edge1;
this.edge2 = edge2;
this.fill = fill;
this.size = size;
this.direction = direction;
}

private void drawDownArrow(Graphics g, int xo, int yo) {
g.setColor(edge1);
g.drawLine(xo, yo, xo + size - 1, yo);
g.drawLine(xo, yo + 1, xo + size - 3, yo + 1);
g.setColor(edge2);
g.drawLine(xo + size - 2, yo + 1, xo + size - 1, yo + 1);
int x = xo + 1;
int y = yo + 2;
int dx = size - 6;
while (y + 1 < yo + size) {
g.setColor(edge1);
g.drawLine(x, y, x + 1, y);
g.drawLine(x, y + 1, x + 1, y + 1);
if (0 < dx) {
g.setColor(fill);
g.drawLine(x + 2, y, x + 1 + dx, y);
g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
}
g.setColor(edge2);
g.drawLine(x + dx + 2, y, x + dx + 3, y);
g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
x += 1;
y += 2;
dx -= 2;
}
g.setColor(edge1);
g.drawLine(xo + (size / 2), yo + size - 1, xo + (size / 2), yo + size - 1);
}

private void drawUpArrow(Graphics g, int xo, int yo) {
g.setColor(edge1);
int x = xo + (size / 2);
g.drawLine(x, yo, x, yo);
x--;
int y = yo + 1;
int dx = 0;
while (y + 3 < yo + size) {
g.setColor(edge1);
g.drawLine(x, y, x + 1, y);
g.drawLine(x, y + 1, x + 1, y + 1);
if (0 < dx) {
g.setColor(fill);
g.drawLine(x + 2, y, x + 1 + dx, y);
g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
}
g.setColor(edge2);
g.drawLine(x + dx + 2, y, x + dx + 3, y);
g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
x -= 1;
y += 2;
dx += 2;
}
g.setColor(edge1);
g.drawLine(xo, yo + size - 3, xo + 1, yo + size - 3);
g.setColor(edge2);
g.drawLine(xo + 2, yo + size - 2, xo + size - 1, yo + size - 2);
g.drawLine(xo, yo + size - 1, xo + size, yo + size - 1);
}
}
}

关于Java Swing - Nimbus L&F 在应用排序后覆盖 JTable header 中的自定义图标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10915994/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com