Java GUI - How to center a single button - java

I'm very new to java (I'm used to python).
NOTE: I do want the position to stay in the center even when the gui is resized.
I was wondering how I can center a single button? At the moment, the button is at the top of the gui.
public class main_gui extends JFrame{
public static void main(String[] args) {
// Initial window
JFrame start_frame = new JFrame("P.D");
start_frame.setSize(1200, 800);
start_frame.setVisible(true);
start_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Panel to hold our buttons
JPanel start_panel = new JPanel();
start_frame.add(start_panel);
// Button to initialize everything
JButton start_button = new JButton("Start");
// Take out the border around the text
start_button.setFocusable(false);
start_panel.add(start_button);
}
}
Here is what is currently looks like, I just want this button down a bit, to the center.

There is no need for the panel. Just add the button directly to the frame.
The easiest way is to use a GridBagLayout:
frame.setLayout( new GridBagLayout() );
frame.add(startButton, new GridBagConstraints());
By default the component will be centered horizontally and vertically within the GridBagLayout.

A quick solution would be to set the vertical gap between components of your FlowLayout to half the size of your JFrame:
public class MainGUI {
static java.awt.Dimension bd;
public static void main(String[] args) {
// Initial window
JFrame start_frame = new JFrame("P.D");
start_frame.setSize(1200, 800);
start_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Button to initialize everything
JButton start_button = new JButton("Start");
bd = start_button.getPreferredSize();
// Take out the border around the text
start_button.setFocusable(false);
// Panel to hold our buttons
java.awt.Dimension d = start_frame.getSize();
JPanel start_panel = new JPanel(new java.awt.FlowLayout(FlowLayout.CENTER, 0, d.height / 2 - bd.height / 2));
start_panel.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent evt) {
JPanel c = (JPanel) evt.getSource();
c.setLayout(new java.awt.FlowLayout(FlowLayout.CENTER, 0, c.getSize().height / 2 - bd.height / 2));
}
});
start_panel.add(start_button);
start_frame.add(start_panel);
start_frame.setVisible(true);
}
}
When the size of your JFrame is changed, the ComponentAdapter recalculates the new height and places the button to the new center.
In order to place the button to the vertical center, we calculate the height of your button and subtract its half from the vertical gap.
The horizontal center is automatically applied by the layout.
Your class should not extend JFrame if you instantiate another JFrame inside it and use it.
Class names should be nouns, in mixed case with the first letter of each internal word capitalized.
It is recommended to make your JFrame visible after you have added all widgets to it.
In order to use the SwingUtilities invoker and make your application code cleaner, let your class extend JFrame, write a constructor and call it this way:
public class MainGUIJFrame extends JFrame {
public MainGUIJFrame() {
initComponents();
}
private void initComponents() {
setTitle("P.D");
setSize(1200, 800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
start_button = new JButton("Start");
bd = start_button.getPreferredSize();
// Take out the border around the text
start_button.setFocusable(false);
java.awt.Dimension d = getSize();
start_panel = new JPanel(new java.awt.FlowLayout(FlowLayout.CENTER, 0, d.height / 2 - bd.height / 2));
start_panel.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent evt) {
JPanel c = (JPanel) evt.getSource();
c.setLayout(new java.awt.FlowLayout(FlowLayout.CENTER, 0, c.getSize().height / 2 - bd.height / 2));
}
});
start_panel.add(start_button);
add(start_panel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MainGUIJFrame().setVisible(true);
}
});
}
private JButton start_button;
private JPanel start_panel;
private java.awt.Dimension bd;
}
You keep main simple and small this way, and bd does not have to be static anymore.

You can use a layout manager like BorderLayout if you want to put the button in the center so that it occupies the whole space in the frame. So, your code will look something like this:
public class main_gui extends JFrame{
public static void main(String[] args) {
// Initial window
JFrame start_frame = new JFrame("P.D");
start_frame.setSize(1200, 800);
start_frame.setVisible(true);
start_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Panel to hold our buttons
JPanel start_panel = new JPanel();
start_panel.setLayout(new BorderLayout());
start_frame.add(start_panel);
// Button to initialize everything
JButton start_button = new JButton("Start");
// Take out the border around the text
start_button.setFocusable(false);
start_panel.add(start_button, BorderLayout.CENTER);
}
}
You may go without using a layout manager. It's a bad practice but it should work. This code will put a small button in the center of the frame:
public class MainGUI {
public static void main(String[] args) {
JFrame start_frame = new JFrame("P.D");
int width = 1200;
int height = 800;
start_frame.setSize(width, height);
start_frame.setVisible(true);
start_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Panel to hold our buttons
JPanel start_panel = new JPanel();
start_panel.setLayout(null);
start_frame.add(start_panel);
// Button to initialize everything
JButton start_button = new JButton("Start");
buttonWidth = 80;
buttonHeight = 20;
start_button.setBounds(new Rectangle((width - buttonWidth)/2, (height - buttonHeight)/2, buttonWidth, buttonHeight));
start_button.setSize(new Dimension(buttonWidth, buttonHeight));
start_button.setFocusable(false);
start_panel.add(start_button);
}
}

The best way to do it is to use a Layout of your choice and try to make it work using that.
However, if you are sure your window won't be getting resized, or you're happy to deal with such events yourself, you could attempt working without a layout and position the button manually, e.g.:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.Dimension;
public class main_gui {
public static void main(String[] args) {
// Initial window
JFrame start_frame = new JFrame("P.D");
int FrameWidth = 1200, FrameHeight = 800;
start_frame.setSize(FrameWidth, FrameHeight);
start_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Panel to hold our buttons
JPanel start_panel = new JPanel();
start_panel.setLayout(null); // Now working without a layout manager
// i.e, can position things manually.
start_frame.add(start_panel);
// Button to initialize everything
JButton start_button = new JButton("Start");
start_button.setFocusable(false); // Take out the border around the text
Dimension size = start_button.getPreferredSize();
start_button.setBounds( FrameWidth/2 - size.width/2,
FrameHeight/2 - size.height/2,
size.width, size.height);
start_panel.add(start_button);
// Display the Layout after all components have been added.
// (adding components after the frame has been set to visible
// may result in components not showing up reliably!)
start_frame.setVisible(true);
}
}

Related

Why doesn't the image paint over my JPanel?

I have been struggling with this for some time. At first, I only used ActionListener, then I added the paintComponent, but I have no idea what to put there. I read some tutorials and used their code as an example, but it still doesn't work. Right now, the end result is the same as it was without PaintComponent.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Scream extends JPanel {
private JButton button = new JButton("OK");
private Color screenColor;
private JPanel panel = new JPanel();
private JFrame frame;
private Dimension screenSize;
private ImageIcon image;
private JLabel label = new JLabel(image);
private int x;
private int y;
private boolean mouseClicked;
public Scream() {
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e ) {
if (e.getSource() == button) {
mouseClicked = true;
frame.getContentPane().add(label);
frame.setSize(image.getIconWidth(), image.getIconHeight());
panel.repaint();
}
}
});
frame = new JFrame ("Existential angst");
screenColor = new Color(150, 100, 0);
panel.setBackground( screenColor );
frame.add(button, BorderLayout.PAGE_END);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1300, 700);
frame.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
image.paintComponent(this, g, 1300, 700);
}
public static void main (String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Scream scream = new Scream();
}
});
}
}
If you are trying to dynamically add an image to a panel then you need to add the label to the panel. There is no need for any custom painting.
The basic code for adding components to a visible GUI is:
panel.add(...);
panel.revalidate();
panel.repaint();
Also, don't attempt to set the size of the frame to the size of the image. A frame contains a titlebar and borders. Instead you can use frame.pack();
I noticed a couple of issues:
image is never initialized to anything so it is null, effectively making the label empty. I assume maybe your example was just incomplete?
Once I initialized the image to something, your example still did not work. Turns out adding label without specifying any constraint basically does nothing (I assume since adding a component to a border layout without a constraint puts it in the center where panel already is). When I added the label to BorderLayout.NORTH, everything worked (though resizing the frame to the size of the image makes it only partially visible since the frame includes the OK button)

Java basic GUI blank

When I run this program it appears as an empty window until you fullscreen, then it can be resized as you like, why is it doing this/how do I stop it?
the program is very basic just a menubar and two panels split.
public class SplitPane {
public static void main(String[] args) {
window view = new window();
}
private static class window extends JFrame {
public window() {
this.setSize(1000, 750);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//menubar is here, must lower code quantity for stack
//panels
//graph half
JPanel graphRep = new JPanel();
//Background colour - graphRep.setBackground(Color.RED);
graphRep.setVisible(true);
String graphTitle = "Textual Representation.";
Border graphBorder = BorderFactory.createTitledBorder(graphTitle);
graphRep.setBorder(graphBorder);
//text half
JPanel textRep = new JPanel();
textRep.setVisible(true);
String textTitle = "Graphical Representation.";
Border textBorder = BorderFactory.createTitledBorder(textTitle);
textRep.setBorder(textBorder);
//splitpane
JSplitPane splitPane = new JSplitPane();
splitPane.setSize(600, 750);
splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setOneTouchExpandable(true);
splitPane.setDividerSize(10);
splitPane.setDividerLocation(250);
splitPane.setLeftComponent(graphRep);
splitPane.setRightComponent(textRep);
this.add(splitPane);
}
}
this.setVisible(true);
You are making the frame visible BEFORE you add components to the frame. The layout manager is never invoked so the size of all the components remains (0, 0) so there is nothing to paint.
The frame should be made visible AFTER all the components have been added to the frame.
And the code should be:
frame.pack();
frame.setVisible();
So each component is displayed at its proper size. Don't hardcode the size() because you don't know what the size of a users screen might be.

Are GridLayout cells really all the same size?

I decided to use a GridLayout LayoutManager for my Java Swing app because each cell within the grid is supposed to be exactly the same size.
From the Java Tutorials:
A GridLayout object places components in a grid of cells. Each component takes all the available space within its cell, and each cell is exactly the same size.
And even in the description of the GridLayout class:
The GridLayout class is a layout manager that lays out a container's components in a rectangular grid. The container is divided into equal-sized rectangles, and one component is placed in each rectangle.
However, my code seems to make a certain cell twice as large as the others. I added 3 JPanels to a Container with GridLayout, and gave each JPanel a different background color. This was the result:
Clearly, the first JPanel (red background) is twice as big as the others (green and yellow). The code that produced this is the following:
public void updateListFrameContentPane(Container mainPane) {
mainPane.setLayout(new GridLayout(1,0));
JPanel listPanel = new JPanel();
listPanel.setLayout(new BoxLayout(listPanel, BoxLayout.Y_AXIS));
listPanel.add(friendsLabel);
listPanel.add(listScrollPane);
listPanel.setBackground(Color.RED);
mainPane.add(listPanel);
for(JPanel chatPanel : chatPanels) {
chatPanel.setBackground((Math.random()>0.5 ? Color.YELLOW : Color.GREEN));
mainPane.add(chatPanel);
}
}
All I do is set the Container's layout to GridLayout with 1 row and any number of columns, and then add 3 JPanels to that. So why is the first JPanel so much larger? Strangely this only happens when two or more chatPanels are added. When there is only one, it formats correctly.
Kiheru is right. revalidate/repaint after changing the contents of a container. Here's a rough but working example:
public class GridLayoutExample {
private JFrame frame;
private Map<String,JPanel> chatBoxes = new HashMap<String,JPanel>();
private String lastKey = "0";
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GridLayoutExample window = new GridLayoutExample();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public GridLayoutExample() {
initialize();
}
private void addChatBox() {
/*
* JPanel (border layout)
* - JPanel (Border South, Border layout)
* - - JTextField ( Border center )
* - - JButton ( Border east )
* - JLabel (Border North )
* - JTextArea (Border Center);
*/
int lk = Integer.valueOf(lastKey)+1;
lastKey = Integer.toString(lk);
JPanel np = new JPanel();
np.setLayout(new BorderLayout(0,0));
np.setBackground((lk%2 == 0) ? Color.GREEN : Color.YELLOW);
JPanel south = new JPanel();
south.setLayout(new BorderLayout(0,0));
np.add(south,BorderLayout.SOUTH);
JButton b = new JButton("New Button");
south.add(b,BorderLayout.EAST);
JTextField field = new JTextField();
south.add(field,BorderLayout.CENTER);
JLabel label = new JLabel(lastKey);
label.setHorizontalAlignment(SwingConstants.CENTER);
np.add(label,BorderLayout.NORTH);
JTextArea text = new JTextArea();
np.add(text,BorderLayout.CENTER);
chatBoxes.put(lastKey, np);
frame.getContentPane().add(np);
frame.revalidate(); // CRITICAL MISSING LINES
frame.repaint(); // CRITICAL MISSING LINES
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 923, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new GridLayout(1, 0, 0, 0));
JPanel panel = new JPanel();
panel.setBackground(Color.RED);
frame.getContentPane().add(panel);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JLabel lblNewLabel = new JLabel("Online Users");
panel.add(lblNewLabel);
JList list = new JList();
list.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
addChatBox();
}
});
list.setModel(new AbstractListModel() {
String[] values = new String[] {"Alpha", "Beta", "Gamma", "Delta", "Epsilon"};
public int getSize() {
return values.length;
}
public Object getElementAt(int index) {
return values[index];
}
});
panel.add(list);
}
}
I chose to revalidate/repaint the entire frame, but it may be possible to have it work while repainting a lesser container. Certainly without the critical lines marked above, it doesn't matter how often you click on the list elements, nothing new will show up. With those lines, every time you click, a new chatbox is added.
Huh... just noticed this. If the red area is considered two separate panels, then they're all the exactly correct size. Have you perhaps accidentally added an extra panel?

Resize JButtons in a BoxLayout

I'm trying to make a simple menu for my game. I have 4 buttons in the center and I want to make them a little bit bigger and center them.
The last part worked but I can't seem to call any of my JButtons and do a .setSize / .setPreferedSize(new Dimension()) on it.
public class mainMenu extends JFrame {
private JButton start, highscore, help, stoppen;
public mainMenu() {
super("Master Mind");
maakComponenten();
maakLayout();
toonFrame();
}
private void maakComponenten() {
start = new JButton("Start");
start.setBackground(Color.gray);
highscore = new JButton("Higscores");
help = new JButton("Help");
stoppen = new JButton("Stoppen");
}
private void maakLayout() {
JPanel hoofdmenu = new JPanel();
hoofdmenu.setLayout(new BoxLayout(hoofdmenu, BoxLayout.Y_AXIS ));
hoofdmenu.add(start);
start.setAlignmentX(CENTER_ALIGNMENT);
hoofdmenu.add(highscore);
highscore.setAlignmentX(CENTER_ALIGNMENT);
hoofdmenu.add(help);
help.setAlignmentX(CENTER_ALIGNMENT);
hoofdmenu.add(stoppen);
stoppen.setAlignmentX(CENTER_ALIGNMENT);
super.add(hoofdmenu);
}
private void toonFrame() {
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
setSize(500,500);
}
public static void main(String[] args) {
new mainMenu();
}
}
As an example, to change the size of the "Start" button,
change :
start1 = new JButton("Start");
to
start1 = new JButton("Start") {
{
setSize(150, 75);
setMaximumSize(getSize());
}
};
The problem is that JFrames use BorderLayout by default, which means that your JPanel will naturally fill the space.
Before adding your JPanel, call the following code to change the JFrame's layout to null and use the JPanel's settings instead.
this.setLayout(null);
JPanel hoofdmenu = new JPanel();
hoofdmenu.setBounds(0,0, 400, 100);
Alternatively, you could set the maximum size of the JButtons
Dimension maxSize = new Dimension(100, 100);
start.setMaximumSize(maxSize);
highscore.setMaximumSize(maxSize);
help.setMaximumSize(maxSize);
stoppen.setMaximumSize(maxSize);
Here's another example following behind the previous two - I'm making a soundboard program, and this is actually a sample from it - The JPanel actually is needed, agreeing to the second post.
JFrame frame = new JFrame();
JPanel menuPanel = new JPanel();
JButton Button1 = new JButton("<BUTTON NAME 1>");
Button1.setSize(80, 30);
Button1.setLocation(4, 4);
JButton Button2 = new JButton("<BUTTON NAME 2>");
Button2.setSize(80, 30);
Button2.setLocation(90, 4);
Ah, and another thing - You created the buttons in a different block from the second piece of code. Doing that causes the other blocks to not see it. You need to declare them outside the block so all the blocks can see them.

pass value from one jframe to other jframe?

i created two classes one class is just like form the other class is main class and having jmenu and jinternal frames i want to print the input from the form class on the jinternal frame but i cannot understand how i recall the jinternalframe in the form classes, please guide me in this regard or any hint or some piece of code or tutorial that can help me here is code of both the classes. Moreover both classes are working fine .
JTextArea text;
static int openFrameCount = 0;
public form(){
super("Insert Form");
Container panel=getContentPane();
JPanel cc = new JPanel();
cc.setLayout(new FlowLayout());
JButton b=new JButton("print");
b.setPreferredSize(new Dimension(140,50));
b.setBounds(1000,500,350,50);
cc.add(b);
.......................................................
JLabel label1=new JLabel(" Question"+(++openFrameCount));
cc.add(label1);
text=new JTextArea();
text.setLineWrap(true);
text.setWrapStyleWord(true);
text.setPreferredSize(new Dimension(750,50));
text.setBounds(80, 60,750,50);
cc.add(text);
JLabel symbol=new JLabel("Selection for Option?");
symbol.setBounds(200, 120,1000,100);
cc.add(symbol);
..................................................
JLabel op4=new JLabel("4th Option?");
JTextArea otext4=new JTextArea();
otext4.setLineWrap(true);
otext4.setWrapStyleWord(true);
otext4.setPreferredSize(new Dimension(750,50));
otext4.setBounds(10, 40,700,30);
cc.add( op4 ) ;
cc.add( otext4 ) ;
cc.revalidate();
validate();
............................................................
}
#Override
public void actionPerformed(ActionEvent ae) {
if ( e.getSource() == b1 ){
}
}
}
and the second class of jinternalframe is
public class Desktop1 extends JFrame
implements ActionListener {
Desktop p=new Desktop();
JDesktopPane desktop;
static int openFrameCount = 0;
public Desktop1() {
super("InternalFrameDemo");
//Make the big window be indented 50 pixels from each edge
//of the screen.
int inset = 50;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(inset, inset,
screenSize.width - inset*2,
screenSize.height - inset*2);
//Set up the GUI.
desktop = new JDesktopPane(); //a specialized layered pane
createFrame(); //create first "window"
setContentPane(desktop);
setJMenuBar(createMenuBar());
//Make dragging a little faster but perhaps uglier.
desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
}
protected JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
//Set up the lone menu.
.................................................
return menuBar;
}
//React to menu selections.
public void actionPerformed(ActionEvent e) {
if ("new".equals(e.getActionCommand())) { //new
createFrame();
}
............................................
}
}
class MyInternalFrame extends JInternalFrame {
static final int xPosition = 30, yPosition = 30;
public MyInternalFrame() {
super("IFrame #" + (++openFrameCount), true, // resizable
true, // closable
true, // maximizable
true);// iconifiable
setSize(700, 700);
// Set the window's location.
setLocation(xPosition * openFrameCount, yPosition
* openFrameCount);
}
}
//Create a new internal frame.
protected void createFrame() {
Desktop1.MyInternalFrame frame = new Desktop1.MyInternalFrame();
JPanel panel=new JPanel();//to add scrollbar in jinternalpane insert jpanel
panel.setBackground(Color.white);//set background color of jinternal frame
JScrollPane scrollBar=new JScrollPane(panel,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
frame.add(scrollBar);
frame.setVisible(true);
desktop.add(frame);
try {
frame.setSelected(true);
frame.setMaximum(true);
} catch (java.beans.PropertyVetoException e) {}
}
public static void main(String[] args) {
Desktop1 d=new Desktop1();
d.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
d.setVisible(true);
}
}
i want to know hint about the work that come in this part of code to pass the value of form to internal frame when i click on print button
public void actionPerformed(ActionEvent ae) {
if ( e.getSource() == b1 ){
}
}
}
just call the constructor and pass the value
ClassName(parameter)
I guess you want to pass some text to your InternalFrame class on the button click from the main form.
Modify your createFrame() method to accept a String value
e.g-
protected void createFrame(String value){
//..your code
}
and when you call your InternalFrame class, pass this value to its constructor. e.g-
Desktop1.MyInternalFrame frame = new Desktop1.MyInternalFrame(value);
Parameterised constructor will solve your problem. Modify your InternalFrame constructor
e.g-
public MyInternalFrame(String value){
//..use this value
}

Categories