我有一个JScrollPane
,其列标题由多个组件组成。其中一个组件需要静态定位,而其他组件需要像平常一样滚动。
我唯一想到的就是在滚动条上添加一个监听器,它设置冻结组件的位置,如下所示:
frozenHeader.setLocation(scrollViewport.getVisibleRect().getLocation()).
但是,在滚动条不长滚动之前,该位置实际上不会更新,因此它看起来相当不吸引人。是的,我尝试在revalidate()
及其父级repaint()
上调用frozenHeader
后跟import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/**
*
* @author brian
*/
public class TestScroll extends JFrame {
private JScrollPane scrollPane;
private JPanel viewport;
private JPanel colHeader;
// This should be frozen
private JPanel frozenHeader;
// This should scroll
private JPanel scrollHeader;
public TestScroll() {
this.setSize(new Dimension(500, 400));
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Set up the scroll pane
scrollPane = new JScrollPane();
viewport = new JPanel();
viewport.setPreferredSize(new Dimension(1000, 400));
scrollPane.setViewportView(viewport);
// Set up the scroll panes column header
colHeader = new JPanel(new GridBagLayout());
frozenHeader = new JPanel();
// Width is equal to the frame's width, as it should stay in the same location
frozenHeader.setPreferredSize(new Dimension(500, 30));
frozenHeader.setBackground(Color.RED);
scrollHeader = new JPanel();
// Width equal to viewportview's as it should scroll
scrollHeader.setPreferredSize(new Dimension(1000, 30));
scrollHeader.setBackground(Color.BLUE);
JLabel label = new JLabel("Text");
scrollHeader.add(label);
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.WEST;
c.gridx = 0;
c.gridy = 0;
colHeader.add(frozenHeader, c);
c.gridy = 1;
colHeader.add(scrollHeader, c);
scrollPane.setColumnHeaderView(colHeader);
add(scrollPane);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TestScroll().setVisible(true);
}
});
}
}
。
以下是重现我所说的内容的示例:
frozenHeader
我希望scrollHeader
(红色面板)始终在屏幕中居中而不是滚动屏幕,scrollHeader
(蓝色面板)继续滚动,就像在示例中一样
要添加更多上下文,我之所以不是简单地将frozenHeader
放在视口中,或将JScrollPane
移出列标题而只是将其放在JScrollPane
上方是因为我的实际应用程序中的{{1}}有一个左上角面板,它与列标题的高度相同。由于应用程序的性质,我需要利用所有的屏幕空间。
非常感谢有关如何实现这一目标的任何建议!
答案 0 :(得分:1)
“我希望红色面板始终位于屏幕中央,而不是滚动屏幕。”
问题是您正在设置columnHeaderView
。这可以轻松完成,但只需将colHeader
面板添加为独立实体,不设置columnHeaderView
colHeader = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
colHeader.add(frozenHeader);
JPanel panelForScrollPaneAndScrollHeader = new JPanel(new BorderLayout());
panelForScrollPaneAndScrollHeader.add(scrollHeader, BorderLayout.NORTH);
panelForScrollPaneAndScrollHeader.add(scrollPane, BorderLayout.CENTER);
add(colHeader, BorderLayout.NORTH);
add(panelForScrollPaneAndScrollHeader, BorderLayout.CENTER);
执行此操作时的结果
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class TestScroll1 extends JFrame{
private JScrollPane scrollPane;
private JPanel viewport;
private JPanel colHeader;
private JPanel frozenHeader;
private JPanel scrollHeader;
public TestScroll1() {
frozenHeader = new JPanel();
frozenHeader.setPreferredSize(new Dimension(500, 30));
frozenHeader.setBackground(Color.RED);
scrollHeader = new JPanel();
scrollHeader.setPreferredSize(new Dimension(1000, 30));
scrollHeader.setBackground(Color.BLUE);
scrollPane = new JScrollPane();
viewport = new JPanel();
viewport.setPreferredSize(new Dimension(1000, 400));
scrollPane.setViewportView(viewport);
colHeader = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
colHeader.add(frozenHeader);
JPanel panelForScrollPaneAndScrollHeader = new JPanel(new BorderLayout());
panelForScrollPaneAndScrollHeader.add(scrollHeader, BorderLayout.NORTH);
panelForScrollPaneAndScrollHeader.add(scrollPane, BorderLayout.CENTER);
add(colHeader, BorderLayout.NORTH);
add(panelForScrollPaneAndScrollHeader, BorderLayout.CENTER);
setSize(new Dimension(500, 400));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new TestScroll1().setVisible(true);
}
});
}
}