JDialog - "line break" in between components - java

I have a JDialog that looks like this:
JDialog myDialog = new JDialog();
myDialog.setLocationRelativeTo(parent);
// parent is a JPanel.
// I want the Dialog to appear in the middle of the parent JPanel.
myDialog.setModal(true);
myDialog.setLayout(new FlowLayout());
myDialog.add(new JLabel("my text", SwingConstants.CENTER));
myDialog.add(new JButton("button 1"));
myDialog.add(new JButton("button 2"));
myDialog.pack();
myDialog.setVisible(true);
The result is a dialog where the JLabel and the JButtons appear next to each other.
1) What is the most convenient way make a "line break" after the JLabel, so that the JButtons appear below the JLabel, without using setSize()? I want the size to be automatically determined so the the components fit exactly, as is done by pack().
2) When I do set a custom size, the dialog appears where I want it: the middles of parent and myDialog match. However, if I use pack() instead, the top left corner of myDialog is at the middle of the parent. What is the best way to make the middles match instead?

Nest JPanels, each using its own layout manager
Call setLocationRelativeTo(parent) after calling pack(). You need to position the window after it has been rendered.
For example:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class SimpleGuiPanel extends JPanel {
private static final String TITLE = "This is my Dialog Title";
public SimpleGuiPanel() {
JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER);
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 16f));
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 5));
buttonPanel.add(new JButton("Button 1"));
buttonPanel.add(new JButton("Button 2"));
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(titleLabel, BorderLayout.PAGE_START);
add(buttonPanel, BorderLayout.CENTER);
}
private static void createAndShowGui() {
JPanel mainFramePanel = new JPanel();
mainFramePanel.setPreferredSize(new Dimension(500, 400));
final JFrame mainFrame = new JFrame("Main Frame");
mainFrame.add(mainFramePanel);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SimpleGuiPanel simpleGuiPanel = new SimpleGuiPanel();
final JDialog myDialog = new JDialog(mainFrame, "Dialog", ModalityType.APPLICATION_MODAL);
myDialog.getContentPane().add(simpleGuiPanel);
myDialog.pack();
mainFramePanel.add(new JButton(new AbstractAction("Show Dialog") {
#Override
public void actionPerformed(ActionEvent e) {
myDialog.setLocationRelativeTo(mainFrame);
myDialog.setVisible(true);
}
}));
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}

Related

Problem with buttons exceeding the Panel (JAVA)

I'm having a problem with a layout I'm trying to do in java. I have 2 panels in a 800x600 frame. The first panel "gamePanel" is (600x600) and the second "menuPanel" is (200x600).
In the menuPanel there are 4 buttons that I tried to organize as a single column of 4 rows using gridLayout(which partially worked). The buttons appear to be in place but when hovering on them they expand occupying the other panel (gamePanel). I tried placing them using setBounds but they directly disappear.
This is how it works before hovering the buttons.
After hovering 2 buttons, but all 4 are displayed the same way
Here is the code:
public class Layout {
Point point = new Point();
public Layout() {
JFrame window = new JFrame();
ImageIcon icon = new ImageIcon("images/icon.jpg");
//JFRAME
window.setSize(800,600);
window.setLocationRelativeTo(null);
window.setTitle("Arkanoid");
window.setUndecorated(true);
window.setIconImage(icon.getImage());
//PANELS
JPanel gamePanel = new JPanel();
gamePanel.setBackground(Color.RED);
gamePanel.setBounds(0, 0, 600, 600);
JPanel menuPanel = new JPanel(new GridLayout(4,1));
menuPanel.setBackground(Color.BLACK);
menuPanel.setBounds(600,0,200,600);
menuPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
window.add(gamePanel);
window.add(menuPanel);
//Buttons
JButton closeButton = new JButton("Close Me");
closeButton.addActionListener(e -> System.exit(0));
menuPanel.add(closeButton);
JButton playButton = new JButton("Play");
menuPanel.add(playButton);
JButton Button1 = new JButton("Test1");
menuPanel.add(Button1);
JButton Button2 = new JButton("Test2");
menuPanel.add(Button2);
//Labels
//SHOW
window.setVisible(true);
}
}
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Laying Out Components Within a Container section.
A JFrame has a default BorderLayout, which I used to place the two JPanels.
I added a main method so I could run the GUI. I commented out the icon code, which doesn't make any sense for an undecorated JFrame. I moved the setLocationRelativeTo method to after the pack method, so the JFrame is actually centered.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ExampleLayout {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ExampleLayout();
}
});
}
Point point = new Point();
public ExampleLayout() {
JFrame window = new JFrame();
// ImageIcon icon = new ImageIcon("images/icon.jpg");
// JFRAME
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setTitle("Arkanoid");
window.setUndecorated(true);
// window.setIconImage(icon.getImage());
// PANELS
JPanel gamePanel = new JPanel();
gamePanel.setBackground(Color.RED);
gamePanel.setPreferredSize(new Dimension(600, 600));
JPanel menuPanel = new JPanel(new GridLayout(0, 1));
menuPanel.setBackground(Color.BLACK);
menuPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
menuPanel.setPreferredSize(new Dimension(200, 600));
window.add(gamePanel, BorderLayout.CENTER);
window.add(menuPanel, BorderLayout.EAST);
// Buttons
JButton closeButton = new JButton("Close Me");
closeButton.addActionListener(e -> System.exit(0));
menuPanel.add(closeButton);
JButton playButton = new JButton("Play");
menuPanel.add(playButton);
JButton Button1 = new JButton("Test1");
menuPanel.add(Button1);
JButton Button2 = new JButton("Test2");
menuPanel.add(Button2);
// Labels
// SHOW
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}

Is there an option to add ScrollPane without disabling CardLayout?

I have a card layout where I switch panels with a button. However, the code (switching panels) works only when lines:
JScrollPane scrPane = new JScrollPane(card1);
frame.add(scrPane);
are removed. In other case, clicking button achieves nothing. Is there an option to keep the scrolling (I need this, since the main application will have a lot of wrapped text) without disabling an option to switch cards?
package com.code;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.event.*;
public class Card {
public static void main(String[] args) {
JFrame frame = new JFrame("App");
frame.setVisible(true);
frame.setSize(1200, 800);//Give it a size
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel mainPanel = new JPanel(new CardLayout());
frame.add(mainPanel);
JPanel menu = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel card1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel card2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
mainPanel.add(menu, "menu");
mainPanel.add(card1, "card1");
mainPanel.add(card2, "card2");
JLabel l1 = new JLabel("label 1");
JLabel l2 = new JLabel("label 2");
card1.add(l1);
card2.add(l2);
JButton click = new JButton("Click!");
menu.add(click);
JScrollPane scrPane = new JScrollPane(card1);
frame.add(scrPane);
click.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cardLayout = (CardLayout) mainPanel.getLayout();
cardLayout.show(mainPanel, "card1");
}
});
}
}
A JFrame (its content pane) uses BorderLayout by default. That means you can have only 1 component at BorderLayout.CENTER. When you frame.add(component) the default constraints is BorderLayout.CENTER.
Now, you frame.add(mainPanel); and then frame.add(scrPane);. So main panel is removed, since scrPane is being added after it.
Doing JScrollPane scrPane = new JScrollPane(card1); it means you add a scrollpane to card1, and not in content pane. I guess that you want it to the content pane (the whole frame). So the fix is to delete frame.add(mainPanel); and do the following:
JScrollPane scrPane = new JScrollPane(mainPanel);
frame.add(scrPane);
Now, the main panel is added to scrPane and scrPane is added to the frame.
However, your GUI will be empty after that, because you frame.setVisible(true); before you are finished adding components to it. Take a look at Why shouldn't I call setVisible(true) before adding components?
Eventually, full code is:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("App");
frame.setSize(1200, 800);//Give it a size
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel mainPanel = new JPanel(new CardLayout());
JPanel menu = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel card1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel card2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
mainPanel.add(menu, "menu");
mainPanel.add(card1, "card1");
mainPanel.add(card2, "card2");
JLabel l1 = new JLabel("label 1");
JLabel l2 = new JLabel("label 2");
card1.add(l1);
card2.add(l2);
JButton click = new JButton("Click!");
menu.add(click);
JScrollPane scrPane = new JScrollPane(mainPanel);
frame.add(scrPane);
click.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cardLayout = (CardLayout) mainPanel.getLayout();
cardLayout.show(mainPanel, "card1");
}
});
frame.setVisible(true);
});
}
Some good links I suggest you to read are the Initial Threads and What does .pack() do?

Can't position Buttons or JLabels

I am new to working with GUI's in Java and I am having a problem moving my text and buttons around. No matter what coordinates I give my button or any of the other JLabel it doesn't move, I was wondering how I could fix it this in such a way that I can place my components where ever I want on the JPanel
public class IntroPage extends JFrame {
public static void main(String[] args) {
IntroPage main = new IntroPage();
main.setVisible(true);
}
private JPanel contentPane;
public IntroPage (){
//make sure the program exits when the frame closes
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Welcome");
contentPane = new JPanel();
setSize(400,700);
//This will center the JFrame in the middle of the screen
setLocationRelativeTo(null);
//Welcome Page stuff :D
JLabel ApplauseLabel = new JLabel("Welcome to U.X.Dot.X");
ApplauseLabel.setFont(new Font("Gill Sans MT", Font.PLAIN, 30));
ApplauseLabel.setLocation(100, 50);
contentPane.add(ApplauseLabel);
JLabel slogan = new JLabel("Register below");
slogan.setFont(new Font("Gill Sans MT", Font.PLAIN, 15));
slogan.setLocation(100, 400);
contentPane.add(slogan);
//FacebookSignUp.
JButton FBbutton = new JButton("Login With FaceBook");
FBbutton.setBackground(Color.BLUE);
FBbutton.setSize(50,50);
FBbutton.setLocation(20, 40);
FBbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Add JPanel to go to FB API. Much later
}
});
contentPane.add(FBbutton);
add(contentPane);
//make sure the JFrame is visible
setVisible(true);
}
}
You're ignoring the layout managers of your contentPane JPanel. Understand that it uses FlowLayout by default, and will ignore your setLocation and setBounds statements. Ror the JPanel to accept absolute positioning, you would have to give it a null layout via contentPane.setLayout(null).
Having said that, I do not advise you to do this! While null layouts, setLocation(...) and setBounds(...) might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
For example the following GUI
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import javax.swing.*;
public class IntroPage2 extends JPanel {
public static final String TITLE = "Welcome to U.X.Dot.X";
private JLabel welcomeLabel = new JLabel(TITLE, SwingConstants.CENTER);
private JButton fbButton = new JButton("Login With Facebook");
public IntroPage2() {
fbButton.setBackground(Color.BLUE);
fbButton.setForeground(Color.CYAN);
welcomeLabel.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 30));
int wlGap = 20;
welcomeLabel.setBorder(BorderFactory.createEmptyBorder(wlGap, wlGap, wlGap, wlGap));
JLabel registerBelowLabel = new JLabel("Register Below");
registerBelowLabel.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 15));
JPanel centralPanel = new JPanel(new GridBagLayout());
centralPanel.setPreferredSize(new Dimension(300, 600));
centralPanel.add(registerBelowLabel);
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(fbButton, BorderLayout.LINE_START);
topPanel.add(welcomeLabel, BorderLayout.CENTER);
setLayout(new BorderLayout());
int ebGap = 8;
setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap));
add(topPanel, BorderLayout.PAGE_START);
add(centralPanel, BorderLayout.CENTER);
}
private static void createAndShowGui() {
IntroPage2 mainPanel = new IntroPage2();
JFrame frame = new JFrame("Welcome");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
would create something like:

Moving JButtons

What would be the best way for me to move the buttons so they are under each other instead of beside each other (see image below)?
The code for this class is as follows. The Main method is in a different class.
package guiplay;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class MainGUI extends JFrame {
private JButton openReportSelection = new JButton("Open Report Viewer");
private JButton closeButton = new JButton("Close Program");
private JButton getCloseButton(){
return closeButton;
}
private JButton getOpenReportSelection(){
return openReportSelection;
}
public MainGUI(){
mainInterface();
}
private void mainInterface(){
setTitle("Program Information Application");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel centerPanel = new JPanel(new FlowLayout());
centerPanel.add(openReportSelection);
openReportSelection.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
JFrame reports = new JFrame();
new ReportGUI();
}
});
centerPanel.add(closeButton);
getCloseButton().addActionListener(new Listener());
add(centerPanel, BorderLayout.CENTER);
setSize(700,200);
setVisible(true);
}
}
You can use a BoxLayout as it aligns all elements either horizontally or vertically. Simply set BoxLayout's axis to BoxLayout.Y_AXIS.
Example:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.BoxLayout;
import javax.swing.JButton;
public class BoxLayoutExample extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
BoxLayoutExample frame = new BoxLayoutExample();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public BoxLayoutExample() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 180, 150);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
JButton btnOpenReportViewer = new JButton("Open Report Viewer");
contentPane.add(btnOpenReportViewer);
JButton btnCloseProgram = new JButton("Close Program");
contentPane.add(btnCloseProgram);
}
}
If you want to control the size so that they are similar to each other, you can use a grid layout by setting the JFrame's content pane to a GridLayout:
contentPane.setLayout(new GridLayout(0, 1, 0, 0)); // the value of 1 here means 1 column
Don't put the JButtons in a container that uses FlowLayout but rather one that uses another layout that allows stacking of components. A GridLayout comes to mind if the buttons are to be the same size, or if they need to be different sizes, a BoxLayout.
Check out the Layout Manager Tutorial.
You could try using a BoxLayout instead of a FlowLayout. In that case, you could have:
JPanel centerPanel = new JPanel(new BoxLayout());
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS)); // Y_AXIS will cause the components to be added vertically
centerPanel.add(openReportSelection);
centerPanel.add(closeButton);
centerPanel.setMaximumSize(new Dimension(100, 60)); // Set the maximum horizontal and vertical distances used, as BoxLayouts expand to fill the provided area
Or as Hovercraft said, you could use a GridLayout, in which case you would specify it as follows:
JPanel centerPanel = new JPanel(new GridLayout(1,0); // The "0" parameter specifies as many rows as needed, but only one column
centerPanel.add(openReportSelection);
centerPanel.add(closeButton);
centerPanel.setMaximumSize(new Dimension(100, 60)); // GridLayouts will also expand to fill the entire area, so you'll probably want some size parameters.
You could also see this link for more on BoxLayouts, or this link for more on GridLayouts.

Getting Labels a name with a label

This panel class is suppose to print out "Course Info" Yet when I do try to print it out on the GUI, the gui frame shows up but not the Panel. So I feel the panel code is the problem, how to get the "Course Info" to appear? And if the label is working correctly, why when I post the label to the gui, it just shows another blank Frame?
Panel:
import javax.swing.*;
import java.awt.*;
public class TopPanel extends JPanel {
public TopPanel(){
JPanel panel = new JPanel();
JLabel Crse = new JLabel("Course Info");
Crse.setFont(new Font("Serif", Font.PLAIN, 14));
panel.add(Crse);
}
}
GUI code:
import javax.swing.*;
import java.awt.*;
public class CourseGUI extends JFrame {
public CourseGUI()
{
super("CourseGUI Frame");
JPanel topPanel = new JPanel();
topPanel.setBackground(java.awt.Color.WHITE);
Dimension d = new Dimension(800,600);
topPanel.setPreferredSize(d);
this.setLayout(new BorderLayout());
this.add(topPanel, BorderLayout.NORTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(800,600);
//JPanel tp = new TopPanel();
//this.add(tp.BorderLayout.North);
JPanel panel = new TopPanel();
this.add(panel, BorderLayout.SOUTH);
this.setVisible(true);
}
public static void main(String[] args)
{
new CourseGUI();
}
}
Try like this
public TopPanel(){
JLabel Crse = new JLabel("Course Info");
Crse.setFont(new Font("Serif", Font.PLAIN, 14));
add(Crse);
}
You are creating new JPanel which will not going to get added in JFrame.
As you are doing this.
this.add(topPanel, BorderLayout.NORTH);
for JFrame but topPanel don't have anything to display because you didn't add anything.

Categories