首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JScrollPane滚动条直到调用rowSorter.toggleSortOrder()之后才会出现

JScrollPane滚动条直到调用rowSorter.toggleSortOrder()之后才会出现
EN

Stack Overflow用户
提问于 2014-07-24 17:58:38
回答 1查看 588关注 0票数 0

我注意到,当我有一个带有由JTable包含的TableRowSorter的JScrollPane时,垂直滚动条直到我为分类器创建了SortKeys之后才会出现(这是通过为其中一个列调用toggleSortOrder()来完成的)。

我的问题是为什么?SortKeys与垂直滚动条有什么关系?

Update:添加了SSCCE,它打开一个JFrame,在JScrollPane中有一个JTable,它位于容器中,还有一个“填充”按钮。在最初绘制表时,不存在数据,因此不需要滚动条。在我用20行填充它之后,需要一个滚动条,但是没有出现。

有两种方法可以使滚动条出现:

  • 单击任何一个标头单元格都可以导致排序。
  • 删除容器的refresh()方法中的注释调用toggleSortOrder()。 // table.getRowSorter().toggleSortOrder(0);

toggleSortOrder()调用setSortKeys()调用sort()调用fireRowSorterChanged(),最终有东西捕获事件并添加滚动条。

代码语言:javascript
复制
package test;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;

@SuppressWarnings("serial")
public class TestFrame extends JFrame
{
    class MyTableModel extends AbstractTableModel
    {
        public List<String> names = new ArrayList<String>();

        public int getRowCount ()
        {
            return names.size();
        }

        public int getColumnCount ()
        {
            return 2;
        }

        public String getColumnName (int columnIndex)
        {
            return columnIndex > 0 ? "Name" : "Number";
        }

        public Class<?> getColumnClass (int columnIndex)
        {
            return String.class;
        }

        public Object getValueAt (int row, int col)
        {

            return row < names.size() ? col == 0 ? Integer.toString(row) : names.get(row) : "";
        }

        public void refresh (List<String> names)
        {
            this.names = names;
        }
    }

    class MyContainer extends java.awt.Container implements ActionListener
    {
        JTable                               table;
        MyTableModel                         model = new MyTableModel();
        private TableRowSorter<MyTableModel> sorter;

        public MyContainer()
        {
        }

        public void init ()
        {
            sorter = new TableRowSorter<MyTableModel>(model);
            table = new JTable(model);
            table.setBorder(BorderFactory.createEmptyBorder());
            table.setRowHeight(35);
            table.getTableHeader().setPreferredSize(new Dimension(200, 35));
            table.setRowSorter(sorter);
            table.setPreferredScrollableViewportSize(new Dimension(200, 70));
            table.setFillsViewportHeight(true);
            table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            //Create the scroll pane and add the table to it.
            JScrollPane scrollPane = new JScrollPane(table);
            scrollPane.setBounds(10, 10, 200, 210);

            //Add the scroll pane to this panel.
            add(scrollPane);
            JButton btn = new JButton("Populate");
            btn.setActionCommand("populate");
            btn.addActionListener(this);
            btn.setBounds(10, 220, 200, 35);
            add(btn);
        }

        public void refresh (List<String> rows)
        {
            model.refresh(rows);
            try
            {
                // Notify sorter that model data (possibly number of rows) has changed.
                // Without this call, the sorter assumes the number of rows is the same.
                table.getRowSorter().allRowsChanged();
                // Do we really want to toggle the sort order every time we refresh?
                // User can toggle the sort order himself by clicking on the 
                // appropriate header cell.
                List<?> keys = table.getRowSorter().getSortKeys();
                if (null == keys || keys.isEmpty())
                {
//                    table.getRowSorter().toggleSortOrder(0);
                }
            } catch (Exception e)
            {
                e.printStackTrace();
            }
            table.repaint();
        }

        public void actionPerformed(ActionEvent e)
        {
            if ("populate".equals(e.getActionCommand()))
            {
                List<String> rows = new ArrayList<String>();
                for (int ii = 0; ii < 20; ii++)
                {
                    rows.add(String.format("%02d", new Integer(ii)));
                }
                refresh(rows);
            }
        }

        MyTableModel getModel ()
        {
            return model;
        }
    }

    public static void main (String args[])
    {
        new TestFrame();
    }

    MyContainer myContainer = new MyContainer();

    TestFrame() 
    {
        myContainer.init();
        myContainer.table.getSelectionModel().clearSelection();
        add(myContainer);
        this.setSize(240, 310);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //pack();
        setVisible(true);
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-25 00:34:08

嗯,这实际上不是SSCCE,因为您使用的是自定义TableModel。如果您已经创建了一个适当的SSCCE,您将使用DefaultTableModel,以便使用标准的JDK类测试您的代码。如果您这样做,那么您就会注意到代码会正常工作。

因此,接下来的步骤是使用自定义TableModel尝试代码,您会注意到代码不起作用。

那么,您在论坛上的问题是,为什么代码不适用于我的自定义TableModel?SSCCE的目的是进行基本的调试,以隔离错误发生的位置,因此我们可以使用信息。在您最初的问题中,我们不知道您在哪里使用自定义类。

无论如何,问题是当对数据进行更改时,您的自定义TableModel不会通知表。在refresh(...)方法中,需要在重置包含数据的列表后添加以下内容:

代码语言:javascript
复制
  fireTableRowsInserted(0, names.size()-1);

在任何代码中都不需要table.repaint()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24940806

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档