我的情况有点复杂,所以不要解释我只是展示我目前所拥有的图片:
我的想法是,我想在工作人员上方移动乐器选择器(在每个工作人员中说"长笛"的组合框)。但是,我总是希望将它保持在工作人员正上方的同一个地方,即使在水平滚动时也是如此。当垂直滚动时,它应该移动,以便它总是直接在其工作人员上方。有点像工具栏。问题是它已经存在于JScrollPane中(因为可能有多个五线谱,你需要滚动两个轴,并且每个工作人员都有一个"仪表板;将是其他UI元素在本地伪工具栏中与其附加的工作人员进行交互))。这是否需要使用绝对定位+监听滚动/调整大小/窗口移动事件?或者是否有一个我不知道可以做这种事情的布局?
感谢您的期待!
答案 0 :(得分:2)
我通过以下方法进行了一些工作:
AdjusmentListener
以更新组合框的坐标X. 换句话说,组合框在其空布局面板中滑动以匹配您正在查看的位置。它并不完美,因为当你移动scrollBar时,这会导致组合框稍微摆动。
我看起来像你的模拟界面如下:
请注意屏幕截图中的水平条是如何移动的,但组合框中的"长笛"仍然可见。
所以最重要的代码是:
将comboBox放在空布局面板中:
JComboBox comboBox = new JComboBox(new String[]{"Flute", "Piano", "Cello"});
comboBox.setBounds(0, 0, comboBox.getPreferredSize().width, comboBox.getPreferredSize().height);
_comboBoxes.add(comboBox);
JPanel comboBoxPanel = new JPanel();
comboBoxPanel.setLayout(null);
comboBoxPanel.add(comboBox);
然后,您将此面板放在工作人员上,无论您使用何种布局。在我的情况下,我有一个带有垂直Box布局的面板,其中包含comboBoxPanel和工作人员所在的红色面板。
将一个监听器添加到滚动条并更新其面板中的组合框位置:
scrollPane.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
for (JComboBox comboBox : _comboBoxes)
{
comboBox.setLocation(e.getValue(), 0);
}
}
});
完整代码:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class ScrollIndependentTest
{
private ArrayList<JComboBox> _comboBoxes = new ArrayList<JComboBox>();
public static final void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
new ScrollIndependentTest().createAndShowGUI();
}
});
}
public void createAndShowGUI()
{
JFrame frame = new JFrame();
frame.setTitle("Fourier Synthesis");
JPanel listPanel = new JPanel();
listPanel.setLayout(new BoxLayout(listPanel, BoxLayout.Y_AXIS));
for (int i = 0; i < 10; ++i)
{
listPanel.add(createStaffPanel());
}
JScrollPane scrollPane = new JScrollPane(listPanel);
scrollPane.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener()
{
@Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
for(JComboBox comboBox : _comboBoxes)
{
//if (comboBox.isVisible()) //maybe?
comboBox.setLocation(e.getValue(), 0);
}
}
});
frame.add(scrollPane);
/*
* Cosmetic elements to make it look more similar to your case
*/
JMenuBar menuBar = new JMenuBar();
menuBar.add(new JMenu("File"));
menuBar.add(new JMenu("Synthesis"));
menuBar.add(new JMenu("Help"));
frame.setJMenuBar(menuBar);
JPanel toolBar = new JPanel();
toolBar.setLayout(new BoxLayout(toolBar, BoxLayout.Y_AXIS));
for (int i = 0; i < 10; ++i)
{
toolBar.add(new JButton("Note " + i));
}
frame.add(toolBar, BorderLayout.WEST);
/*
* end
*/
frame.setSize(new Dimension(500, 400));
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createStaffPanel()
{
JPanel staffPanel = new JPanel();
staffPanel.setLayout(new BoxLayout(staffPanel, BoxLayout.Y_AXIS));
staffPanel.setBorder(BorderFactory.createLineBorder(Color.black));
JComboBox comboBox = new JComboBox(new String[]{"Flute", "Piano", "Cello"});
comboBox.setBounds(0, 0, comboBox.getPreferredSize().width, comboBox.getPreferredSize().height);
_comboBoxes.add(comboBox);
JPanel comboBoxPanel = new JPanel();
comboBoxPanel.setLayout(null);
comboBoxPanel.add(comboBox);
comboBoxPanel.setPreferredSize(new Dimension(600, comboBox.getPreferredSize().height));
staffPanel.add(comboBoxPanel);
JPanel panel = new JPanel();
panel.setBackground(Color.red);
panel.setPreferredSize(new Dimension(600, 100));
panel.setAlignmentX(Component.LEFT_ALIGNMENT);
staffPanel.add(panel);
return staffPanel;
}
}
答案 1 :(得分:2)
类似的东西:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class ScrollSSCCE extends JPanel
{
public ScrollSSCCE()
{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
BoundedRangeModel model = null;
for (int i = 0; i < 5; i++)
{
JLabel label = new JLabel("Flute " + i);
label.setAlignmentX(JComponent.LEFT_ALIGNMENT);
add( label );
JTextArea textArea = new JTextArea(3, 20);
textArea.setText("Just some text to make a horizontal scroll necessary");
JScrollPane scrollPane = new JScrollPane( textArea );
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setAlignmentX(JComponent.LEFT_ALIGNMENT);
add( scrollPane );
// Share the horizontal scrollbar model
JScrollBar horizontal = scrollPane.getHorizontalScrollBar();
if (i == 0)
model = horizontal.getModel();
else
horizontal.setModel( model );
}
// Create the scrollbar that uses the shared model
JScrollBar shared = new JScrollBar( JScrollBar.HORIZONTAL );
shared.setModel( model );
shared.setAlignmentX(JComponent.LEFT_ALIGNMENT);
add( shared );
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Scroll SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new ScrollSSCCE() );
frame.setLocationByPlatform( true );
frame.setSize(200, 400);
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
编辑:
您甚至无需创建“共享”滚动条即可实现此目的。只需使用最后一个滚动窗格的滚动条:
if (i != 4)
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
我也需要一个垂直滚动条。
不要以为你需要创建另一个面板。只需将当前面板直接添加到滚动窗格:
JScrollPane master = new JScrollPane( new ScrollSSCCE() );
master.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
JFrame frame = new JFrame("Scroll SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.add( new ScrollSSCCE() );
frame.add( master );
frame.setLocationByPlatform( true );
frame.setSize(200, 400);
frame.setVisible( true );
这是我的最后一个提示。我不会在附近呆几天。祝你好运。