Java 如何将JComponent添加到框的某个索引中
在我的软件中,我有一个滚动窗格,它的视图有一个方框布局,并保存JPanel。 一个按钮允许将JPanel添加到该框中,我想找到一种方法将其放置在某个位置 以下是一个屏幕截图: 下面是示例代码:Java 如何将JComponent添加到框的某个索引中,java,swing,layout,Java,Swing,Layout,在我的软件中,我有一个滚动窗格,它的视图有一个方框布局,并保存JPanel。 一个按钮允许将JPanel添加到该框中,我想找到一种方法将其放置在某个位置 以下是一个屏幕截图: 下面是示例代码: public class MyClass { //run a swing App public static void main(String[] args) throws IOException { SwingUtilities.invokeLater(new S
public class MyClass {
//run a swing App
public static void main(String[] args) throws IOException {
SwingUtilities.invokeLater(new ScrollPaneExample());
}
}
class ScrollPaneExample implements Runnable{
private Box boxHolder;
private JPanel scrollPaneContainer;
//show a JFrame
@Override
public void run(){
JFrame mainFrame = initFrame();
mainFrame.setPreferredSize(new Dimension(300, 200));
mainFrame.setLocationRelativeTo(null);
mainFrame.pack();
mainFrame.setVisible(true);
}
//init JFrame and add to it a scrollpane and a button
private JFrame initFrame() {
JFrame mainFrame = new JFrame("MyFrame");
mainFrame.setLayout(new BorderLayout());
mainFrame.getContentPane().add(initScrollPane(),BorderLayout.CENTER);
mainFrame.getContentPane().add(initButtonAdd(),BorderLayout.SOUTH);
return mainFrame;
}
//init scrollpane which contains a boxholder for colored panels
private Component initScrollPane() {
scrollPaneContainer = new JPanel( new BorderLayout() );
boxHolder = Box.createVerticalBox();
scrollPaneContainer.add(boxHolder, BorderLayout.PAGE_START);
return new JScrollPane(scrollPaneContainer);
}
//init a button which add a panel to the boxholder on pressed
private Component initButtonAdd() {
JButton button = new JButton("addPanel");
button.setBackground(Color.green);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
boxHolder.add(createPanel());
scrollPaneContainer.revalidate();
}
});
return button;
}
//create a panel setting its background to a random color
private Component createPanel() {
JPanel panel = new JPanel();
panel.setBackground(randomColor());
panel.setPreferredSize(new Dimension(100,50));
panel.addMouseListener(new MouseListener() {
public void mousePressed(MouseEvent e) {
/** TODO code to replace the clicked panel with a new one*/
}
@Override public void mouseClicked(MouseEvent e) {}
@Override public void mouseReleased(MouseEvent e) {}
@Override public void mouseEntered(MouseEvent e) {}
@Override public void mouseExited(MouseEvent e) {}
});
panel.add(new JLabel("a colored Panel"));
return panel;
}
//generate a randomColor
private Color randomColor() {
Random rand = new Random();
float r = rand.nextFloat() / 2f ;
float g = rand./***/nextFloat() / 2f;
float b = rand.nextFloat() / 2f;
Color randomColor = new Color(r, g, b);
return randomColor;
}
}
我想做一些类似的事情:
int indexPosition = 2;
boxHolder.add(createPanel(), indexPosition);
JPanel replacePanel = createPanel();
// next istruction leads to a compilation error since Box do not has this method
int indexOfClickedPanel= boxHolder.indexOf(this);
boxHolder.add(replacePanel,indexOfClickedPanel);
更新1-2
首先:谢谢。
我注意到提供的示例代码没有正确反映我的代码,在解释我的问题时,我失去了目标。
我将保留前一个问题,因为它对其他人有用。
让我们继续
我需要替换一个特定的面板,所以,我们以前用给定的索引所做的,应该用一些更动态的东西来实现。
我在JPanel上加了一个鼠标听器。单击后,应将其替换为新面板。比如:
int indexPosition = 2;
boxHolder.add(createPanel(), indexPosition);
JPanel replacePanel = createPanel();
// next istruction leads to a compilation error since Box do not has this method
int indexOfClickedPanel= boxHolder.indexOf(this);
boxHolder.add(replacePanel,indexOfClickedPanel);
在我的代码中,我使用JLabel而不是按钮。其图标在鼠标进入/退出时更改,并在按下时添加特定面板。对我来说,这听起来更合适,任何建议都将不胜感激。在这个回答中,我为您的听众添加了额外的代码,但如果您需要更改,可以很容易地更改 如果您想在该位置添加另一个面板,可以使用任何索引位置
public void mouseClicked(MouseEvent e) {
boxHolder.add(createPanel());
int indexPosition = 2;
try //Will only add here if you have a component in index position 1
{
boxHolder.add(createPanel(),indexPosition);
}
catch(Exception ex){}
scrollPaneContainer.revalidate();
}
这将在索引位置2添加一个面板,并将索引位置2的当前面板移动到索引位置3
如果要替换索引位置2的当前面板,可以使用
public void mouseClicked(MouseEvent e) {
boxHolder.add(createPanel());
int indexPosition = 2;
try //Will only remove it if there is already a panel or other component there
{
boxHolder.remove(indexPosition);
}
catch(Exception ex){}
try //Will only add here if you have a component in index position 1
{
boxHolder.add(createPanel(),indexPosition);
}
catch(Exception ex){}
scrollPaneContainer.revalidate();
}
这将移除当前处于索引位置2的面板,并在其位置添加另一个面板
但是,如果尝试将组件添加到索引位置2,而索引位置0或1中没有任何组件,则会出现异常java.lang.IllegalArgumentException:非法组件位置
。因此,这就是为什么添加一个面板的代码位于try catch
块中,在该面板中,int变量的索引位置为indexPosition
。这与删除方法的原因相同
编辑
如前所述,如果您使用操作侦听器会更好,因此在您的代码中应该是这样的
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
//Rest of your code
}
});
编辑2
如果您希望在单击JPanel
时替换JPanel
,您可以这样做
private Component createPanel() {
JPanel panel = new JPanel();
panel.setBackground(randomColor());
panel.setPreferredSize(new Dimension(100,50));
panel.add(new JLabel("a colored Panel"));
panel.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
int indexPosition = boxHolder.getComponentZOrder(panel);
try
{
boxHolder.remove(indexPosition);
}
catch(Exception ex){}
try //Will only add here if you have a component in index position 1
{
boxHolder.add(createPanel(),indexPosition);
}
catch(Exception ex){}
scrollPaneContainer.revalidate();
}
@Override public void mousePressed(MouseEvent e) {}
@Override public void mouseReleased(MouseEvent e) {}
@Override public void mouseEntered(MouseEvent e) {}
@Override public void mouseExited(MouseEvent e) {}
});
return panel;
}
至于改进建议。我建议将您的initScrollPane
方法更改为以下代码,以便您可能更熟悉滚动的速度
private Component initScrollPane() {
scrollPaneContainer = new JPanel( new BorderLayout() );
boxHolder = Box.createVerticalBox();
scrollPaneContainer.add(boxHolder, BorderLayout.PAGE_START);
JScrollPane jSP = new JScrollPane(scrollPaneContainer);
jSP.getVerticalScrollBar().setUnitIncrement(16);
return jSP;
}
我的答案是你想要的还是你的问题中的其他意思?在你的按钮
上添加一个动作监听器,而不是鼠标监听器
。丹,谢谢你的回答,它完全符合我的意思。问题是这不是我的问题,我问错了。我将编辑问题以添加真正的问题xD@Koop4那么,当你点击按钮(或标签或任何你使用的组件)时,你能告诉我它要替换哪个面板吗?@Koop4假设你想在点击面板时替换它,请参见我的回答中的编辑2关于编辑2:getComponentZOrder(面板)该方法工作正常。还感谢重新实现initScrollPane()。在未来,我将需要为这些面板实现可比性。在每次操作之后,我应该在滚动窗格中对它们进行排序。“你认为我应该处理一些事情吗?”Koop4只要仔细阅读你的评论。你会如何比较你的面板?我还没学过技术。在我的软件中,这些JPanel包含一个具有特定int字段的对象,我将轻松实现可比较的接口。假设我们的面板变成了对象,在其构造函数中计算了一个随机(0-100)int字段,并有一个新按钮将它们从上到下排列(递增)。您认为这样的实现对这样做有好处吗?我相信我们可以做到,但我仍然想知道使用BoxLayout是否适合这种管理方式。再次感谢您,如果您需要一些示例代码,我将提供@Koop4来执行您可能希望查看或使用的类似操作。它们显示冒泡排序和合并排序等排序。因此,最好的方法是从所有JPanel中获取INT,然后对它们进行排序。然后根据排序重新排列JPaneloutcome@Koop4至于使用BoxLayout
这实际上是个人喜好的问题。对于这个特定的程序,由于函数getComponentZOrder
,它似乎工作得很好。然而,如果你寻找另一个布局,这可能是我的最爱之一