JTable 的页脚

2024-02-16

JTable 不支持显示包含每列聚合数据的页脚。受到建议解决方案的启发Oracle/Suns 错误数据库 https://bugs.java.com/bugdatabase/view_bug?bug_id=4242646看起来很有希望,我从用滚动窗格的边框绘制页脚的方法开始。

现在,一开始我只想要一个“概念证明”,看起来我已经快到了,每列都有一个页脚,宽度是同步的。等等。所以它似乎工作得很好,除了一件事,没有绘制文字!我期望从返回的虚拟值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 处,即靠近上边界线,具有视口矩形的完整高度,然后文本被绘制在中间的某个位置视口,然后被视口覆​​盖。要看到这种效果,请使用零行 tableModel 并使视口不透明。

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JTable 的页脚 的相关文章

随机推荐

  • 在 javascript 中解构嵌套对象 |解构第二级父对象和子对象

    我需要从该对象中解构并获取 title child childTitle 的值 const obj1 title foo child title2 bar let title child obj1 console log title foo
  • 如果 jstat 已被弃用,我应该使用什么来代替?

    突然我发现jstat 已弃用 http docs oracle com javase 1 5 0 docs tooldocs share jstat html jstat 工具显示已检测的性能统计信息 HotSpot Java 虚拟机 JV
  • Haproxy 性能调整?

    我们正在尝试为来自客户端 而不是浏览网络交易类型的用户 的 get 和 post 请求找到 haproxy 的最佳调整选项 使用 30k 线程运行 jmeter 测试 其中包括 5 个对服务器的调用 1 个用户注册和一些更新调用 这些通过管
  • 使用awk解析

    如何使用 awk 根据另一个文件的数据解析文件 我做了一个脚本 BEGIN FS t OFS t while getline lt headfpkm gt 0 a id a 1 fpkm a 2 print id a fpkm a last
  • Sass::SyntaxError:未定义的 mixin 'mixin_name'

    我正在开发一个 Rails 4 项目 其中使用 Sass 和 Sass 的 import 将多个 css 合并为一个 它工作正常 但如果我使用新的混入部分则不行 mixins css scss 和 import这个main css scss
  • 如何以编程方式获取 SVN 修订号?

    喜欢这个问题 https stackoverflow com questions 681770 how to programmatically get svn revision description and author in c 但不需
  • 当 transactionManager 未命名为“transactionManager”时

    我正在尝试 Spring 3 0 2 RELEASE 和 JPA2 和 Hibernate 3 5 1 Final 令我不安的一件事是 spring 似乎只接受名为 transactionManager 的事务管理器 如果我不将其命名为 t
  • 如何在 MacOS X 上以编程方式打开控制台窗口

    我想知道 是否可以在 MacOS X 上以编程方式打开控制台窗口并将 IO 重定向到它 类似于AllocConsole GetStdHandle Windows 上的 API 我打算在 xxx app 应用程序中使用它 该应用程序默认情况下
  • gdb在检查内存时如何同时显示hex和ascii?

    使用 x 100c 时 输出显示 ascii 和十进制 0x111111 40 40 gdb如何同时显示ascii和hex like 0x111111 0x28 C 0x28 C 这种格式更好 0x111111 0x28 0x28 CC 您
  • WooCommerce 可变产品通知问题 - 请选择产品选项

    我正在建立一个电子商务网站 我在使用 WooCommerce 时遇到一些问题可变产品 添加到购物车 按钮适用于简单产品 但不适用于可变产品 它给出了一个 Please choose product options notice 我到处寻找并
  • 如何在.NET中为SmtpClient对象设置用户名和密码?

    我看到不同版本的构造函数 一种使用 web config 中的信息 一种指定主机 一种指定主机和端口 但是如何将用户名和密码设置为与 web config 不同的内容呢 我们遇到的问题是我们的内部 smtp 被一些高安全性客户端阻止 并且我
  • 电子标题栏“无拖动”和“拖动”不起作用

    我有一个 topleft红色标题栏包含多个 选项卡 按钮 应填充所有可用空间except a topright蓝色块 可以通过单击并拖动来移动 Electron 主窗口 topleft的红色背景 感谢 webkit app region d
  • 如何在集群外部访问/公开 kubernetes-dashboard 服务?

    我有以下服务 ubuntu master kubectl get services all namespaces NAMESPACE NAME CLUSTER IP EXTERNAL IP PORT S AGE default kubern
  • 堆上数组的初始化

    如何手动初始化堆上数组中的值 如果数组是局部变量 在堆栈中 则可以以非常优雅且简单的方式完成 如下所示 int myArray 3 1 2 3 不幸的是 下面的代码 int myArray new int 3 myArray 1 2 3 编
  • 如何注入模拟程序集以与 Moq 一起使用

    我的控制器中有一个方法 它将属性数据从当前执行的程序集返回到分部视图中 在这个例子中 我只是拉动标题 但我需要用它做更多的事情 控制器 var title var asm Assembly GetExecutingAssembly var
  • jQuery - 通过文本描述设置选择控件的选定值

    我有一个选择控件 在 JavaScript 变量中我有一个文本字符串 使用 jQuery 我想将选择控件的选定元素设置为具有我拥有的文本描述的项目 而不是我没有的值 我知道按值设置它非常简单 例如 my select val myVal 但
  • 获取那些有子子 ul 的 li

    如何获得那些li有孩子的ul 我想将 CSS 设置为那些li 我无法设置班级 因为li是动态打印的 当我如下设置 CSS 时 它设置了所有父级li来加 ul width 200px position relative ul li posit
  • 贝塞尔曲线和画布

    如何在画布上绘制贝塞尔曲线 我只有起点和终点 我想从起点到终点画一条线 我怎样才能做到这一点 您可以使用Path quadTo or Path cubicTo 为了那个原因 示例可以在 SDK 示例 FingerPaint 中找到 在你的情
  • backbone.js 解析 1 个元素(Id)

    对于骨干模型上的 id 来说 它只是id并且全部小写 如果我在服务器上的Id被调用怎么办UserId 在主干的解析方法中 我该如何更改UserId to id并对所有其他属性使用相同的名称 For eg window User Backbo
  • JTable 的页脚

    JTable 不支持显示包含每列聚合数据的页脚 受到建议解决方案的启发Oracle Suns 错误数据库 https bugs java com bugdatabase view bug bug id 4242646看起来很有希望 我从用滚