当用户滚动时,具有自定义布局的Jtable会闪烁

时间:2014-05-05 19:38:20

标签: java swing layout jtable flicker

我已经完成了一个扩展JTable的自定义表。我的自定义表格在布局上有所不同,它有一个JPanel,表格底部有一个按钮。 无论滚动位置如何,面板应始终位于表格可见部分的底部。

它几乎可以按照我想要的方式工作,除了当我滚动表格时它会闪烁某些行位于面板后面

是否有可能在某些方面使代码变得更好,摆脱闪烁并使其成为面板后面没有行?

以下是我的自定义表格的一个工作示例:

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;

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

    public TableDemo() {
        JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());
        CustomTable table = new CustomTable();
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setViewportView(table);
        table.initChangeListener();
        frame.add(scrollPane);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    class CustomTable extends JTable {
        private TableLayout layout = new TableLayout();
        public CustomTable() {
            super(100,10);
            JPanel panel = new JPanel();
            panel.setLayout(new FlowLayout(FlowLayout.CENTER));
            panel.setBackground(Color.lightGray);
            panel.add(new JButton("Press me!"));
            this.add(panel);
            this.setLayout(layout);
        }

        public void initChangeListener() {
            if(this.getParent() != null) {
                if(this.getParent() instanceof JViewport) {
                    JViewport viewport = (JViewport)this.getParent();
                    viewport.addChangeListener(new ChangeListener() {
                        @Override
                        public void stateChanged(ChangeEvent e) {
                            if(CustomTable.this.getLayout() instanceof TableLayout) {
                                CustomTable.this.getLayout().layoutContainer(CustomTable.this);
                            }
                        }
                    });
                }
            }
        }
    }

    class TableLayout implements LayoutManager {

        @Override
        public void addLayoutComponent(String name, Component comp) {}

        @Override
        public void removeLayoutComponent(Component comp) {}

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            return parent.getPreferredSize();
        }

        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return parent.getMinimumSize();
        }


        @Override
        public void layoutContainer(Container parent) {
            CustomTable table = (CustomTable)parent;
            JViewport vp = (JViewport)table.getParent();
            Point p = vp.getViewPosition();
            Rectangle rectangle = vp.getVisibleRect();

            for(Component c : parent.getComponents()) {
                if(c instanceof JPanel) {
                    c.setBounds(0,  p.y + (int)rectangle.getHeight() - 40, (int)rectangle.getWidth(), (int)rectangle.getHeight());
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

为什么使用自定义布局?它有什么特殊的用途吗?如果不是,我认为我有另一种建议

您可以通过扩展JPanel(或JComponent)而不是扩展JTable来创建新组件,并且可以将带有滚动窗格和Button面板的JTable添加到该容器。请参阅下面的代码。

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

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

public TableDemo() {
    JFrame frame = new JFrame();
    frame.setLayout(new BorderLayout());
    CustomTable table = new CustomTable();
    frame.add(table);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
}


class CustomTable extends JPanel
{

    JTable table;
    JPanel buttonPanel;

    public CustomTable() {
        super();
        setLayout(new BorderLayout());
        table=new JTable(100,10);
        JScrollPane scrollPane=new JScrollPane(table);
        buttonPanel=new JPanel();
        buttonPanel.add(new JButton("Press Me"));

        add(scrollPane, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);
    }
}
}