JTable在点击时选择了错误的单元格

时间:2009-06-04 17:55:13

标签: java swing scroll jtable

我在一个非常复杂的基于eclipse的应用程序中工作,并且在JSplitPane内部遇到基于JTable的自定义组件的问题。我实际可以访问的应用程序部分是一个面板,一个选项卡内,一个面板内,实际应用程序内部,因此有很多东西可能出错。

我现在遇到的具体问题是,当我点击它时,表组件选择了错误的单元格。如果我在第0行第0列中选择一个单元格,则实际获取的单元格位于第2行第0列,即实际点击下方约20个像素。只有当表位于JSplitPane中时才会发生这种情况:如果我只是将表本身添加到面板中,则单元格选择是正确的。

对我来说似乎是因为该表位于JSplitPane中,表格的边界(或者包含表格的滚动窗格的视口?)在某处偏离了大约20个像素。我可以支持这个理论的另一个问题是,滚动表会导致重新绘制在表格之上:例如,当我向下滚动而不是表格滚动时,它实际上向上移动(绘制在表格上方的组件上) )滚动前大约20个像素。我能够通过添加

来解决这个问题
jscrollpane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);

到包含该表的滚动窗格。

由于所涉及的所有自定义组件,我实际上无法获得显示问题的小应用程序,但我有下一个最好的东西,这是一个显示我的布局的应用程序(当然,它没有实际上有同样的问题)。关于可能导致问题的任何想法?

//Test class showing layout of table/splitpane
import javax.swing.*;
import java.awt.*;

public class SplitTest
{
    private static JFrame frame;

    private static JPanel buildTable()
    {
        JPanel tblPanel = new JPanel();
        tblPanel.setLayout(new BorderLayout());

        String[] cols = new String[]{"one", "two", "three", "four", "five", "six", "seven"};
        Object[][] data = new Object[30][7];
        for(int x = 0;x < data.length;x++)
            for(int y = 0;y < data[x].length;y++)
                data[x][y] = x + ", " + y;

        JTable tbl = new JTable(data, cols);

        JScrollPane scrollPane = new JScrollPane(tbl);
        tblPanel.add(scrollPane, BorderLayout.CENTER);

        return tblPanel;
    }

    private static JPanel buildTab()
    {
        JPanel pnl = new JPanel();
        pnl.setLayout(new BorderLayout());

        JPanel menuPnl = new JPanel();
        menuPnl.setLayout(new FlowLayout(FlowLayout.LEFT));
        menuPnl.add(new JLabel("label"));
        menuPnl.add(new JComboBox(new String[]{"one", "two"}));
        menuPnl.add(new JButton("Button"));
        pnl.add(menuPnl, BorderLayout.NORTH);

        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        splitPane.setLeftComponent(buildTable());
        JPanel bottomPnl = new JPanel();
        bottomPnl.setPreferredSize(new Dimension(800, 200));
        bottomPnl.setBackground(Color.RED);
        splitPane.setRightComponent(bottomPnl);
        splitPane.setDividerLocation(.5);
        pnl.add(splitPane, BorderLayout.CENTER);

        return pnl;
    }

    private static JTabbedPane buildGUI()
    {
        JTabbedPane topLevelTabbedFrame = new JTabbedPane();
        topLevelTabbedFrame.addTab("Tab 1", buildTab());
        topLevelTabbedFrame.addTab("Tab 2", new JPanel());
        topLevelTabbedFrame.addTab("Tab 3", new JPanel());

        return topLevelTabbedFrame;
    }

    private static void createAndShowGUI()
    {
        frame = new JFrame("Split Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().add(buildGUI(), BorderLayout.CENTER);
//        frame.setSize(new Dimension(800, 600));

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) throws Exception
    {
        SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        createAndShowGUI();
                    }
        });
    }
}

3 个答案:

答案 0 :(得分:0)

  

由于所涉及的所有自定义组件,我实际上无法获得显示问题的小应用程序,但我有下一个最好的东西,这是一个显示我所拥有的布局的应用程序(当然,它实际上没有相同的问题。)

我正要告诉你发布的代码工作正常,我读了这篇文章。

无论如何,问题似乎在于你添加到混音中的所有自定义组件。对于JTable和JSplitPane单独工作很好。

我要做的是逐个删除组件直到它工作(可能我会在代码类似于发布的代码时工作,而且没有别的东西)

或者你可以采取相反的方式,这更容易。从示例代码开始,然后添加越来越多的组件,直到它失败。

您可以借此机会重构和清理代码并移动不需要的组件。甚至(为什么不)在过程中添加测试用例。

祝你好运。

答案 1 :(得分:0)

您是否尝试过在另一个盒子上打开它以检查其硬件是否相关。

可能与此错误有关

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4763448

答案 2 :(得分:0)

事实证明,问题在于组件已初始化并添加到拆分窗格的顺序。因此,最终修复是延迟将表添加到拆分窗格,直到拆分窗格实际添加到面板之后,而不是在将拆分窗格添加到面板之前将表添加到拆分窗格。做出这个小小的改变解决了这个问题。