Reputation: 5496
I'm trying to make some items dynamically add to a jpanel. I have used a gridbaglayout as my manager for this jpanel ( with red background color bellow ) and I want to vertically align the panel along with its items to the top. Any idea how I can make this panel go to the top of the panel?
Here is my code:
public class WebcamFrame extends JFrame implements Runnable {
private Webcam webcam;
private WebcamPanel webcamPanel;
private JLabel labelText;
private JPanel actionsPanel;
private boolean running;
private HashSet<String> cardsPlayed;
private final JPanel actionsContainer;
private final JPanel buttonsPanel;
private final GridBagConstraints constraints;
public WebcamFrame( Callback killWebcam, Callback handleSubmit ) {
running = true;
setLayout( new FlowLayout() );
setTitle( "Scan a card" );
setIconImage( new ImageIcon(getClass().getResource("/tslogo.png")).getImage() );
setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
addWindowListener( new WindowAdapter() {
@Override
public void windowClosing( WindowEvent e ) {
super.windowClosing( e );
killWebcam.call();
}
} );
cardsPlayed = new HashSet<>();
Dimension size = WebcamResolution.QVGA.getSize();
webcam = Webcam.getDefault();
webcam.setViewSize( size );
webcamPanel = new WebcamPanel( webcam );
webcamPanel.setPreferredSize( size );
webcamPanel.setLayout( new BorderLayout() );
labelText = new JLabel( "", SwingConstants.CENTER );
if( Webcam.getDefault() == null ) labelText.setText( "No Webcam detected" );
actionsContainer = new JPanel( new BorderLayout() );
JButton confirmButton = new JButton( "Confirm Selection" );
confirmButton.addActionListener( e -> {
List<CardDataModel> cardsToSubmit = new ArrayList<>();
cardsPlayed.forEach( cardName -> {
CardDataModel card = new CardDataModel();
card.cardName = cardName;
cardsToSubmit.add( card );
} );
handleSubmit.call( cardsToSubmit );
} );
JButton clearButton = new JButton( "Clear Selection" );
buttonsPanel = new JPanel();
buttonsPanel.add( confirmButton );
buttonsPanel.add( clearButton );
buttonsPanel.setVisible( false );
constraints = new GridBagConstraints();
clearButton.addActionListener( e -> {
cardsPlayed.clear();
actionsPanel.removeAll();
constraints.gridy = 0;
actionsPanel.add( new JLabel( "Played Cards"), constraints );
actionsContainer.setVisible( false );
buttonsPanel.setVisible( false );
labelText.setVisible( false );
constraints.gridy = 0;
pack();
} );
JPanel subPanel = new JPanel();
subPanel.setLayout( new BorderLayout() );
subPanel.add( labelText, BorderLayout.NORTH );
subPanel.add( buttonsPanel, BorderLayout.SOUTH );
webcamPanel.add( subPanel, BorderLayout.SOUTH );
actionsPanel = new JPanel( new GridBagLayout() );
constraints.gridy = 0;
constraints.insets = new Insets( 0, 0, 5, 0 );
actionsPanel.add( new JLabel( "Played Cards"), constraints );
actionsPanel.setBackground(Color.red);
JScrollPane scrollPane = new JScrollPane( actionsPanel );
actionsContainer.add( scrollPane, BorderLayout.NORTH );
actionsContainer.setVisible( false );
add( webcamPanel );
add( actionsContainer );
pack();
setLocationRelativeTo( null );
setVisible( false );
setResizable( false );
}
@Override
public void run() {
do {
try {
Thread.sleep( 100 );
} catch( InterruptedException e ) {
e.printStackTrace();
}
Result result = null;
BufferedImage image;
// Only try to read qr code if webcam is open and frame is webCamFrame is visible
if( webcam.isOpen() && isVisible() ) {
if( (image = webcam.getImage()) == null ) {
continue;
}
LuminanceSource source = new BufferedImageLuminanceSource( image );
BinaryBitmap bitmap = new BinaryBitmap( new HybridBinarizer(source) );
try {
result = new MultiFormatReader().decode( bitmap );
} catch( NotFoundException e ) {
// fall through if there is no QR code in image
}
}
if( result != null ) {
String cardName = result.getText();
if( !cardsPlayed.contains( cardName ) ) {
labelText.setText( "Play card" + (cardsPlayed.size() > 0 ? "s" : "") + "?" );
cardsPlayed.add( cardName );
JPanel cardPlayedPanel = new JPanel( new GridLayout( 0, 1, 5, 5) );
cardPlayedPanel.setBorder( BorderFactory.createCompoundBorder(new LineBorder(Color.BLACK), new EmptyBorder(2, 2, 2, 2)) );
cardPlayedPanel.setOpaque( true );
cardPlayedPanel.setBackground( Color.LIGHT_GRAY );
cardPlayedPanel.add( new JLabel(cardName) );
constraints.gridy++;
actionsPanel.add(cardPlayedPanel, constraints );
actionsContainer.setVisible( true );
buttonsPanel.setVisible( true );
pack();
}
}
} while( running );
}
}
Thanks in advance for any help
Upvotes: 1
Views: 786
Reputation: 324098
I want to vertically align the panel along with its items to the top.
Read the Swing tutorial on How to Use GridBagLayout.
You can use the anchor
constraint of the GridBagConstraints
object to control the position of the component in the available space.
Edit:
if anyone knows of a better way to solve this please post an answer!
We can't give an "exact" answer because layout management always deals with frame resizing. We don't know what components should grow or shrink as the frame size is changed.
In any case the solution is always the same. Nest panels with different layout managers to achieve your desired layout.
I realised this issue occurs because my frame uses a flowlayout and the 2 components in the flowlayout are different heights
So my answer from above still stands. You change the frame layout to also use a GridBagLayout
(instead of the FlowLayout). Then you add the two child panels to the frame. Each panel you use the "anchor" constraint to anchor the panel to the vertical top of the cell.
Or if you really want to use a BoxLayout instead of the FlowLayout, then when you add your panels to the BoxLayout you would need to use:
panel.setAlignmentY(0.0f);
on each panel. This should tell each panel to align to the top. There is not need to override the getBaseLine() method.
Upvotes: 2
Reputation: 5496
Through my own experimentation I realised this issue occurs because my frame uses a flowlayout and the 2 components in the flowlayout are different heights. Then because flowlayouts are always vertically centered my issue is occuring. I solved the issue with some hacky code from here: https://stackoverflow.com/a/28878404/6716062 But if anyone knows of a better way to solve this please post an answer! :)
Upvotes: 0