使用GridBagLayout在一个面板中设置多个组件,但我不想填满整个面板
Using GridBagLayout to set multiple components in one panel, but I dont want to fill up the whole panel
我正在开展一个项目,我正在使用 java swing 构建 GUI。目前我在 JFrame
中有一个 Jpanel
应该包含一个标签(问题)和一组 buttons/textfield (答案),它可以根据被问到的问题而改变.我想让问题集中在顶部的某个地方,答案适当地集中在中间。目前我使用 GridBagLayout
设置 JLabel
和 JButton
s 但仍然没有成功。
public class QuestionPanel extends MoviePanel{
private String question;
public QuestionPanel(String type, Application app, String question) throws Exception{
super(type, app);
this.question = question;
JLabel lab = new JLabel(this.question);
this.getGbc().anchor = GridBagConstraints.PAGE_START;
this.getGbc().fill = GridBagConstraints.HORIZONTAL;
this.getGbc().weighty = 0.5;
this.getGbc().gridx = 2;
this.getGbc().gridy = 0;
lab.setFont(new Font("Helvetica", Font.BOLD, 40));
lab.setForeground(new Color(189, 189, 189, 255));
add(lab, this.getGbc());
getAnswers(type);
}
private void getAnswers(String type){
if(type.equals("AgeRestriction")){
this.getGbc().gridx=0;
this.getGbc().gridy=1;
add(new YesButton(this.getApp()),this.getGbc());
this.getGbc().gridx = 3;
this.getGbc().gridy = 1;
add(new NoButton(this.getApp()),this.getGbc());
}
}
}
GridBagLayout
设置在 super MoviePanel
和 this.getGbc()
returns 合适的 GridBagConstraints
。目前我的布局如下所示:
想法是让“是”和“否”按钮彼此靠近,并将未来的按钮动态定位在中心。
解决方案
我最终通过结合 angushjoshi and c0der 的答案解决了问题,因此在带有 GridBagLayout 的问题面板中添加了一个 answerPanel。我的代码现在看起来像这样:
public class QuestionPanel extends MoviePanel {
private String question;
private JPanel answerPanel = new JPanel();
public QuestionPanel(String type, Application app, String question) throws Exception {
super(type, app);
this.question = question;
JLabel lab = new JLabel(this.question);
answerPanel.setOpaque(false);
this.getGbc().anchor = GridBagConstraints.PAGE_START;
this.getGbc().weighty = 1;
this.getGbc().gridy = 0;
this.getGbc().gridx = 2;
this.getGbc().gridwidth = 3;
lab.setFont(new Font("Helvetica", Font.BOLD, 40));
lab.setForeground(new Color(189, 189, 189, 255));
add(lab, this.getGbc());
getAnswers(type);
}
public void getAnswers(String type) {
if (type.equals("AgeRestriction")) {
createYesNoButtons();
}
if (type.equals("Age")) {
createAgeField();
}
if (type.equals("Genre")){
createGenreButtons();
}
if (type.equals("Actor")){
createActorField();
}
}
private void createYesNoButtons() {
this.getGbc().weighty = 0.5;
this.getGbc().anchor = GridBagConstraints.CENTER;
answerPanel.add(new YesButton(this.getApp()));
answerPanel.add(new NoButton(this.getApp()));
this.add(answerPanel,this.getGbc());
}
private void createAgeField() {
this.getGbc().weighty = 0.5;
this.getGbc().anchor = GridBagConstraints.CENTER;
answerPanel.add(new AgeField(this.getApp()));
this.add(answerPanel,this.getGbc());
}
private void createGenreButtons(){
}
private void createActorField(){
}
}
现在面板看起来像这样:
感谢您的帮助!
很难为您的问题提供确切的解决方案,但我可以告诉您,您可能想尝试使用 GridBagConstraints.insets
和 GridBagConstraints.anchor
。
insets
用于更改布局中对象周围的填充,即距 JPanel 边缘的最小距离。你可以这样使用它:
this.getGbc().insets = new Inset(top,right,bottom,left);
anchor
用于表示您希望对象在布局中的放置位置,例如:
this.getGbc().anchor = GridBagConstraints.CENTER;
这里有一些有用的 GridBagConstraints.anchor
值:
FIRST_LINE_START ... PAGE_START ... FIRST_LINE_END
LINE_START ... 中心 ... LINE_END
最后_LINE_START ... PAGE_END ... 最后_LINE_END
我建议将布局分成更小、更易于布局的部分。
在这种情况下使用 3 JPanel
s 并通过以下 MRE:
进行演示
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class QuestionAnswerPanel extends JPanel{
private Image background;
//use publicly available resources when posting questions or answers
private final String imageLink = "https://www.whatsonnetwork.co.uk/uploads/800x600/98331337cb0f7f31c874e22a8f2b5f8b.jpg";
QuestionAnswerPanel() {
URL url;
try {
url = new URL(imageLink);
background = ImageIO.read(url);
setPreferredSize(new Dimension(background.getWidth(null), background.getHeight(null)));
} catch (IOException ex) {
ex.printStackTrace();
}
//border layout allows you to add components to 5 positions,
//including north and center
setLayout(new BorderLayout());
//have a JPanel for the question
JLabel lab = new JLabel("To Be Or Not To Be ?");
lab.setFont(new Font("Helvetica", Font.BOLD, 40));
lab.setForeground(new Color(189, 189, 189, 255));
JPanel questionPanel = new JPanel();
questionPanel.setOpaque(false);
questionPanel.add(lab);
add(questionPanel, BorderLayout.NORTH); //place it at the top
//have a JPanel for the answer
JPanel answerPanel = new JPanel();
answerPanel.setOpaque(false);
//use GridBagLayout to center components
answerPanel.setLayout(new GridBagLayout());
//add components as you need
answerPanel.add(new JButton("Yes"));
answerPanel.add(new JButton("No"));
add(answerPanel, BorderLayout.CENTER);//place it at the center
}
@Override //Override to paint image at the background
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, null);
}
public static void main(String[] args) throws IOException {
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new QuestionAnswerPanel());
frame.pack();
frame.setVisible(true);
}
}
我正在开展一个项目,我正在使用 java swing 构建 GUI。目前我在 JFrame
中有一个 Jpanel
应该包含一个标签(问题)和一组 buttons/textfield (答案),它可以根据被问到的问题而改变.我想让问题集中在顶部的某个地方,答案适当地集中在中间。目前我使用 GridBagLayout
设置 JLabel
和 JButton
s 但仍然没有成功。
public class QuestionPanel extends MoviePanel{
private String question;
public QuestionPanel(String type, Application app, String question) throws Exception{
super(type, app);
this.question = question;
JLabel lab = new JLabel(this.question);
this.getGbc().anchor = GridBagConstraints.PAGE_START;
this.getGbc().fill = GridBagConstraints.HORIZONTAL;
this.getGbc().weighty = 0.5;
this.getGbc().gridx = 2;
this.getGbc().gridy = 0;
lab.setFont(new Font("Helvetica", Font.BOLD, 40));
lab.setForeground(new Color(189, 189, 189, 255));
add(lab, this.getGbc());
getAnswers(type);
}
private void getAnswers(String type){
if(type.equals("AgeRestriction")){
this.getGbc().gridx=0;
this.getGbc().gridy=1;
add(new YesButton(this.getApp()),this.getGbc());
this.getGbc().gridx = 3;
this.getGbc().gridy = 1;
add(new NoButton(this.getApp()),this.getGbc());
}
}
}
GridBagLayout
设置在 super MoviePanel
和 this.getGbc()
returns 合适的 GridBagConstraints
。目前我的布局如下所示:
想法是让“是”和“否”按钮彼此靠近,并将未来的按钮动态定位在中心。
解决方案
我最终通过结合 angushjoshi and c0der 的答案解决了问题,因此在带有 GridBagLayout 的问题面板中添加了一个 answerPanel。我的代码现在看起来像这样:
public class QuestionPanel extends MoviePanel {
private String question;
private JPanel answerPanel = new JPanel();
public QuestionPanel(String type, Application app, String question) throws Exception {
super(type, app);
this.question = question;
JLabel lab = new JLabel(this.question);
answerPanel.setOpaque(false);
this.getGbc().anchor = GridBagConstraints.PAGE_START;
this.getGbc().weighty = 1;
this.getGbc().gridy = 0;
this.getGbc().gridx = 2;
this.getGbc().gridwidth = 3;
lab.setFont(new Font("Helvetica", Font.BOLD, 40));
lab.setForeground(new Color(189, 189, 189, 255));
add(lab, this.getGbc());
getAnswers(type);
}
public void getAnswers(String type) {
if (type.equals("AgeRestriction")) {
createYesNoButtons();
}
if (type.equals("Age")) {
createAgeField();
}
if (type.equals("Genre")){
createGenreButtons();
}
if (type.equals("Actor")){
createActorField();
}
}
private void createYesNoButtons() {
this.getGbc().weighty = 0.5;
this.getGbc().anchor = GridBagConstraints.CENTER;
answerPanel.add(new YesButton(this.getApp()));
answerPanel.add(new NoButton(this.getApp()));
this.add(answerPanel,this.getGbc());
}
private void createAgeField() {
this.getGbc().weighty = 0.5;
this.getGbc().anchor = GridBagConstraints.CENTER;
answerPanel.add(new AgeField(this.getApp()));
this.add(answerPanel,this.getGbc());
}
private void createGenreButtons(){
}
private void createActorField(){
}
}
现在面板看起来像这样:
感谢您的帮助!
很难为您的问题提供确切的解决方案,但我可以告诉您,您可能想尝试使用 GridBagConstraints.insets
和 GridBagConstraints.anchor
。
insets
用于更改布局中对象周围的填充,即距 JPanel 边缘的最小距离。你可以这样使用它:
this.getGbc().insets = new Inset(top,right,bottom,left);
anchor
用于表示您希望对象在布局中的放置位置,例如:
this.getGbc().anchor = GridBagConstraints.CENTER;
这里有一些有用的 GridBagConstraints.anchor
值:
FIRST_LINE_START ... PAGE_START ... FIRST_LINE_END
LINE_START ... 中心 ... LINE_END
最后_LINE_START ... PAGE_END ... 最后_LINE_END
我建议将布局分成更小、更易于布局的部分。
在这种情况下使用 3 JPanel
s 并通过以下 MRE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class QuestionAnswerPanel extends JPanel{
private Image background;
//use publicly available resources when posting questions or answers
private final String imageLink = "https://www.whatsonnetwork.co.uk/uploads/800x600/98331337cb0f7f31c874e22a8f2b5f8b.jpg";
QuestionAnswerPanel() {
URL url;
try {
url = new URL(imageLink);
background = ImageIO.read(url);
setPreferredSize(new Dimension(background.getWidth(null), background.getHeight(null)));
} catch (IOException ex) {
ex.printStackTrace();
}
//border layout allows you to add components to 5 positions,
//including north and center
setLayout(new BorderLayout());
//have a JPanel for the question
JLabel lab = new JLabel("To Be Or Not To Be ?");
lab.setFont(new Font("Helvetica", Font.BOLD, 40));
lab.setForeground(new Color(189, 189, 189, 255));
JPanel questionPanel = new JPanel();
questionPanel.setOpaque(false);
questionPanel.add(lab);
add(questionPanel, BorderLayout.NORTH); //place it at the top
//have a JPanel for the answer
JPanel answerPanel = new JPanel();
answerPanel.setOpaque(false);
//use GridBagLayout to center components
answerPanel.setLayout(new GridBagLayout());
//add components as you need
answerPanel.add(new JButton("Yes"));
answerPanel.add(new JButton("No"));
add(answerPanel, BorderLayout.CENTER);//place it at the center
}
@Override //Override to paint image at the background
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, null);
}
public static void main(String[] args) throws IOException {
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new QuestionAnswerPanel());
frame.pack();
frame.setVisible(true);
}
}