gpt4 book ai didi

java - JTable 的页脚

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

JTable 不支持显示包含每列聚合数据的页脚。受建议解决方案的启发 Oracle/Suns bug database这看起来很有希望,我开始采用在滚动 Pane 的边框上绘制页脚的方法。

现在一开始我只想要一个“概念证明”,看起来我快到了,每列都有一个页脚,宽度是同步的。等等 所以它似乎工作得很好,除了一件事,没有文字被绘制!我希望从 getFooterValueAt 返回的虚拟值绘制在每个“页脚单元格”上,但它们都是空白的,只绘制了背景(仅用于测试)。

为什么没有绘制任何文字?我在 paintFooter 中的位置/大小计算有问题吗?

import static java.awt.BorderLayout.CENTER;
import static java.awt.Color.BLUE;
import static java.awt.Color.CYAN;
import static java.awt.Color.GREEN;
import static java.awt.Color.LIGHT_GRAY;
import static java.awt.Color.MAGENTA;
import static java.awt.Color.ORANGE;
import static java.awt.Color.PINK;
import static java.awt.Color.RED;
import static java.awt.Color.WHITE;
import static java.awt.Color.YELLOW;
import static javax.swing.JTable.AUTO_RESIZE_OFF;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;

import javax.swing.CellRendererPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

/**
* Demo application for JTable with footer.
*
* @author Martin Uhlén
*/
public class TableFooterBorderDemo extends JFrame
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new TableFooterBorderDemo().setVisible(true);
}
});
}

private TableFooterBorderDemo()
{
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());

JTable table = createTable();
JScrollPane scroll = new JScrollPane(table);
add(scroll, CENTER);
TableFooter.install(scroll, table);
pack();
positionAtMiddleOfScreen();
}

private void positionAtMiddleOfScreen()
{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setLocation((int) ((screenSize.getWidth() / 2) - (getWidth() / 2)),
(int) ((screenSize.getHeight() / 2) - (getHeight() / 2)));
}

private JTable createTable()
{
Object[][] data = new Object[][]
{
{ "A", "*", "*", "*", "*", "*" },
{ "*", "B", "*", "*", "*", "*" },
{ "*", "*", "C", "*", "*", "*" },
{ "*", "*", "*", "D", "*", "*" },
{ "*", "*", "*", "*", "E", "*" },
{ "*", "*", "*", "*", "*", "F" }
};
Object[] columns = new Object[] { "A", "B", "C", "D", "E", "F" };
DefaultTableModel model = new DefaultTableModel(data, columns);
JTable table = new JTable(model);
table.setAutoResizeMode(AUTO_RESIZE_OFF);
return table;
}

/**
* A Border for JScrollPane that paints a footer for JTable.
*/
private static class TableFooter implements Border
{
private static final Color[] COLORS = {RED, GREEN, BLUE, YELLOW, PINK, CYAN, LIGHT_GRAY, MAGENTA, ORANGE, WHITE};

private final JScrollPane scroll;
private final JTable table;
private final CellRendererPane cellRendererPane;

TableFooter(JScrollPane scroll, JTable table)
{
this.scroll = scroll;
this.table = table;
cellRendererPane = new CellRendererPane();
}

public static TableFooter install(JScrollPane scroll, JTable table)
{
verify(scroll, table);
TableFooter footer = new TableFooter(scroll, table);

RepaintListener repainter = new RepaintListener(scroll);
scroll.getViewport().addChangeListener(repainter);
scroll.getHorizontalScrollBar().addAdjustmentListener(repainter);
table.getColumnModel().addColumnModelListener(repainter);
scroll.setViewportBorder(footer);
return footer;
}

private static void verify(JScrollPane scroll, JTable table)
{
if (scroll.getViewport().getView() != table)
{
throw new IllegalArgumentException("Given table must be inside given scroll pane");
}
}

/**
* @see javax.swing.border.Border#paintBorder(java.awt.Component, java.awt.Graphics, int, int, int, int)
*/
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
{
System.out.println("x: " + x + ", y: " + y + ", width: " + width + ", height: " + height);
System.out.println("viewRect: " + scroll.getViewport().getViewRect());
paintFooter(g, x, y, width, height);
}

private void paintFooter(Graphics g, int x, int y, int width, int height)
{
Color oldColor = null;
Component cellRendererComponent = null;
int columnWidths = x - scroll.getViewport().getViewRect().x;
for (int column = 0; column < table.getColumnCount(); column++)
{
TableCellRenderer cellRenderer = table.getCellRenderer(0, column);
cellRendererComponent = cellRenderer.getTableCellRendererComponent(table, getFooterValueAt(column), false, false, 0, column);
if (oldColor == null)
{
oldColor = cellRendererComponent.getBackground();
}
int columnWidth = table.getColumnModel().getColumn(column).getWidth();
cellRendererComponent.setBackground(COLORS[column % COLORS.length]);
cellRendererPane.paintComponent(g, cellRendererComponent, scroll, columnWidths, y, columnWidth, height);
columnWidths += columnWidth;
}
if (cellRendererComponent != null)
{
cellRendererComponent.setBackground(oldColor);
}
}

private Object getFooterValueAt(int viewColumn)
{
return "Column " + viewColumn;
}

@Override
public Insets getBorderInsets(Component c)
{
return new Insets(0, 0, table.getRowHeight(), 0);
}

@Override
public boolean isBorderOpaque()
{
return true;
}
}

/**
* Repaints JScrollPane when needed.
*/
private static class RepaintListener implements ChangeListener, AdjustmentListener, TableColumnModelListener
{
private final JScrollPane scroll;

RepaintListener(JScrollPane scroll)
{
this.scroll = scroll;
}

@Override
public void columnAdded(TableColumnModelEvent e)
{
repaint();
}

@Override
public void columnRemoved(TableColumnModelEvent e)
{
repaint();
}

@Override
public void columnMoved(TableColumnModelEvent e)
{
repaint();
}

@Override
public void columnMarginChanged(ChangeEvent e)
{
repaint();
}

@Override
public void columnSelectionChanged(ListSelectionEvent e)
{
repaint();
}

@Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
repaint();
}

@Override
public void stateChanged(ChangeEvent e)
{
repaint();
}

private void repaint()
{
scroll.repaint();
}
}
}

最佳答案

问题是 rendererPane 的位置:您的代码中发生的是标签位于 x/y,即靠近具有视口(viewport)矩形完整高度的上边界线,然后文本被绘制在某处视口(viewport)的中间,后来被视口(viewport)覆盖。要查看效果,请使用零行 tableModel 并使视口(viewport)不透明。

相反,您必须将它定位在边框的底部。一个非常脏(没有做任何事情来使其像素正确,在周末运行时:) 片段

        g.setColor(Color.RED);
int scrollBottom = scroll.getInsets().bottom;
int lowerBorderTop = height - scrollBottom;
g.drawLine(x, height - scrollBottom - 1, width - 10, height - scrollBottom - 1);
g.drawRect(x + 1, height - scrollBottom, width - 10, 10);
Color oldColor = null;
Component cellRendererComponent = null;
int columnWidths = x ;//- scroll.getViewport().getViewRect().x;
for (int column = 0; column < table.getColumnCount(); column++)
{
TableCellRenderer cellRenderer = table.getCellRenderer(0, column);
cellRendererComponent = cellRenderer.getTableCellRendererComponent(table,
getFooterValueAt(column), false, false, 0, column);
if (oldColor == null)
{
oldColor = cellRendererComponent.getBackground();
}
int columnWidth = table.getColumnModel().getColumn(column).getWidth();
cellRendererComponent.setForeground(Color.BLACK);
cellRendererComponent.setBackground(COLORS[column % COLORS.length]);
cellRendererPane.paintComponent(g, cellRendererComponent, scroll, columnWidths,
lowerBorderTop , columnWidth, table.getRowHeight(), false);
columnWidths += columnWidth;
}
if (cellRendererComponent != null)
{
cellRendererComponent.setBackground(oldColor);
}

额外的线和矩形只是为了看看我们在哪里。顺便说一句,不错的方法:-)

关于java - JTable 的页脚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9131355/

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