问题
I have a question about nested BoxLayouts.
I want to build a DropDownPanel which consists of 2 sub-Panels: a header at the top and a body at the bottom. The body is initially hidden. By clicking on the header you can toggle the visibility of the body and show its contents (like expand/collapse).
In general this works fine. However there is some strange behaviour:
If only one DropDownPanel is expanded and the other is collapsed then the collapsed DropDownPanel gets resized and floated to the right.
I already experimented with the JPanel's properties like alignmentX, but I could not find my mistake. Does anyone know what I am doing wrong?
Here is the code:
DropDownPanel.java
public class DropDownPanel extends javax.swing.JPanel {
private boolean mShowContent = false;
/**
* Creates new form DropDownPanel
*/
public DropDownPanel() {
initComponents();
showContent(mShowContent);
}
private void showContent(boolean showContent) {
mShowContent = showContent;
System.out.println(mShowContent? "show" : "hide");
body.setVisible(mShowContent);
revalidate();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jPanel3 = new javax.swing.JPanel();
header = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
body = new javax.swing.JPanel();
jPanel5 = new javax.swing.JPanel();
jLabel2 = new javax.swing.JLabel();
setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.Y_AXIS));
jPanel3.setLayout(new javax.swing.BoxLayout(jPanel3, javax.swing.BoxLayout.Y_AXIS));
header.setMaximumSize(new java.awt.Dimension(32000, 60));
header.setMinimumSize(new java.awt.Dimension(0, 60));
header.setPreferredSize(new java.awt.Dimension(0, 60));
header.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
headerMouseClicked(evt);
}
});
header.setLayout(new javax.swing.BoxLayout(header, javax.swing.BoxLayout.X_AXIS));
jLabel1.setText("Click Me!");
header.add(jLabel1);
jPanel3.add(header);
body.setLayout(new javax.swing.BoxLayout(body, javax.swing.BoxLayout.Y_AXIS));
jPanel5.setLayout(new javax.swing.BoxLayout(jPanel5, javax.swing.BoxLayout.X_AXIS));
jLabel2.setText("jLabel2");
jPanel5.add(jLabel2);
body.add(jPanel5);
jPanel3.add(body);
add(jPanel3);
}// </editor-fold>//GEN-END:initComponents
private void headerMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_headerMouseClicked
System.out.println("asd");
showContent(!mShowContent);
}//GEN-LAST:event_headerMouseClicked
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel body;
private javax.swing.JPanel header;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JPanel jPanel5;
// End of variables declaration//GEN-END:variables
}
TestFrame.java
public class TestFrame extends javax.swing.JFrame {
/**
* Creates new form TestFrame
*/
public TestFrame() {
initComponents();
jPanel1.add(new DropDownPanel());
jPanel1.add(new DropDownPanel());
revalidate();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setMinimumSize(new java.awt.Dimension(400, 300));
jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.Y_AXIS));
jScrollPane1.setViewportView(jPanel1);
getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
pack();
}// </editor-fold>//GEN-END:initComponents
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/*
* Set the Nimbus look and feel
*/
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/*
* If Nimbus (introduced in Java SE 6) is not available, stay with the
* default look and feel. For details see
* http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/*
* Create and display the form
*/
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TestFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables
}
回答1:
not sure from your question are you ...
- Accordion
or
- Expand/Collapsing JPanels
or
- Ribbon (with Substance Look and Feel only)
回答2:
This happens because you set a minimum size for the header.
So, when one panel is expanded, the other shrinks because his child (the header) allows it to do so.
Don't set any minimum size for the header panel (in the Netbeans IDE, click the Reset to default button)
and the problem should be gone.
来源:https://stackoverflow.com/questions/10597989/jpanel-gets-resized-of-another-jpanel-is-shown