将面板中的项目与顶部摆动对齐
Align items in a panel to the top swing
我正在尝试将一些项目动态添加到 jpanel。我使用 gridbaglayout 作为这个 jpanel 的管理器(下面是红色背景),我想将面板及其项目垂直对齐到顶部。知道如何使此面板位于面板顶部吗?
这是我的代码:
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 );
}
}
提前感谢您的帮助
I want to vertically align the panel along with its items to the top.
阅读 How to Use GridBagLayout 上的 Swing 教程。
可以使用GridBagConstraints
对象的anchor
约束来控制组件在可用space.
中的位置
编辑:
if anyone knows of a better way to solve this please post an answer!
我们无法给出“准确”的答案,因为布局管理总是处理框架大小调整。我们不知道随着帧大小的变化,哪些组件应该增大或缩小。
无论如何,解决方案总是一样的。嵌套具有不同布局管理器的面板以实现您想要的布局。
I realised this issue occurs because my frame uses a flowlayout and the 2 components in the flowlayout are different heights
所以我上面的回答仍然有效。您将框架布局更改为也使用 GridBagLayout
(而不是 FlowLayout)。然后将这两个子面板添加到框架中。您使用“锚点”约束将面板锚定到单元格的垂直顶部的每个面板。
或者,如果您真的想使用 BoxLayout 而不是 FlowLayout,那么当您将面板添加到 BoxLayout 时,您需要使用:
panel.setAlignmentY(0.0f);
在每个面板上。这应该告诉每个面板对齐到顶部。不需要覆盖 getBaseLine() 方法。
通过我自己的实验,我意识到这个问题的发生是因为我的框架使用了流式布局,而流式布局中的 2 个组件高度不同。然后因为 flowlayouts 总是垂直居中我的问题发生了。我从这里用一些骇人听闻的代码解决了这个问题:
但是,如果有人知道解决此问题的更好方法,请 post 回答! :)
我正在尝试将一些项目动态添加到 jpanel。我使用 gridbaglayout 作为这个 jpanel 的管理器(下面是红色背景),我想将面板及其项目垂直对齐到顶部。知道如何使此面板位于面板顶部吗?
这是我的代码:
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 );
}
}
提前感谢您的帮助
I want to vertically align the panel along with its items to the top.
阅读 How to Use GridBagLayout 上的 Swing 教程。
可以使用GridBagConstraints
对象的anchor
约束来控制组件在可用space.
编辑:
if anyone knows of a better way to solve this please post an answer!
我们无法给出“准确”的答案,因为布局管理总是处理框架大小调整。我们不知道随着帧大小的变化,哪些组件应该增大或缩小。
无论如何,解决方案总是一样的。嵌套具有不同布局管理器的面板以实现您想要的布局。
I realised this issue occurs because my frame uses a flowlayout and the 2 components in the flowlayout are different heights
所以我上面的回答仍然有效。您将框架布局更改为也使用 GridBagLayout
(而不是 FlowLayout)。然后将这两个子面板添加到框架中。您使用“锚点”约束将面板锚定到单元格的垂直顶部的每个面板。
或者,如果您真的想使用 BoxLayout 而不是 FlowLayout,那么当您将面板添加到 BoxLayout 时,您需要使用:
panel.setAlignmentY(0.0f);
在每个面板上。这应该告诉每个面板对齐到顶部。不需要覆盖 getBaseLine() 方法。
通过我自己的实验,我意识到这个问题的发生是因为我的框架使用了流式布局,而流式布局中的 2 个组件高度不同。然后因为 flowlayouts 总是垂直居中我的问题发生了。我从这里用一些骇人听闻的代码解决了这个问题: