I want the buttons and textfield to go in the spaces marked red in the same layout as they are in. look at the picture to understand what I mean.
update: the buttons are in the place now, but the image wont appear on the second panel
how can I move them to there? heres my code so far
package gasindicator;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
import java.io.*;
import javax.imageio.*;
import java.net.*;
public class GasIndicator extends JPanel
{
private Image image;
GasIndicator()
{
try
{
image = ImageIO.read(new URL("http://i68.tinypic.com/2ceja8i.png"));
}
catch (IOException ioe)
{
System.out.println("Unable to fetch image.");
ioe.printStackTrace();
}
setLayout( new BorderLayout() );
JLabel background = new JLabel( new ImageIcon(image) );
background.setLayout( new FlowLayout(FlowLayout.LEFT) );
add( background );
JPanel buttonPanel = new JPanel( new GridLayout(0, 3, 6, 5) );
buttonPanel.setBorder( new EmptyBorder(338, 233, 0, 0) );
buttonPanel.setOpaque( false );
//for (int i = 0; i < 7; i++)
{
JButton button = new JButton("Button");
JButton button1 = new JButton("Button");
JButton button2 = new JButton("Button");
JButton button3 = new JButton("Button");
JButton button4 = new JButton("Button");
JButton button5 = new JButton("Button");
button.setPreferredSize( new Dimension(160, 45) );
buttonPanel.add(button);
buttonPanel.add(button1);
buttonPanel.add(button2);
buttonPanel.add(button3);
buttonPanel.add(button4);
buttonPanel.add(button5);
button.addActionListener(new Action());
}
background.add( buttonPanel );
}
static class Action implements ActionListener {
public void actionPerformed(ActionEvent e) {
JFrame frame2 = new JFrame("Museums in London");
frame2.setVisible(true);
frame2.setSize(550, 650);
JPanel panel = new JPanel();
frame2.add(panel);
Custom contentPane;
// JFrame frame = new JFrame("JTextField");
contentPane = new Custom();
frame2.setContentPane(contentPane);
}
}
private static void ShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GasIndicator());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> ShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
class Custom extends JPanel {
public BufferedImage image;
public Custom() {
try {
image = ImageIO.read(new URL
("http://www.destination360.com/europe/uk/images/s/museums.jpg"));
} catch (IOException ioe) {
System.out.println("Unable to fetch image.");
ioe.printStackTrace();
}
}
public Dimension getPreferredSize() {
return (new Dimension(image.getWidth(), image.getHeight()));
}
public void paintComponent(Graphics x) {
super.paintComponent(x);
x.drawImage(image, 10, 10, this);
}
}
}
Simple example to demonstrate the concept of using a layout manager with a Border. The size of the buttons has also been tweaked to the size of the buttons in the image:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
import java.io.*;
import javax.imageio.*;
import java.net.*;
public class SSCCE extends JPanel
{
private Image image;
SSCCE()
{
try
{
image = ImageIO.read(new URL("http://i68.tinypic.com/2ceja8i.png"));
}
catch (IOException ioe)
{
System.out.println("Unable to fetch image.");
ioe.printStackTrace();
}
setLayout( new BorderLayout() );
JLabel background = new JLabel( new ImageIcon(image) );
background.setLayout( new FlowLayout(FlowLayout.LEFT) );
add( background );
JPanel buttonPanel = new JPanel( new GridLayout(0, 3, 6, 5) );
buttonPanel.setBorder( new EmptyBorder(338, 233, 0, 0) );
buttonPanel.setOpaque( false );
for (int i = 0; i < 6; i++)
{
JButton button = new JButton("Button " + i);
button.setPreferredSize( new Dimension(160, 45) );
buttonPanel.add(button);
}
background.add( buttonPanel );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
Yes, there is still some tweaking of the values. But it is easier to adjust the location of the entire panel with one EmptyBorder and all the buttons move at the same time than it is to adjust the location of each button individually.
Note: Don't use the JLabel to display the image as the components will shift if the frame is resized. Instead use your custom panel to paint the image.
The problem here is that your panel has the standart Layoutmanager set onto it.
Try disable it with
contentPane.setLayout(null);
Then you can move the buttons around like you want with button.setBountds(x,y,w,h);
I always draw directly on the Frame, not using a custom panel like you do, but I see that there are use cases where this would be the better way.
If you write
new JFrame.getContentPane().setLayout(null);
your frame gets the default pane and still has it's layout set to null.
The difference is you can add directly to the frame instead of using a panel where you drop your stuff on.
frame.add(new Button().setBounds(x,y,w,h));
Try out this version of the code I tried to debugg:
Custom1 contentPane;
//at first create and set the frame
JFrame frame = new JFrame("Windowname goes here");
frame.setSize(1160, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
//next add your custom panel
contentPane = new Custom1();
frame.setContentPane(contentPane);
//better add this to the panel instead of the frame
JTextField textfield = new JTextField(20);
frame.add(textfield);
textfield.setBackground(Color.black);
textfield.setForeground(Color.white);
//you are using 2 panels with null layout here
JPanel panel = new JPanel();
panel.setSize(frame.getHeight(),frame.getWidth()); //give the panel some bounds!
panel.setOpaque(false); //unnecesary
panel.setLayout(null);
panel.setBackground(Color.BLACK);
frame.add(panel);
JButton button = new JButton("London");
JButton button1 = new JButton("Oxford");
JButton button2 = new JButton("Cambridge");
//you seemed to not have added these before
JButton button4 = new JButton("Click");
JButton button5 = new JButton("Click");
JButton button6 = new JButton("Click");
button.setBounds(60, 400, 220, 30);
button.setBackground(Color.black);
button.setForeground(Color.WHITE);
button1.setBounds(x,y,w,h); // !!!! <------
button1.setBackground(Color.black);
button1.setForeground(Color.WHITE);
button2.setBounds(x,y,w,h); // !!!! <------
button2.setBackground(Color.black);
button2.setForeground(Color.WHITE);
button4.setBounds(80, 50, 100, 30);
button5.setBounds(x,y,w,h); // !!!! <------
button6.setBounds(x,y,w,h); // !!!! <------
panel.add(button);
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.add(button5);
panel.add(button6);
//SETVISIBLE ALWAYS GOES LAST
frame.setVisible(true);
I patched your code and wrote some comments in it.
I marked the spots where you need to set the bounds for the buttons with !!!!<----, you seemed to have made this for button4 but not for the other ones. Also you should get a better structure in your code, I don't want to insult you but I would call this "spaghetti code".
There are aswell some things that where a problem, for example you seemed to not have added the buttons at all but they where present in your picture...
Let me know if it would work or not after playing around with the bounds value and investigating for eventual mistakes in the code.
Also if you sent me the whole project I could watch over it, but better try it yourself, it won't give you anything if someone else made your work.
Good luck and happy coding ( ͡° ͜ʖ ͡°)
Related
I am trying to set my JTextArea to take up the max horz length of the screen, so that the next thing, in this case a button, will start on a new line, but I have no clue how to do it. I have messed around by setting the size of the JTextArea to change from, say, 20 to 1000 but that does not do anything.
How can I get my textarea to take up the entire first row and then have the next item that I add to begin on the following row? Here is what I have so far...
MyFrame(){//constructor
super("Simple Calculator");
p = new JPanel();
grid = new GridLayout(4, 4, 3, 3);
p.setLayout(grid);
setSize(400, 500);
setResizable(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setUpTextScreen();
//create buttons
for(int i = 0; i < buttonValues.length; i++){
p.add(new JButton(buttonValues[i]));
}
add(p);
setVisible(true);
}
private void setUpTextScreen() {
textOnScreen = new JTextArea(7, 1000);
textOnScreen.setText("0");//default
textOnScreen.setEditable(false);
p.add(textOnScreen);
}
How can I get my textarea to take up the entire first row and then have the next item that I add to begin on the following row?
Break your layout up into logical pieces. Start with your main panel using a BorderLayout.
First I would use a JTextField for the calculator display, not a JTextArea. Then you can add the text field using: mainPanel.add(textField, BorderLayout.PAGE_START);
Then you create a JPanel using a GridLayout for the buttons. Then you add the buttons to the button panel and use: maonPanel.add(buttonPanel, BorderLayout.CENTER);
For example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class CalculatorPanel extends JPanel
{
private JTextField display;
public CalculatorPanel()
{
Action numberAction = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
// display.setCaretPosition( display.getDocument().getLength() );
display.replaceSelection(e.getActionCommand());
}
};
setLayout( new BorderLayout() );
display = new JTextField();
display.setEditable( false );
display.setHorizontalAlignment(JTextField.RIGHT);
add(display, BorderLayout.NORTH);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout( new GridLayout(0, 5) );
add(buttonPanel, BorderLayout.CENTER);
for (int i = 0; i < 10; i++)
{
String text = String.valueOf(i);
JButton button = new JButton( text );
button.addActionListener( numberAction );
button.setBorder( new LineBorder(Color.BLACK) );
button.setPreferredSize( new Dimension(30, 30) );
buttonPanel.add( button );
InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke(text), text);
inputMap.put(KeyStroke.getKeyStroke("NUMPAD" + text), text);
button.getActionMap().put(text, numberAction);
}
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Calculator Panel");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( new CalculatorPanel() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Hava a look at Nested layouts, you can add one panel with a BorderLayout (there are other options too though) and add the textarea to it. Then you only need one more panel with a GridLayout that displays the buttons. This is an example: (Note that a few lines are unnecessary in this code, but they help understand layouts)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.LineBorder;
public class Example extends JFrame {
Example() {//
super("Simple Calculator");
// The Main Panel where the 2 other panels will be on
JPanel mainPanel = new JPanel(new BorderLayout());
// The textarea will be inside this panel
JPanel areaPanel = new JPanel(new BorderLayout());
JTextArea area = new JTextArea(
"This is a JTextArea -Long text to show it works -Long text to show it works- -Long text to show it works- -Long text to show it works- -Long text to show it works- -Long text to show it works-");
area.setBorder(new LineBorder(Color.BLACK));
area.setWrapStyleWord(true);
area.setLineWrap(true);
// Fill the whole space of the panel with the area
areaPanel.add(area, BorderLayout.CENTER);
// The buttons will be inside this panel
JPanel buttonPanel = new JPanel(new GridLayout(4, 4, 3, 3));
for (int i = 0; i < 16; i++) { // Adding buttons
buttonPanel.add(new JButton("Button" + i));
}
// The textarea-panel should be on top of the main panel
mainPanel.add(areaPanel, BorderLayout.NORTH);
// The panel with the buttons should fill the remaining space
mainPanel.add(buttonPanel, BorderLayout.CENTER);
getContentPane().add(mainPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
setVisible(true);
}
public static void main(String[] args) {
new Example();
}
}
You can also use html tags like:
JButton button = new JButton("<html><b><u>T</u>wo</b><br>lines</html>");
Or in any other JComponent like you got.
So you can use <BR> tag you achieve your need.
I am trying to add 24 JButtons to the GridLayout of my JPanel buttonPanel, but when I run it, I see that no buttons are added. (At least, they are not visible!). I tried giving the buttonPanel a background color, and it
was visible.
Does anyone know what I'm doing wrong?
This is my code (there is an other class):
package com.Egg;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class NormalCalc implements ActionListener {
static JPanel normalCalcPanel = new JPanel();
JPanel buttonPanel = new JPanel(new GridLayout(6,4,10,10));
Font font = new Font("Monospaced Bold", Font.BOLD, 18);
JButton powB = new JButton("^");
JButton sqrtB = new JButton("sqrt(");
JButton hOpenB = new JButton("(");
JButton hCloseB = new JButton(")");
JButton delB = new JButton("DEL");
JButton acB = new JButton("AC");
JButton mulB = new JButton("*");
JButton divB = new JButton("/");
JButton addB = new JButton("+");
JButton minB = new JButton("-");
JButton decB = new JButton(".");
JButton equB = new JButton("=");
JButton negB = new JButton("(-)");
JButton[] numberButtons = new JButton[10];
JButton[] functionButtons = new JButton[13];
public NormalCalc() {
functionButtons[0] = powB;
functionButtons[1] = delB;
functionButtons[2] = acB;
functionButtons[3] = sqrtB;
functionButtons[4] = mulB;
functionButtons[5] = divB;
functionButtons[6] = hOpenB;
functionButtons[7] = addB;
functionButtons[8] = minB;
functionButtons[9] = hCloseB;
functionButtons[10] = decB;
functionButtons[11] = negB;
functionButtons[12] = equB;
for (int i=0; i<10; i++) {
numberButtons[i] = new JButton(String.valueOf(i));
numberButtons[i].setFocusable(false);
numberButtons[i].setFont(font);
numberButtons[i].addActionListener(this);
}
for (int i=0; i <13; i++) {
functionButtons[i].setFocusable(false);
functionButtons[i].setFont(font);
functionButtons[i].addActionListener(this);
}
normalCalcPanel.setBounds(0, 0, 500, 700);
buttonPanel.setBounds(50, 200, 400, 400);
// Adding the buttons;
buttonPanel.add(functionButtons[0]);
buttonPanel.add(numberButtons[7]);
buttonPanel.add(numberButtons[8]);
buttonPanel.add(numberButtons[9]);
buttonPanel.add(functionButtons[1]);
buttonPanel.add(functionButtons[2]);
buttonPanel.add(functionButtons[3]);
buttonPanel.add(numberButtons[4]);
buttonPanel.add(numberButtons[5]);
buttonPanel.add(numberButtons[6]);
buttonPanel.add(functionButtons[4]);
buttonPanel.add(functionButtons[5]);
buttonPanel.add(functionButtons[6]);
buttonPanel.add(numberButtons[1]);
buttonPanel.add(numberButtons[2]);
buttonPanel.add(numberButtons[3]);
buttonPanel.add(functionButtons[7]);
buttonPanel.add(functionButtons[8]);
buttonPanel.add(functionButtons[9]);
buttonPanel.add(numberButtons[0]);
buttonPanel.add(functionButtons[10]);
buttonPanel.add(functionButtons[11]);
buttonPanel.add(functionButtons[12]);
buttonPanel.repaint();
normalCalcPanel.add(buttonPanel);
normalCalcPanel.add(MainMath.exitButton);
MainMath.frame.add(normalCalcPanel);
MainMath.frame.repaint();
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
Other (main) class:
package com.Egg;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class MainMath implements ActionListener {
static JFrame frame = new JFrame("Math Tools");
static JButton exitButton = new JButton("Exit");
JPanel mainPanel = new JPanel();
JLabel mainLabel = new JLabel("Select your tool.", SwingConstants.CENTER);
JButton nB = new JButton("Normal Calc.");
JButton tB = new JButton("Right Triangle Calc.");
JButton eB = new JButton("Equations Calc.");
public MainMath() {
frame.setBounds(300, 300, 500, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setResizable(false);
mainPanel.setLayout(null);
mainPanel.setBounds(0, 0, 500, 700);
mainLabel.setBounds(100, 25, 300, 50);
mainLabel.setFont(new Font("Monospaced Bold", Font.BOLD, 18));
nB.setBounds(100, 100, 300, 40);
tB.setBounds(100, 150, 300, 40);
eB.setBounds(100, 200, 300, 40);
nB.setFocusable(false);
tB.setFocusable(false);
eB.setFocusable(false);
nB.addActionListener(this);
tB.addActionListener(this);
eB.addActionListener(this);
mainPanel.add(mainLabel);
mainPanel.add(nB);
mainPanel.add(tB);
mainPanel.add(eB);
frame.add(mainPanel);
frame.setVisible(true);
exitButton.setBounds(16, 10, 80, 35);
exitButton.setFocusable(false);
exitButton.addActionListener(this);
}
public static void main(String[] args) {
new MainMath();
System.out.println("");
}
public void setMainScreen() {
frame.remove(exitButton);
frame.remove(NormalCalc.normalCalcPanel);
frame.add(mainPanel);
frame.repaint();
}
public static JFrame getFrame() {
return frame;
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == exitButton)
setMainScreen();
if (e.getSource() == nB) {
frame.remove(mainPanel);
new NormalCalc();
}
if (e.getSource() == tB)
new TriangleCalc();
if (e.getSource() == eB)
new EquationCalc();
}
}
I see multiple issues in your code:
Your arrangement of your buttons is weird looking at first glance.
normalCalcPanel is static, why? It should never be
setBounds(...) when using layout managers, those statements are ignored, so no need for them
repaint() unless you've added / removed any element AFTER you've displayed your GUI, these calls are unnecessary, and should come with revalidate() as well.
MainMath.exitButton another static component, STOP
MainMath.frame.add(normalCalcPanel) implies that your JFrame called frame is static as well, which again, shouldn't be
And (I'm gonna guess here) more than probably you're creating a second instance inside MainMath, but because we don't have the code from that class we don't know what's going on
I ran your code and it looks ok, so that's why I believe your MainMath is creating another instance of JFrame
Here's an example of a calculator arrangement, that should help you to structure your code similarly, not the GUI but the components and classes
Edit
Okay, I understand now that I should not use static things, but how can I add a panel to a frame which I created in another class? I used 'static', because it seemed to work
Let's make an analogy for this case, imagine that your JFrame is a book, and that your JPanels are the sheets of that book, when you write on those sheets, you don't add / paste the book to the sheets, you add the sheets to the book.
So, in this case it's the same, your main class should create the JPanels and add those to your JFrame, your JPanel classes shouldn't have knowledge of your JFrame
In the case of the book, your sheets don't need to know to which book the belong, you know that and the book knows which sheets belong to it, not viceversa.
I made an example to show you what I mean by this, I didn't recreate your GUI but made it as simple as I could for you to get the idea:
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class AnotherCalculator {
private JFrame frame;
private CalculatorPanel calculatorPanel;
public static void main(String[] args) {
SwingUtilities.invokeLater(new AnotherCalculator()::createAndShowGUI);
}
private void createAndShowGUI() {
frame = new JFrame(getClass().getSimpleName());
calculatorPanel = new CalculatorPanel();
frame.add(calculatorPanel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class CalculatorPanel extends JPanel {
private String[] operations = {"+", "-", "*", "/", "DEL", "AC", "(", ")", "-", "^", "SQRT", ".", "+/-", "="};
private static final int NUMBER_OF_DIGITS = 10;
private JButton[] buttons;
public CalculatorPanel() {
this.setLayout(new GridLayout(0, 4, 5, 5));
buttons = new JButton[operations.length + NUMBER_OF_DIGITS];
for (int i = 0; i < buttons.length; i++) {
if (i < NUMBER_OF_DIGITS) {
buttons[i] = new JButton(String.valueOf(i));
} else {
buttons[i] = new JButton(operations[i - NUMBER_OF_DIGITS]);
}
this.add(buttons[i]);
}
}
}
I wrote a program to compose a GUI using swing/awt framework for my assignment. So far, I am able to get the pieces working together, but when I put them all into a JFrame, they are not coming out as expected.
I have recently started working on Java GUI framework, and not sure what is missing in my code. How can I get this working properly?
I am also attaching the screen shots (see at the bottom) of the output I am getting.
public class MainFrame extends JFrame {
public MainFrame() {
addComponentsToPane(this.getContentPane());
}
private void addComponentsToPane(Container pane) {
// Set layout
GridBagConstraints gbc = new GridBagConstraints();
this.setTitle("Test tool");
this.setSize(600, 650);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new GridLayout(2, 1));
// Add video JComponent
mMainPanel = new MainPanel();
pane.add(mMainPanel, 0);
// Add conference screen panel
mFeedPanel = new FeedPanel();
pane.add(mFeedPanel, 1);
// Add a button panel
mButtonPanel = new ButtonPanel();
pane.add(mButtonPanel, 2);
this.setResizable(true);
this.setVisible(true);
this.pack();
}
}
// In actual output, there is 1 screen in this panel.
// mScreen1 is derived from JComponent object.
public class MainPanel() extends JPanel {
public MainPanel() {
addMainPanelComponents();
}
private void addMainPanelComponents() {
this.setSize(352, 240);
setBackground(Color.yellow);
setLayout(new GridLayout(1, 2));
add(mScreen);
setVisible(true);
}
}
// In actual output, there are 3 screens in this panel. I have shown code for 1 screen only
// mScreen1 is derived from JComponent object.
public class FeedPanel extends JPanel {
public FeedPanel() {
addFeedPanelComponents();
}
private void addFeedPanelComponents() {
String img1 = "images/screen1.png";
setSize(352, 150);
setBackground(Color.yellow);
setLayout(new GridLayout(1, 3));
Image image1 = ImageIO.read(new File(img1));
mScreen1.setImage(image1);
add(mScreen1);
setVisible(true);
}
}
public class ButtonPanel extends JPanel {
public ButtonPanel() {
addButtonPanelComponents();
}
private void addButtonPanelComponents() {
this.setSize(352, 150);
this.setBackground(Color.yellow);
this.setLayout(new GridLayout(1,
5));
// Add Button to panel
mStartButton = new JButton("Start");
this.add(mStartButton);
mStartButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
StartButtonActionListener(ae);
}
});
mStopButton = new JButton("Stop");
this.add(mStopButton);
mStopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
StopButtonActionListener(ae);
}
});
setVisible(true);
}
}
This comes by default on running the code.
This comes after manually resizing the frame.
The combination of BorderLayout , GirdLayout and BoxLayout can do this for you(Actually it's not the only choice).
Here is the code:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GridLayoutTest {
public void createUI(){
JFrame frame = new JFrame();
JPanel topPanel = new TopPanel();
JPanel buttomPanel = new ButtomPanel();
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainPanel.add(topPanel,BorderLayout.CENTER);
mainPanel.add(buttomPanel,BorderLayout.SOUTH);
frame.add(mainPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
GridLayoutTest test = new GridLayoutTest();
test.createUI();
}
#SuppressWarnings("serial")
class TopPanel extends JPanel{
public TopPanel(){
setLayout(new GridLayout(2, 3));
ImageIcon icon = new ImageIcon("capture.png");
JLabel label1 = new JLabel(icon);
label1.setVisible(false);
JLabel label2 = new JLabel(icon);
JLabel label3 = new JLabel(icon);
label3.setVisible(false);
JLabel label4 = new JLabel(icon);
JLabel label5 = new JLabel(icon);
JLabel label6 = new JLabel(icon);
add(label1);
add(label2);
add(label3);
add(label4);
add(label5);
add(label6);
}
}
#SuppressWarnings("serial")
class ButtomPanel extends JPanel{
public ButtomPanel(){
JButton startButton = new JButton("start");
JButton stopButton = new JButton("stop");
JButton recordButton = new JButton("record");
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(Box.createHorizontalGlue());
add(startButton);
add(Box.createHorizontalStrut(10));
add(stopButton);
add(Box.createHorizontalStrut(10));
add(recordButton);
add(Box.createHorizontalGlue());
}
}
}
BoxLayout is so good too provide white space and help you to center the component.
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(Box.createHorizontalGlue());
add(startButton);
add(Box.createHorizontalStrut(10));
add(stopButton);
add(Box.createHorizontalStrut(10));
add(recordButton);
add(Box.createHorizontalGlue());
Add Glue before the first component and after the last component will help you too center the component and add strut can help you to provide white space you want. you can refer to https://stackoverflow.com/a/22525005/3378204 for more details.
Here is the effect:
The BoxLayout won't affect your component's size. Hope it can help you.
Try this :
public class Main{
private JFrame f;
private JLabel l1, l2, l3,l4;
private JPanel p1, p2, p3;
private JButton b1, b2, b3;
public Main(){
this.f = new JFrame();
this.f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.f.setLayout(new GridLayout(3,1));
this.p1 = new JPanel();
this.p1.setLayout(null)
this.p1.setSize(yoursize);
this.l1 = new JLabel();
this.l1.setBounds(x,y,xspan,yspan);
this.p1.add(l1);
this.p2 = new JPanel();
this.p2.setLayout(new GridLayout(1,3));
this.l2 = new JLabel();
this.l3 = new JLabel();
this.l4 = new JLabel();
this.p2.add(l2);
this.p2.add(l3);
this.p2.add(l4);
this.p3 = new JPanel();
this.p3.setLayout(new GridLayout(1,3));
this.b1 = new JButton();
this.b2 = new JButton();
this.b3 = new JButton();
this.p3.add(b1);
this.p3.add(b2);
this.p3.add(b3);
this.f.add(p1);
this.f.add(p2);
this.f.add(p3);
this.f.pack();
this.f.setResizeable(false)
}}
Add your video components instead of labels and you can change the color of the components as you wish.
Also if you want more control over the size and position of the components, use null layout and place them individually using setBounds() function as once shown in the program above. It is surely time consuming but makes the layout perfect.
As part of a project we've got to have 9 boxes, here I've just implemented alternating colors as an example in place of the images we should be using. But whilst I want these 9 JLabels in this grid layout (3,3), I also want to have a message at the top (a JLabel) that I can just centralize, like a welcoming message as well as having around four JButtons underneath? Can somebody please point me in the right direction as to how to achieve this?
Thank you!
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class HomeController extends JPanel implements MouseListener
{
HomeController()
{
setLayout(new GridLayout(3,3));
JLabel apl1 = new JLabel("");
apl1.setBackground(Color.WHITE);
apl1.setOpaque(true);
this.add(apl1);
JLabel apl2 = new JLabel("");
apl2.setBackground(Color.BLACK);
apl2.setOpaque(true);
this.add(apl2);
JLabel apl3 = new JLabel("");
apl3.setBackground(Color.WHITE);
apl3.setOpaque(true);
this.add(apl3);
JLabel apl4 = new JLabel("");
apl4.setBackground(Color.BLACK);
apl4.setOpaque(true);
this.add(apl4);
JLabel apl5 = new JLabel("");
apl5.setBackground(Color.WHITE);
apl5.setOpaque(true);
this.add(apl5);
JLabel apl6 = new JLabel("");
apl6.setBackground(Color.BLACK);
apl6.setOpaque(true);
this.add(apl6);
JLabel apl7 = new JLabel("");
apl7.setBackground(Color.WHITE);
apl7.setOpaque(true);
this.add(apl7);
JLabel apl8 = new JLabel("");
apl8.setBackground(Color.BLACK);
apl8.setOpaque(true);
this.add(apl8);
JLabel apl9 = new JLabel("");
apl9.setBackground(Color.WHITE);
apl9.setOpaque(true);
this.add(apl9);
JLabel message = new JLabel("hello world");
this.add(message);
}
}
You can combine multiple panels with different layouts. For details take a look at A Visual Guide to Layout Managers.
For example, default layout of JFrame is BorderLayout. Using BorderLayout, you can place the title at BorderLayout.NORTH, panel with buttons at BorderLayout.SOUTH and panel with grid of labels at BorderLayout.CENTER. Each panel may have its own more complex layout. For example, grid of labels is using GridLayout, and buttons panel is using FlowLayout.
Here is a very simple example based on the posted code that demonstrates this approach:
import java.awt.*;
import javax.swing.*;
public class TestGrid {
public TestGrid() {
final JFrame frame = new JFrame("Grid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel(new GridLayout(3, 3));
for (int idx = 0; idx < 9; idx++) {
JLabel label = new JLabel();
label.setBackground(idx % 2 == 0 ? Color.WHITE : Color.BLACK);
label.setOpaque(true);
mainPanel.add(label);
}
mainPanel.setPreferredSize(new Dimension(200, 200));
frame.add(mainPanel, BorderLayout.CENTER);
frame.add(new JLabel("Title", JLabel.CENTER), BorderLayout.NORTH);
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(new JButton("Start"));
buttonsPanel.add(new JButton("Stop"));
frame.add(buttonsPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestGrid();
}
});
}
}
How do I make the subpanels within my main panel stay where they are when I set one of the subpanels to be invisible?
What I have looks like:
[ (Panel1) (Panel2) (Panel3) (Panel4) ]
When I do panel3.setVisible(false) it then looks like:
[ (Panel1) (Panel2) (Panel4) ]
I would like it to look like:
[ (Panel1) (Panel2) (Panel4) ]
I am using the GridBagLayout and my mainPanel declaration looks like:
final JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
and I add an new panel like:
final JTextField valueTextField = new JTextField();
valueTextField.setPreferredSize(new Dimension(80, 25));
valueTextField.setName("Value");
c.gridx =0;
panel.add(valueTextField, c);
I'll provide more code if needed and I don't care which layout I use as long as it gets me what I want.
I suggest using a CardLayout within the individual cells, and instead of setting it to invisible, switch to an empty panel instead.
The code below demonstrates this. Within hidePanel() there are two options to hide the cell with the CardLayout route currently enabled.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class InvisiblePanels {
public static void main(String... args) throws Exception {
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
frame.add(new MyPanel(), c);
c.gridx = 1;
frame.add(new MyPanel(), c);
c.gridx = 2;
frame.add(new MyPanel(), c);
frame.pack();
frame.setVisible(true);
}
private static class MyPanel extends JPanel {
CardLayout layout;
public MyPanel() {
layout = new CardLayout();
setLayout(layout);
JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
hidePanel();
}
});
add(button, "visible");
add(new JPanel(), "invisible");
layout.show(this, "visible");
}
public void hidePanel() {
// setVisible(false);
layout.show(this, "invisible");
}
}
}
I believe all the layout manager respect the visibility of a component and don't include invisible components in the preferred size and layout calculations.
One solution might be to wrap all your panels in a panel using the OverlayLayout:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class OverlayLayoutInvisible
{
public static void main(String[] args)
{
JPanel panel = new JPanel();
panel.add( createPanel("Button 1") );
panel.add( createPanel("Button 2") );
panel.add( createPanel("Button 3") );
panel.add( createPanel("Button 4") );
panel.add( createPanel("Button 5") );
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( panel );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static JPanel createPanel(String text)
{
JButton button = new JButton( text );
button.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Component c = (Component)e.getSource();
c.setVisible(false);
}
});
InvisibleComponent ic = new InvisibleComponent( button );
JPanel panel = new JPanel();
panel.setLayout( new OverlayLayout(panel) );
panel.add( ic );
panel.add( button );
return panel;
}
public static class InvisibleComponent extends JComponent
{
private Component master;
public InvisibleComponent(Component master)
{
this.master = master;
setAlignmentX( master.getAlignmentX() );
setAlignmentY( master.getAlignmentY() );
}
public Dimension getPreferredSize()
{
return master.getPreferredSize();
}
}
}
You might be able to tweak GridLayout (do you have an SSCCE?)
Otherwise:
Put Panel3 and Panel4 together in a single panel that you add to the GridBagLayout. Then setup the new Panel in a Layout like FlowLayout (aligned Left with a preferred size), BorderLayout, GridLayout, etc.