When I create a button using a loop, the last button has the size of the whole frame. How can I fix this?
package test;
import java.awt.*;
import javax.swing.*;
public class test{
private JFrame frame;
private static JButton[][] buttons = new JButton[4][4];
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
test window = new test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public test() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(200, 200, 600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
for(int i=0; i < 4; i++){
for(int j=0; j < 4; j++){
JButton btn = new JButton("" + i+j);
btn.setBounds(60*i,60*j,60,60);
if((i+j)%2==1)
btn.setBackground(Color.BLACK);
buttons[i][j] = btn;
frame.add(btn);
}
}
}
}
Don't use setBounds(...) on the buttons. It is the job of the layout manager to determine the size/location of a component. The default layout manager for a JFrame is a BorderLayout. Only a single component can be added to the CENTER of the BorderLayout, so only the size/location of the last button added is being managed by the BorderLayout and the other buttons are ignored.
Use a different layout manager. I suspect you should be using the GridLayout. Read the section from the Swing tutorial on Using Layout Managers for more information and working examples.
Don't use setBounds on the frame either. After you add the buttons to the frame and before you invoke setVisible(..) you should use frame.pack() so the buttons will be displayed at their preferred size.
This looks like a good use for the Grid Bag Layout manager. Try something like this:
First, you need to import the GridBagConstraints class.
import java.awt.GridBagConstraints;
And then just make these changes to your for loops.
for(int i=0; i < 4; i++){
for(int j=0; j < 4; j++){
JButton btn = new JButton("" + i+j);
//btn.setBounds(60*i,60*j,60,60);
if((i+j)%2==1)
btn.setBackground(Color.BLACK);
buttons[i][j] = btn;
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = i;
gbc.gridy = j;
frame.add(btn, gbc);
}
}
The Grid Bag Layout manager is pretty tricky, but once you understand how it works, it's really useful. You can check out this tutorial on Oracle for more information.
Hope that helps.
Related
When I placed an array into mainJpanel it works correctly. I want to place an array into JScrollPane but it does not work. Please explain why.
import javax.swing.*;
import java.awt.*;
public class Window extends JFrame {
public Window() {
setLocation( 100,100);
setSize(300,300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("FontView");
setVisible(true);
setLayout( new FlowLayout());
JPanel mainPanel = new JPanel();
setContentPane(mainPanel);
Method fontMassive = new Method();
//поехали
JPanel[] jPanels = new JPanel[3];
JLabel[] jLabels = new JLabel[3];
for (int i = 0; i < 3; i++) {
jPanels[i]=new JPanel();
jLabels[i] = new JLabel(fontMassive.getFonts(i));
jPanels[i].add(jLabels[i]);
}
JScrollPane scroll = new JScrollPane();
for (int i = 0; i < 3; i++) {
scroll.add(jPanels[i]);
}
mainPanel.add(scroll);
}
}
placed into mainPanel
placed into scroll
Just another Java programmer 's answer was right, i need to place an array into Panel and then place it into Srcoll.
Thank you guys for the answers.
Hi guys I'm using Eclipse and I'm trying to create a Connect4 Game Grid , which is an JPanel gridArray [6] [7]. I later add the different Panels for buttons and the grid into a main panel and add it into my frame.
My Problem:
I want to fill the gridArray JPanel with Pictures of an empty field(white color) but first of all i want to create a new Panel and insert it into my gridArray through a loop until gridArray has all 42 Panels inside it and is fully filled. I have my Code below but somehow it doesnt work, although my logic should be fine.
I tried it with using a helper Function to create a new JPanel and call the function for each loop in fillGrid();, basically calling it 42 times but it still wont work...
I will gladly appreciate some help!
package connect4;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class GridTest extends JFrame {
JFrame mainWindow;
JPanel buttonPanel, mainPanel;
JPanel gridPanel;
JPanel emptyPanel;
JPanel panel1;
ImageIcon emptyBox;
JPanel[][] gridArray;
JLabel emptyLabel;
JButton arrow1,arrow2,arrow3,arrow4,arrow5,arrow6,arrow7;
public GridTest() {
createGameGrid();
fillGrid();
}
public void createGameGrid() {
//creating window and mainpanel
mainWindow = new JFrame("Connect 4");
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
//defining top panel with 7 buttons;
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 7));
arrow1 = new JButton("V");
arrow2 = new JButton("V");
arrow3 = new JButton("V");
arrow4 = new JButton("V");
arrow5 = new JButton("V");
arrow6 = new JButton("V");
arrow7 = new JButton("V");
buttonPanel.add(arrow1);
buttonPanel.add(arrow2);
buttonPanel.add(arrow3);
buttonPanel.add(arrow4);
buttonPanel.add(arrow5);
buttonPanel.add(arrow6);
buttonPanel.add(arrow7);
//create Grind Panel
gridPanel = new JPanel();
gridPanel.setLayout(new GridLayout(6,7));
mainPanel.add(buttonPanel, BorderLayout.NORTH);
mainPanel.add(gridPanel, BorderLayout.SOUTH);
mainWindow.add(mainPanel);
mainWindow.pack();
mainWindow.setLocationRelativeTo(null);
mainWindow.setVisible(true);
}
private JPanel greateOnePanel(){
//here we need to insert the icon which is in empty box into a newly created panel
//ifirst wanted to insert black panels do ensure it works as intended but it doesnt
JPanel panel = new JPanel();
panel.setBackground(Color.BLACK);
panel.setSize(50,50);
return panel;
}
//here we need to fill the grid with the panels created above from left to right...
public void fillGrid() {
for(int j = 0; j < 6; j++) {
for (int k = 0; k < 7; k++) {
gridPanel.add(greateOnePanel());
}
}
}
public static void main(String[] args) {
new GridTest();
}
}
i tried it with this method using gridArray, but it throws NullPointer Exeptions and wont fill the grid with simple textlabels "Hallo" (just for testing purposes)
public void fillGrid() {
for(int j = 0; j < 6; j++) {
for (int k = 0; k < 7; k++) {
JLabel label = new JLabel("Hallo");
gridArray[j][k] = new JPanel();
gridArray[j][k].setSize(50, 50);
gridArray[j][k].setBackground(Color.RED);
gridArray[j][k].add(label);
gridPanel.add(gridArray[j][k]);
}
}
}
Here is a short, self contained, code that should help with various aspects of the task.
There is no need for a panel in each cell. The only thing it helped with was setting a BG color. That can be done in a label as long as the background is set to opaque.
This code defines a SquareLabel which overrides getPreferredSize() to return the maximum of preferred width and height as the value of both (usually it is the width).
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class SquareLabelGrid {
int rows = 6;
int cols = 7;
JLabel[][] labelArray = new JLabel[cols][rows];
Font bigFont = new Font(Font.SANS_SERIF, Font.BOLD, 30);
Insets labelInsets;
SquareLabelGrid() {
JPanel gameBoard = new JPanel(new GridLayout(rows, cols));
// a border to make the cell boundaries more clear and add
// some space around the text
Border border = new CompoundBorder(
new LineBorder(Color.BLACK),new EmptyBorder(4,4,4,4));
for (int yy = 0; yy < rows; yy++) {
for (int xx = 0; xx < cols; xx++) {
JLabel l = getColoredSquareLabel(xx, yy);
labelArray[xx][yy] = l;
gameBoard.add(l);
l.setBorder(border);
}
}
JOptionPane.showMessageDialog(null, gameBoard);
}
private JLabel getColoredSquareLabel(int x, int y) {
SquareLabel label = new SquareLabel(
String.format("%1s,%1s", (x+1), (y+1)));
label.setFont(bigFont);
label.setOpaque(true); // so we can see the BG color
label.setBackground(Color.ORANGE); // I prefer orange!
// make the GUI less 'crowded'
label.setBorder(new EmptyBorder(4,4,4,4));
return label;
}
public static void main(String[] args) {
Runnable r = () -> {
new SquareLabelGrid();
};
SwingUtilities.invokeLater(r);
}
}
class SquareLabel extends JLabel {
SquareLabel(String label) {
super(label);
}
/* This will create a square component that accounts for the
size of the String / Icon it contains. No guesswork! */
#Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
int w = d.width;
int h = d.height;
int sz = w > h ? w : h;
return new Dimension(sz, sz);
}
}
The problem is that you have not initialized the grid array .
Otherwise it will throw Null pointer exception.
JPanel[][] gridArray = new JPanel[6][8];
Also set the preferred size of main panel to make the grids visible .
mainPanel.setPreferredSize(new Dimension(400, 200));
Here is what i can see when I run your code with the modifications mentioned here .
Also please execute it from main with following code .
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GridTest();
}
});
}
I'm new to Java programming. Can you help me with the layout of my first application (which is a simple calculator) please?
Here's the code I wrote:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class InputPad extends JFrame {
private JLabel statusLabel;
private JTextArea expTextArea;
InputPad() {
prepareGUI();
}
private void prepareGUI(){
JFrame mainFrame = new JFrame("My Calculator");
mainFrame.setSize(450,450);
mainFrame.setLayout(new GridLayout(3,2));
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
JLabel headerLabel = new JLabel("Put your expression here:", JLabel.CENTER);
statusLabel = new JLabel("",JLabel.CENTER);
expTextArea = new JTextArea("1+(2^3*4)");
//Digits Panel
JPanel digitPanel = new JPanel();
GroupLayout layoutDigits = new GroupLayout(digitPanel);
digitPanel.setLayout(layoutDigits);
layoutDigits.setAutoCreateGaps(true);
layoutDigits.setAutoCreateContainerGaps(true);
//Operators Panel
JPanel operatorPanel = new JPanel();
GroupLayout layoutOperators = new GroupLayout(operatorPanel);
operatorPanel.setLayout(layoutOperators);
layoutOperators.setAutoCreateGaps(true);
layoutOperators.setAutoCreateContainerGaps(true);
JButton[] numButtons= new JButton[10];
int i;
for (i=0;i<10;i++){
numButtons[i] = new JButton(Integer.toString(i));
numButtons[i].addActionListener(e -> {
// TODO
});
}
JButton bEquals = new JButton("=");
bEquals.addActionListener(e -> {
// TODO
});
JButton bPlus = new JButton("+");
bPlus.addActionListener(e -> {
// TODO
});
JButton bMinus = new JButton("-");
bMinus.addActionListener(e -> {
// TODO
});
JButton bMultiply = new JButton("*");
bMultiply.addActionListener(e -> {
// TODO
});
JButton bDivide = new JButton("/");
bDivide.addActionListener(e -> {
// TODO
});
JButton bLeftParenthesis = new JButton("(");
bLeftParenthesis.addActionListener(e -> {
// TODO
});
JButton bRightParenthesis = new JButton(")");
bRightParenthesis.addActionListener(e -> {
// TODO
});
JButton bPower = new JButton("^");
bPower.addActionListener(e -> {
// TODO
});
JButton bDel = new JButton("←");
bDel.addActionListener(e -> {
// TODO
});
layoutDigits.setHorizontalGroup(
layoutDigits.createSequentialGroup()
.addGroup(layoutDigits.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(numButtons[7])
.addComponent(numButtons[4])
.addComponent(numButtons[1])
.addComponent(numButtons[0]))
.addGroup(layoutDigits.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(numButtons[8])
.addComponent(numButtons[5])
.addComponent(numButtons[2])
.addComponent(bEquals))
.addGroup(layoutDigits.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(numButtons[9])
.addComponent(numButtons[6])
.addComponent(numButtons[3]))
);
layoutDigits.setVerticalGroup(
layoutDigits.createSequentialGroup()
.addGroup(layoutDigits.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(numButtons[7])
.addComponent(numButtons[8])
.addComponent(numButtons[9]))
.addGroup(layoutDigits.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(numButtons[4])
.addComponent(numButtons[5])
.addComponent(numButtons[6]))
.addGroup(layoutDigits.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(numButtons[1])
.addComponent(numButtons[2])
.addComponent(numButtons[3]))
.addGroup(layoutDigits.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(numButtons[0])
.addComponent(bEquals))
);
layoutOperators.setHorizontalGroup(
layoutOperators.createSequentialGroup()
.addGroup(layoutOperators.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(bPlus)
.addComponent(bMinus)
.addComponent(bLeftParenthesis)
.addComponent(bPower))
.addGroup(layoutOperators.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(bMultiply)
.addComponent(bDivide)
.addComponent(bRightParenthesis)
.addComponent(bDel))
);
layoutOperators.setVerticalGroup(
layoutOperators.createSequentialGroup()
.addGroup(layoutOperators.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(bPlus)
.addComponent(bMultiply))
.addGroup(layoutOperators.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(bMinus)
.addComponent(bDivide))
.addGroup(layoutOperators.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(bLeftParenthesis)
.addComponent(bRightParenthesis))
.addGroup(layoutOperators.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(bPower)
.addComponent(bDel))
);
mainFrame.add(headerLabel);
mainFrame.add(expTextArea);
mainFrame.add(digitPanel);
mainFrame.add(operatorPanel);
mainFrame.add(statusLabel);
mainFrame.setVisible(true);
}
}
I tried the GridLayout for my JFrame, but I couldn't resize and of my JComponent except the main JFrame. Even I can't place two JPanels (side by side) in one cell of the GridLayout or expand a JLabel to two cells of the GridLayout.
This is what I got:
And here's what I want:
Let's start from the use of Layout Managers, from the link on the part of GridLayout
GridLayout simply makes a bunch of components equal in size and displays them in the requested number of rows and columns
So, this isn't what you want, but if you read the GridBagLayout part it says:
GridBagLayout is a sophisticated, flexible layout manager. It aligns components by placing them within a grid of cells, allowing components to span more than one cell. The rows in the grid can have different heights, and grid columns can have different widths.
We can combine both of them, along with a BoxLayout and you will get a similar output to what you're trying to achieve:
PLEASE NOTE:
Before posting the code, take note of the following tips:
You're extending JFrame and at the same time you're creating a JFrame object, this is discouraged, remove one of them, in this case as you're using the object and this is the recommended thing to do, simply remove the extends JFrame from your class. If you really need to extend something, don't extend JFrame but a JPanel instead.
Place your program inside the EDT, as I did in the main() method
Don't use System.exit(0); instead call setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) as shown in the above code
And now the code
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class CalculatorExample {
private JFrame frame;
private JTextArea area;
private JButton[][] digitsButtons, symbolsButtons;
private String[][] digitsText = {{"7", "8", "9"}, {"4", "5", "6"}, {"1", "2", "3"}, {"0", "="}}; //Looks strange but this will make the button adding easier
private String[][] symbolsText = {{"+", "*"}, {"-", "/"}, {"(", ")"}, {"^", "←"}};
private JPanel buttonsPane, areaAndResultsPane, digitsPane, symbolsPane;
private JLabel label;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new CalculatorExample().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame("Calculator Example");
area = new JTextArea();
area.setRows(5);
area.setColumns(20);
label = new JLabel("Results go here");
digitsButtons = new JButton [4][3];
symbolsButtons= new JButton [4][2];
areaAndResultsPane = new JPanel();
areaAndResultsPane.setLayout(new BoxLayout(areaAndResultsPane, BoxLayout.PAGE_AXIS));
buttonsPane = new JPanel();
buttonsPane.setLayout(new GridLayout(1, 2, 10, 10));
digitsPane = new JPanel();
digitsPane.setLayout(new GridBagLayout());
symbolsPane = new JPanel();
symbolsPane.setLayout(new GridLayout(4, 2));
GridBagConstraints c = new GridBagConstraints();
for (int i = 0; i < digitsText.length; i++) {
for (int j = 0; j < digitsText[i].length; j++) {
digitsButtons[i][j] = new JButton(digitsText[i][j]);
}
}
for (int i = 0; i < symbolsText.length; i++) {
for (int j = 0; j < symbolsText[i].length; j++) {
symbolsButtons[i][j] = new JButton(symbolsText[i][j]);
}
}
areaAndResultsPane.add(area);
areaAndResultsPane.add(label);
boolean shouldBreak = false;
for (int i = 0; i < digitsButtons.length; i++) {
for (int j = 0; j < digitsButtons[i].length; j++) {
c.gridx = j;
c.gridy = i;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
if (i == 3) {
if (j == 1) {
c.gridwidth = 2; //This makes the "=" button larger
shouldBreak = true;
}
}
digitsPane.add(digitsButtons[i][j], c);
if (shouldBreak) {
break;
}
}
}
for (int i = 0; i < symbolsButtons.length; i++) {
for (int j = 0; j < symbolsButtons[i].length; j++) {
symbolsPane.add(symbolsButtons[i][j]);
}
}
frame.add(areaAndResultsPane, BorderLayout.NORTH);
buttonsPane.add(digitsPane);
buttonsPane.add(symbolsPane);
frame.add(buttonsPane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
This was done nesting JPanels, each with a different layout, I hope it helps you to continue from here.
According to the Oracle documentation :
Each component takes all the available space within its cell, and each cell is exactly the same size.
So sadly, you can't resize any components inside a GridLayout.
You could instead use a GridBagLayout. It is a little bit more complicated to understand but offers more features. I let you make some tests with the documentation to get in touch with it !
So I'm new to Java and im definitely new to Swing.
I've got a 80 X 80 array thats going to be used by a maze. I need my gui to have 80 X 80 buttons so they can be tied to the values in my array.
I cant figure out why I'm only getting five or six large buttons from this code. If anyone can tell me how I can get this to work then thank you in advance because I'm stumped.
Just run it and you'll see what I mean...also I guess I've not figured out how to change the color of the buttons and I changed the background color instead.
Heres my code:
public static void draw() {
JFrame f = new JFrame();
f.setTitle("Maze");
f.setSize(800, 800);
f.setVisible(true);
f.setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel c = (JPanel)f.getContentPane();
GridLayout gridLayout = new GridLayout();
c.setLayout(gridLayout);
for(int i =0;i<80;i++){
for(int j =0;j<80;j++){
JButton b = new JButton();
c.add(b, i,j);
b.setSize(10, 10);
b.setOpaque(true);
b.setBackground(Color.red);
}
}
}
}
80 * 10 > f.setSize(800, 800); and your code is not possible to fit in FullHd monitor
use f.pack() instead of f.setSize(800, 800);
f.pack() and f.setVisible(true); (could be a main issue) should be last code lines in non_static and renamed to !public void DrawMe() {!, because draw() is reserved word for/in Java API
c.add(b, i,j); should be last code line too (logical ordering),
c.add(b, i,j); set row and columns for GridLayout instead of injecting the JButton to virtual grid in GridLayout
make me some sense (starting with the numbers of elements)
from
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawMe {
private JFrame frame = new JFrame();
private JPanel c = new JPanel();
private static final int column = 10;
private static final int row = 10;
public DrawMe() {
c.setLayout(new GridLayout(row, column));
for (int i = 0; i < column; i++) {
for (int j = 0; j < row; j++) {
JButton b = new JButton((i + 1) + " " + (j + 1));
c.add(b);
}
}
frame.add(c);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new DrawMe();
}
});
}
}
I have an array of objects laid out through a GridLayout in a JPanel. I need to be able to recreate the object in an index in the array and have the GridLayout update to reflect this. As of yet, I cannot find anyway to "refresh" or redraw the GridLayout. Is it possible to refresh a GridLayout without creating the entire GridLayout or JPanel? Assume I do not have access to JFrame.
import javax.swing.*;
import java.awt.*;
public class Test
{
public static void main(String args[])
{
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(5,5));
JLabel[][] labels = new JLabel[5][5];
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
labels[j][i] = new JLabel("("+j+", "+i+")");
panel.add(labels[j][i]);
}
}
labels[0][0] = new JLabel("Hello World");
//Without doing it this way (cause my objects can't do this)
//labels[0][0].setText("Hello World!");
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}
I don't understand why you can't just update the text on the label.
Why do you need to "recreate the object"? It makes no sense. But if you really need to do this then the code would be something like:
panel.remove(0);
panel.add(theNewLabel, 0);
panel.revalidate();
panel.repaint();