I'm having some trouble trying to resize the components in my GUI when I resize the GUI. Right now, when I resize the GUI, the size of the components don't change, they keep to the static size I set them to. When I resize the GUI passed the minimum size needed to display them, they are no longer displayed. I want them to resize and maintain an aspect ratio when the GUI is resized.
Here's the code I have for the GUI:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.*;
import java.net.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.text.*;
import javax.swing.text.html.*;
public class DraftGUI implements MouseListener {
private JPanel jpPack;
private JPanel jpCards;
private JPanel jpInfo;
private JPanel jpChat;
private TextField tf;
private StyledDocument doc;
private JTextPane tp;
private JScrollPane sp;
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
e.getComponent().setVisible(false);
}
private Client client;
public GUI(Client client) throws IOException {
JFrame frame = new JFrame("Draft");
//set the size to fullscreen to start
frame.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
//set the content pane, we'll add everything to it and then add it to the frame
JPanel contentPane = new JPanel();
contentPane.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
contentPane.setLayout(new GridBagLayout());
//creates some panels with some default values for now
JPanel jpCards = new JPanel(new BorderLayout());
jpCards.setOpaque(true); //ensures it paints every pixel
jpCards.setBackground(Color.BLUE);
JPanel jpInfo = new JPanel();
jpInfo.setOpaque(true);
jpInfo.setBackground(Color.GREEN);
JPanel jpPack = new JPanel(new GridBagLayout());
jpPack.setOpaque(true);
jpPack.setBackground(Color.RED);
//grab some info to make the JTextPane and make it scroll
this.client = client;
tf = new TextField();
doc = new DefaultStyledDocument();
tp = new JTextPane(doc);
tp.setEditable(false);
tf.addActionListener(this.client);
sp = new JScrollPane(tp);
//adding the quantities to the chat panel
JPanel jpChat = new JPanel();
jpChat.setLayout(new BorderLayout());
jpChat.add("North", tf);
jpChat.add("Center", sp);
//a new GridBagConstraints used to set the properties/location of the panels
GridBagConstraints c = new GridBagConstraints();
//adding some panels to the content pane
//set it to start from the top left of the quadrant if it's too small
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.fill = GridBagConstraints.BOTH; //set it to fill both vertically and horizontally
c.gridx = 0; //set it to quadrant x=0 and
c.gridy = 0; //set it to quadrant y=0
c.weightx = 0.7;
c.weighty = 0.3;
contentPane.add(jpCards, c);
c.gridx = 1;
c.gridy = 0;
c.weightx = 0.3;
c.weighty = 0.3;
contentPane.add(jpInfo, c);
c.gridx = 0;
c.gridy = 1;
c.weightx = 0.7;
c.weighty = 0.7;
contentPane.add(jpPack, c);
c.gridx = 1;
c.gridy = 1;
c.weightx = 0.3;
c.weighty = 0.7;
contentPane.add(jpChat, c);
//set some necessary values
frame.setContentPane(contentPane);
frame.setLocationByPlatform(true);
frame.setVisible(true);
//This code works for adding an Image
//need to learn how to specify a path not dependent on the specific users's machine
//this is not a high priority for now though
GridBagConstraints d = new GridBagConstraints();
d.gridx = 0;
d.gridy = 0;
ImageLabel imageLabel1 = new ImageLabel("path-to-file");
imageLabel1.setPreferredSize(new Dimension(223, 310));
jpPack.add(imageLabel1, d);
ImageLabel imageLabel2 = new ImageLabel("path-to-file");
imageLabel2.setPreferredSize(new Dimension(223, 310));
ImageLabel imageLabel3 = new ImageLabel("path-to-file");
imageLabel3.setPreferredSize(new Dimension(223, 310));
d.gridx = 1;
jpPack.add(imageLabel2, d);
d.gridy = 1;
jpPack.add(imageLabel3, d);
imageLabel1.addMouseListener(this);
imageLabel2.addMouseListener(this);
imageLabel3.addMouseListener(this);
//223, 310 are the aspect values for a card image, width, height
//these need to be maintained as the GUI size changes
}
}
class ImageLabel extends JLabel {
Image image;
ImageObserver imageObserver;
// constructor with filename
ImageLabel(String filename) {
ImageIcon icon = new ImageIcon(filename);
image = icon.getImage();
imageObserver = icon.getImageObserver();
}
// constructor with icon
ImageLabel(ImageIcon icon) {
image = icon.getImage();
imageObserver = icon.getImageObserver();
}
// overload setIcon method
void setIcon(ImageIcon icon) {
image = icon.getImage();
imageObserver = icon.getImageObserver();
}
// overload paint()
public void paint( Graphics g ) {
super.paint( g );
g.drawImage(image, 0 , 0 , getWidth() , getHeight() , imageObserver);
}
}
For some reason, there's no default resizing property for the frame's components, so when the frame resizes, the components don't do anything. I'm not sure what I'm doing wrong or missed, but clearly I left something out.
Also, if anyone knows, the ImageLabels are taking up extra space around them. The padding is set to 0 by default, so I'm not sure why it's creating like a border around them.
Thanks.
EDIT for Guillaume:
I know a main is necessary if I want to run it as a standalone, it's currently part of another application and gets called separately from within it. It was probably not the best decision to post it without a main for completeness, but whatever, it can't be that big of a problem.
Your code took out the portion where the picture was actually displayed. "path-to-file" was supposed to be replaced by an actual image file path, so you would display the image. It's hard to actually see the issue at hand when it's simply text in there.
When you have the image displayed correctly, and you try to resize the entire GUI, you will notice that the image doesn't shrink. It keeps to its preferred size and has issues when it becomes smaller than it. In my code, it stops displaying the picture completely when it can't display at least the preferred size. In your code, it cuts off part of the picture when it shrinks.
What I want is for it to actually resize the JLabel containing the picture, so that as the GUI resizes, so will the image. It's necessary that the image shrinks accordingly for my program. The user will eventually have functionality based on clicking the images, so displaying only some images or portions of them simply won't do.
Please try your code/my code again and reproduce the issue I'm having, testing with pictures, so that we can find a correct solution. Thanks.
JFrame.setVisible(true) should be the last line you call.
GridBagLayout can adapt the size of your components according to the frame size, as long as you use weightx/weighty and fill
UPDATE:
Forget about setting preferred size, this is just going down the path to GUI-problems
If you use LayoutManager's (and it is a very good idea), forget about calling setSize()/setBounds()/setLocation(), the LayoutManager's will override them anyway
You need to take care of the resizing of the image in order to maintain the original image ratio
If you use weightx/weighty, you should also use anchor and/or fill
Use frame.pack() to size properly your frame
Use setExtendedState() to maximize a frame
Btw, an SSCCE means that you make a runnable example for others, this includes changing local path to images to online URL's (see the example below).
With the following snippet, everything seems to work ok:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.TextField;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyledDocument;
public class DraftGUI implements MouseListener {
private static final String IMAGE_URL = "http://images.paramountbusinessjets.com/space/spaceshuttle.jpg";
private JPanel jpPack;
private JPanel jpCards;
private JPanel jpInfo;
private JPanel jpChat;
private TextField tf;
private StyledDocument doc;
private JTextPane tp;
private JScrollPane sp;
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
public DraftGUI() throws MalformedURLException {
final JFrame frame = new JFrame("Draft");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// set the content pane, we'll add everything to it and then add it to the frame
JPanel contentPane = new JPanel();
contentPane.setLayout(new GridBagLayout());
// creates some panels with some default values for now
JPanel jpCards = new JPanel(new BorderLayout());
jpCards.setBackground(Color.BLUE);
JPanel jpInfo = new JPanel();
jpInfo.setBackground(Color.GREEN);
JPanel jpPack = new JPanel(new GridBagLayout());
jpPack.setBackground(Color.RED);
// grab some info to make the JTextPane and make it scroll
tf = new TextField();
doc = new DefaultStyledDocument();
tp = new JTextPane(doc);
tp.setEditable(false);
sp = new JScrollPane(tp);
// adding the quantities to the chat panel
JPanel jpChat = new JPanel();
jpChat.setLayout(new BorderLayout());
jpChat.add("North", tf);
jpChat.add("Center", sp);
// a new GridBagConstraints used to set the properties/location of the panels
GridBagConstraints c = new GridBagConstraints();
// adding some panels to the content pane
// set it to start from the top left of the quadrant if it's too small
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.fill = GridBagConstraints.BOTH; // set it to fill both vertically and horizontally
c.gridx = 0; // set it to quadrant x=0 and
c.gridy = 0; // set it to quadrant y=0
c.weightx = 0.7;
c.weighty = 0.3;
contentPane.add(jpCards, c);
c.gridx = 1;
c.gridy = 0;
c.weightx = 0.3;
c.weighty = 0.3;
contentPane.add(jpInfo, c);
c.gridx = 0;
c.gridy = 1;
c.weightx = 0.7;
c.weighty = 0.7;
contentPane.add(jpPack, c);
c.gridx = 1;
c.gridy = 1;
c.weightx = 0.3;
c.weighty = 0.7;
contentPane.add(jpChat, c);
// set some necessary values
frame.setContentPane(contentPane);
frame.setLocationByPlatform(true);
// This code works for adding an Image
// need to learn how to specify a path not dependent on the specific users's machine
// this is not a high priority for now though
GridBagConstraints d = new GridBagConstraints();
d.weightx = 1.0;
d.weighty = 1.0;
d.fill = GridBagConstraints.BOTH;
d.gridx = 0;
d.gridy = 0;
ImageLabel imageLabel1 = new ImageLabel(new ImageIcon(new URL(IMAGE_URL)));
jpPack.add(imageLabel1, d);
ImageLabel imageLabel2 = new ImageLabel(new ImageIcon(new URL(IMAGE_URL)));
d.gridx++;
jpPack.add(imageLabel2, d);
ImageLabel imageLabel3 = new ImageLabel(new ImageIcon(new URL(IMAGE_URL)));
d.gridy++;
jpPack.add(imageLabel3, d);
imageLabel1.addMouseListener(this);
imageLabel2.addMouseListener(this);
imageLabel3.addMouseListener(this);
frame.pack();
// 223, 310 are the aspect values for a card image, width, height
// these need to be maintained as the GUI size changes
frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new DraftGUI();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
});
}
public static class ImageLabel extends JPanel {
private static int counter = 1;
private ImageIcon icon;
private int id = counter++;
public ImageLabel(ImageIcon icon) {
super();
setOpaque(false);
this.icon = icon;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(icon.getIconWidth(), icon.getIconHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
double zoom = Math.min((double) getWidth() / icon.getIconWidth(), (double) getHeight() / icon.getIconHeight());
int width = (int) (zoom * icon.getIconWidth());
int height = (int) (zoom * icon.getIconHeight());
g.drawImage(icon.getImage(), (getWidth() - width) / 2, (getHeight() - height) / 2, width, height, this);
g.setFont(g.getFont().deriveFont(36.0f));
g.drawString(String.valueOf(id), getWidth() / 2, getHeight() / 2);
}
}
}
I suggest this way to resize the contents of a window
JPanel jPanel = new JPanel(new BorderLayout()); // Create a panel that contains the elements you want to resize, in this example I use BorderLayout as the layout manager
jPanel.add(somePanel, BorderLayout.NORTH);
// this will resize the con
this.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
somePanel.setSize(e.getComponent().getSize());
jPanel.paintComponents(getGraphics());
}
});
Related
I've got this list of JPanels and I'd like to save them without displaying them
make Jpanel -> Save it(without displaying it)
I tried using BufferedImage and painting it but the image returned is always black, the method I used for that is "save" and is displayed in the code below.
I'd like to know how to do fix this problem.
EDIT:
#camickr thanks to your suggestion and this thread
Why does the JTable header not appear in the image?
I was able to fix the problem, here is the fixed code:
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class Solution extends JFrame
{
int i;
ArrayList <Individual> AKA;
Container jgraph;
JButton gauche;
JButton droite;
JMenuBar barre;
JMenu fichier;
JMenuItem enregistrer;
JPanel jpgenerale ;
Solution current;
Component middle;
public Solution(ArrayList <Individual> graph) throws HeadlessException
{
setDefaultCloseOperation(EXIT_ON_CLOSE);
barre = new JMenuBar();
fichier = new JMenu("Fichier");
enregistrer = new JMenuItem("Enregistrer");
enregistrer.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK));
fichier.add(enregistrer);
barre.add(fichier);
AKA = graph;
current = this;
gauche = new JButton("Gauche");
droite = new JButton("Droite");
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.PAGE_END;
c.gridx = 1;
c.gridy = 2;
gauche.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(java.awt.event.ActionEvent e)
{
i = (AKA.size() + (i - 1)) % AKA.size();
jpgenerale.removeAll();
jpgenerale.validate();
jpgenerale.add(AKA.get(i).chopper.getContentPane());
jpgenerale.revalidate();
jpgenerale.repaint();
}
});
getContentPane().add(gauche, c);
c.gridx = 3;
c.gridy = 2;
droite.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(java.awt.event.ActionEvent e)
{
i = (i+1)% AKA.size();
jpgenerale.removeAll();
jpgenerale.validate();
jpgenerale.add(AKA.get(i).chopper.getContentPane());
jpgenerale.revalidate();
jpgenerale.repaint();
}
});
getContentPane().add(droite, c);
jpgenerale = new JPanel();
c.anchor = GridBagConstraints.CENTER;
jpgenerale.setLayout(new BoxLayout(jpgenerale,BoxLayout.LINE_AXIS));
jpgenerale.setPreferredSize(new Dimension(400, 400));
jpgenerale.add(AKA.get(0).chopper.getContentPane());
c.ipady = 40;
c.gridx = 2;
c.gridy = 1;
getContentPane().add(jpgenerale,c);
setTitle("AGPM");// le titre on va change plutard
setSize(600,600);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
middle = AKA.get(0).chopper.getContentPane();
scan(middle);
middle = AKA.get(1).chopper.getContentPane();
scan(middle);
}
private static void scan(Component pan1)
{
JPanel temp = new JPanel();
temp.setBackground(Color.WHITE);//so that the image and JPanel background are unified
temp.setPreferredSize(new Dimension(400, 400));
temp.add(pan1);
BufferedImage bi = ScreenImage.createImage(temp);
try {
ScreenImage.writeImage(bi, "image.png");
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
I edited the thread's title so that it's clearer, if you have any suggestion they're welcomed.
Thanks again everyone:)
If the component hasn't been added to the visible frame, then the size of the component is (0, 0) so there is nothing to paint. Also, the components haven't been positioned on the panel since the layout manager hasn't been invoked.
So you first need to:
set the size of the component equal to the preferred size
invoke doLayout() on the component
Or, you can check out Screen Image which does the above for you and can be used to create an image of any component.
I am making authentication GUI which should contain 2 text fields, username JTextField and password JPasswordField. I want to make the password field be below the username field. my current code is as follows:
public class GuiAuthentication extends JFrame {
private static final int WIDTH = 1000;
private static final int HEIGHT = 650;
private JTextField tfUsername;
private JPasswordField tfPassword;
public GuiAuthentication() {
try {
setTitle("Metaspace Launcher");
getContentPane().setLayout(new FlowLayout());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(WIDTH, HEIGHT);
tfUsername = new JTextField("Username");
tfPassword = new JPasswordField("********");
tfUsername.setBounds(10, 10, 50, 20);
tfPassword.setBounds(10, 50, 50, 20);
getContentPane().add(tfUsername);
getContentPane().add(tfPassword);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setMinimumSize (new Dimension(WIDTH, HEIGHT));
setMaximumSize (new Dimension(WIDTH, HEIGHT));
setResizable(false);
requestFocus();
setLocationRelativeTo(null);
setVisible(true);
} catch (final Exception ex) {
ex.printStackTrace();
System.exit(ex.toString().hashCode());
}
}
#Override
public void paint(final Graphics g) {
super.paint(g);
Gui.drawBackground(this, g, WIDTH, HEIGHT);
Gui.drawRect(g, WIDTH/3, HEIGHT/3 + 20, 325, 200, 0xAA000000);
}
However, this results in the password field being located against the username field, and both of them are centered, and not located at X position 10 which I specify:
--> Screenshot (click)
Is the problem in the layout I currently use (FlowLayout)? If so, which one should I use then? If not, what else might be wrong?
Tried using GridBagLayout as well. It results in this (fields side by side, centered):
Your GridBagLayout attempt images suggest that either you're not using GridBagConstraints when adding components or that you're using the incorrectly.
If you want to center your text components in the GUI, one over the other, and say put them in their own box, then use a GridBagLayout for the container that holds them, and also pass in appropriate GridBagConstraints that will work well with your desire. This will mean giving the constraints an appropriate gridx and gridy value to match where in the grid you wish to place the component. Also you will want to anchor the component correctly, and you will usually want to set the constraints insets to give an empty space buffer around your components so that they don't crowd each other. Myself, when I do something like this, I often use a 4 x 4 grid with two rows and two columns including a column of JLabels on the left so the user knows what each text component in the right column represents. I often use a helper method to help create my constraints, something like this:
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.fill = GridBagConstraints.HORIZONTAL; // stretch components horizontally
gbc.weightx = 1.0;
gbc.weighty = 0.0; // increase if you want component location to stretch vert.
// I_GAP is a constant and is the size of the gap around
// each component
gbc.insets = new Insets(I_GAP, I_GAP, I_GAP, I_GAP);
// if the x value is odd, anchor to the left, otherwise if even to the right
gbc.anchor = x % 2 == 0 ? GridBagConstraints.WEST : GridBagConstraints.EAST;
return gbc;
}
And then I'd use it like this:
JPanel innerPanel = new JPanel(new GridBagLayout());
JLabel userNameLabel = new JLabel("User Name:");
userNameLabel.setForeground(Color.LIGHT_GRAY);
innerPanel.add(userNameLabel, createGbc(0, 0)); // add w/ GBC
innerPanel.add(tfUsername, createGbc(1, 0)); // etc...
JLabel passwordLabel = new JLabel("Password:");
passwordLabel.setForeground(Color.LIGHT_GRAY);
innerPanel.add(passwordLabel, createGbc(0, 1));
innerPanel.add(tfPassword, createGbc(1, 1));
A working example could look like so:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
#SuppressWarnings("serial")
public class MetaSpaceLauncherPanel extends JPanel {
// path to a public starry image
public static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia/"
+ "commons/thumb/b/be/Milky_Way_at_Concordia_Camp%2C_Karakoram_Range%2"
+ "C_Pakistan.jpg/1280px-Milky_Way_at_Concordia_Camp%2C_Karakoram_Range"
+ "%2C_Pakistan.jpg";
private static final int I_GAP = 10;
private static final int COLS = 15;
private JTextField tfUsername = new JTextField(COLS);
private JPasswordField tfPassword = new JPasswordField(COLS);
private BufferedImage background = null;
public MetaSpaceLauncherPanel(BufferedImage background) {
this.background = background;
// close window if enter pressed and data within fields
ActionListener listener = e -> {
String userName = tfUsername.getText().trim();
char[] password = tfPassword.getPassword();
Window window = SwingUtilities.getWindowAncestor(MetaSpaceLauncherPanel.this);
if (userName.isEmpty() || password.length == 0) {
// both fields need to be filled!
String message = "Both user name and password fields must contain data";
String title = "Invalid Data Entry";
JOptionPane.showMessageDialog(window, message, title, JOptionPane.ERROR_MESSAGE);
} else {
// simply close the dialog
window.dispose();
}
};
tfUsername.addActionListener(listener);
tfPassword.addActionListener(listener);
JPanel innerPanel = new JPanel(new GridBagLayout());
innerPanel.setOpaque(false);
Border outerBorder = BorderFactory.createEtchedBorder();
Border innerBorder = BorderFactory.createEmptyBorder(I_GAP, I_GAP, I_GAP, I_GAP);
Border border = BorderFactory.createCompoundBorder(outerBorder, innerBorder);
innerPanel.setBorder(border);
JLabel userNameLabel = new JLabel("User Name:");
userNameLabel.setForeground(Color.LIGHT_GRAY);
innerPanel.add(userNameLabel, createGbc(0, 0));
innerPanel.add(tfUsername, createGbc(1, 0));
JLabel passwordLabel = new JLabel("Password:");
passwordLabel.setForeground(Color.LIGHT_GRAY);
innerPanel.add(passwordLabel, createGbc(0, 1));
innerPanel.add(tfPassword, createGbc(1, 1));
setLayout(new GridBagLayout());
add(innerPanel); // add without constraints to center it
}
public String getUserName() {
return tfUsername.getText();
}
public char[] getPassword() {
return tfPassword.getPassword();
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.fill = GridBagConstraints.HORIZONTAL; // stretch components horizontally
gbc.weightx = 1.0;
gbc.weighty = 0.0; // increase if you want component location to stretch vert.
// I_GAP is a constant and is the size of the gap around
// each component
gbc.insets = new Insets(I_GAP, I_GAP, I_GAP, I_GAP);
// if the x value is odd, anchor to the left, otherwise if even to the right
gbc.anchor = x % 2 == 0 ? GridBagConstraints.WEST : GridBagConstraints.EAST;
return gbc;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
g.drawImage(background, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || background == null) {
return super.getPreferredSize();
}
int w = background.getWidth();
int h = background.getHeight();
return new Dimension(w, h);
}
private static void createAndShowGui() {
BufferedImage img = null;
try {
// just using this as an example image, one available to all
// you would probably use your own image
URL imgUrl = new URL(IMG_PATH); // online path to starry image
img = ImageIO.read(imgUrl);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1); // no image available -- exit!
}
MetaSpaceLauncherPanel launcherPanel = new MetaSpaceLauncherPanel(img);
JDialog dialog = new JDialog(null, "MetaSpace Launcher", ModalityType.APPLICATION_MODAL);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.getContentPane().add(launcherPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
// test to see if we can get the data
String userName = launcherPanel.getUserName();
char[] password = launcherPanel.getPassword();
// don't convert password into String as I'm doing below as it is now
// not secure
String message = String.format("<html>User Name: %s<br/>Password: %s</html>", userName,
new String(password));
JOptionPane.showMessageDialog(null, message);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
For some reason my borders aren't showing for my panels and i am unsure why, is there something i'm missing?
I have a main class which runs the frame class as well as other classes separate to the GUI
This is the code from my frame class:
import javax.swing.*;
import java.awt.*;
public class Frame
{
public static int xsize;
public static int ysize;
public static void main()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new MainFrame("Warlock of Firetop Mountain");
//Implementing Toolkit to allow computer to get dimensions of screen and assign them to two int values
Toolkit tk = Toolkit.getDefaultToolkit();
Frame.xsize = (int) tk.getScreenSize().getWidth();
Frame.ysize = (int) tk.getScreenSize().getHeight();
frame.setTitle("Warlock of Firetop Mountain");
frame.setSize(new Dimension(xsize, ysize));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
The frame.java takes its panels from MainFrame.java:
import javax.swing.*;
import java.awt.*;
public class MainFrame extends JFrame
{
private Panel1 storyPanel;
private Panel2 statsPanel;
private Panel3 commandsPanel;
public MainFrame(String title)
{
super(title);
// Setting Layout
setLayout(new BorderLayout());
storyPanel = new Panel1();
statsPanel = new Panel2();
commandsPanel = new Panel3();
Container p = getContentPane();
p.add(storyPanel, BorderLayout.WEST);
p.add(statsPanel, BorderLayout.EAST);
p.add(commandsPanel, BorderLayout.SOUTH);
}
}
This calls up my three panels which look like this:
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Dimension;
import java.awt.Color;
public class Panel1 extends JPanel
{
public Panel1()
{
//Set size of Panel1
int xsizeP1 = (Frame.xsize / 2);
int ysizeP1 = (Frame.ysize / 3 * 2);
setPreferredSize(new Dimension(xsizeP1, ysizeP1));
setBorder(BorderFactory.createLineBorder(Color.black));
}
}
when the code runs the window launches as full screen but no borders or possibly panels are visible.
Thanks for any help, sorry if my questions are tedious, i'm relatively new to programming.
This is roughly what i want my panels to look like, eventually ill add in components to the panel and use GridBagConstraints to control the formatting
// this creates the JPanels and sets their preferred sizes
JFrame frame = new MainFrame("Warlock of Firetop Mountain");
//this sets your size static contents -- after the above's been done!
Toolkit tk = Toolkit.getDefaultToolkit();
Frame.xsize = (int) tk.getScreenSize().getWidth();
Frame.ysize = (int) tk.getScreenSize().getHeight();
You're setting preferred sizes of all your JPanels to 0, 0, and so you're not seeing any borders. Your sizing is being created after you've created your JPanels, and this method of sizing looks dangerous to me.
OK, thanks for posting an image of the desired GUI. My recommendations are:
First and foremost, don't try setting sizes as you're doing.
Instead, let the components and their layout managers size themselves.
Nest JPanels, each using its own layout manager to allow you to simply create complex GUI's.
When displaying images / ImageIcons, let them set the sizes of things as well.
If your GUI starts up with no icons displaying, consider creating a blank ImageIcon with a blank image of the right size as a placeholder icon.
For example, something like this:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
#SuppressWarnings("serial")
public class TomGuiPanel extends JPanel {
// rows and cols for jtextarea
private static final int CURRENT_AREA_ROWS = 20;
private static final int CURRENT_AREA_COLS = 40;
// columns for command jtextfied
private static final int COMMANDS_FIELD_COLS = 50;
// size of GUI component gaps
private static final int EB_GAP = 3;
private static final int NUMBER_OF_OPTIONS = 5;
// number if ImageIcons displayed within the user image char JList
private static final int CHAR_IMG_VISIBLE_ROWS = 5;
// a guess of the width of the largest image icon in the JList
// You'd use a different number
private static final int USER_IMG_CHAR_IMG_WIDTH = 70;
private JTextArea currentTextArea = new JTextArea(CURRENT_AREA_ROWS, CURRENT_AREA_COLS);
private JTextField commandsField = new JTextField(COMMANDS_FIELD_COLS);
private EnterAction enterAction = new EnterAction("Enter");
private DefaultListModel<Icon> charImgListModel = new DefaultListModel<>();
private JList<Icon> charImgList = new JList<>(charImgListModel);
public TomGuiPanel() {
JPanel topBtnPanel = new JPanel(new GridLayout(1, 0, EB_GAP, EB_GAP));
String[] btnTexts = { "Inventory", "Options", "Save", "Load" };
for (String txt : btnTexts) {
topBtnPanel.add(new JButton(txt));
}
JPanel characteristicsPanel = new JPanel(new GridBagLayout());
addCharacteristics(characteristicsPanel, "HP", 20, 0);
addCharacteristics(characteristicsPanel, "Attack", 12, 1);
addCharacteristics(characteristicsPanel, "Defence", 8, 2);
addCharacteristics(characteristicsPanel, "Agility", 9, 3);
addCharacteristics(characteristicsPanel, "Luck", 2, 4);
JScrollPane imgListPane = new JScrollPane(charImgList);
imgListPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
charImgList.setVisibleRowCount(CHAR_IMG_VISIBLE_ROWS);
charImgList.setPrototypeCellValue(createProtoType());
JPanel rightPanel = new JPanel(new BorderLayout(EB_GAP, EB_GAP));
rightPanel.add(topBtnPanel, BorderLayout.PAGE_START);
rightPanel.add(imgListPane, BorderLayout.CENTER);
rightPanel.add(characteristicsPanel, BorderLayout.LINE_END);
JPanel optionsPanel = new JPanel(new GridLayout(1, 0));
for (int i = 0; i < NUMBER_OF_OPTIONS; i++) {
String text = "Option " + (i + 1);
optionsPanel.add(new JCheckBox(text));
}
currentTextArea.setWrapStyleWord(true);
currentTextArea.setLineWrap(true);
currentTextArea.setFocusable(false);
JScrollPane taScrollPane = new JScrollPane(currentTextArea);
taScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(taScrollPane, BorderLayout.CENTER);
centerPanel.add(rightPanel, BorderLayout.LINE_END);
centerPanel.add(optionsPanel, BorderLayout.PAGE_END);
JPanel commandsPanel = new JPanel();
commandsPanel.setLayout(new BoxLayout(commandsPanel, BoxLayout.LINE_AXIS));
commandsPanel.add(commandsField);
commandsPanel.add(Box.createHorizontalStrut(EB_GAP));
commandsPanel.add(new JButton(enterAction));
commandsPanel.add(Box.createHorizontalStrut(EB_GAP));
commandsPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));
commandsField.setAction(enterAction); // use same action for button and
// text field
setBorder(BorderFactory.createEmptyBorder(EB_GAP, EB_GAP, EB_GAP, EB_GAP));
setLayout(new BorderLayout(EB_GAP, EB_GAP));
add(centerPanel, BorderLayout.CENTER);
add(commandsPanel, BorderLayout.PAGE_END);
}
private void addCharacteristics(JPanel cPanel, String text, int value, int row) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = row;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.weightx = 1.0;
gbc.weighty = 0.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.WEST;
cPanel.add(new JLabel(text), gbc);
gbc.insets.left = 20;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 1;
cPanel.add(new JLabel(String.valueOf(value)), gbc);
}
private Icon createProtoType() {
int w = USER_IMG_CHAR_IMG_WIDTH;
int h = w;
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Icon icon = new ImageIcon(img);
return icon;
}
private class EnterAction extends AbstractAction {
public EnterAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
String text = commandsField.getText();
currentTextArea.append(text + "\n");
commandsField.selectAll();
}
}
private class ExitAction extends AbstractAction {
public ExitAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
Component source = (Component) e.getSource();
Window win = SwingUtilities.getWindowAncestor(source);
win.dispose();
}
}
private static void createAndShowGUI() {
TomGuiPanel mainPanel = new TomGuiPanel();
JFrame frame = new JFrame("Tom's GUI");
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(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Would create this realizable GUI:
Note that the GUI is roughly made, has no functionality other than the enter and exit buttons.
I'm trying to create a GUI for a personal project. I have a file chooser, a console area, a text field (with label), a button panel(2 buttons) and finally a "drop zone" area.
The GUI is divided vertically in half with the console on the right.
On the UpperLeft I have FileChooser positioned at BorderLayout.CENTER, followed by the ButtonPanel at BorderLayout.SOUTH.
Below that is the "drop zone"
It currently looks something like this:
_________________
| file | console|
| chooser| |
| buttons| |
|--------| |
| drop | |
| zone | |
|________|________|
I want to add a new text field between the file chooser and the button panel, but when I change file chooser to NORTH, jtextfield to CENTER and buttons to SOUTH, the file chooser is weirdly small and the jtextfield is much to large. I think this is just due to the inherent properties of BorderLayout, but I am not sure. Should I use a different Layout and what kind of changes would I make?
I've included the code I'm working with below. Thank you for any help in advance!
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.io.*;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.text.*;
import java.util.*;
import java.nio.*;
public class ConsolidatorDemo extends JPanel implements ActionListener {
JFileChooser fc;
JButton clear;
JButton ok;
JTextArea console;
JList<File> dropZone;
DefaultListModel listModel;
JSplitPane childSplitPane, parentSplitPane;
PrintStream ps;
JTextField wordCount;
JLabel lblCount;
public ConsolidatorDemo() {
super(new BorderLayout());
fc = new JFileChooser();;
fc.setMultiSelectionEnabled(true);
fc.setDragEnabled(true);
fc.setControlButtonsAreShown(false);
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
JPanel fcPanel = new JPanel(new BorderLayout());
fcPanel.add(fc, BorderLayout.CENTER);
clear = new JButton("Clear All");
clear.addActionListener(this);
JPanel buttonPanel = new JPanel(new BorderLayout());
buttonPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
buttonPanel.add(clear, BorderLayout.LINE_END);
ok = new JButton("OK");
ok.addActionListener(this);
buttonPanel.add(ok, BorderLayout.WEST);
JPanel sizePanel = new JPanel(new BorderLayout());
sizePanel.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
wordCount = new JTextField();
sizePanel.add(wordCount, BorderLayout.LINE_END);
// lblCount = new JLabel("Word Counter");
// buttonPanel.add(lblCount, BorderLayout.CENTER);
JPanel leftUpperPanel = new JPanel(new BorderLayout());
leftUpperPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
leftUpperPanel.add(fcPanel, BorderLayout.NORTH);
leftUpperPanel.add(sizePanel, BorderLayout.CENTER);
leftUpperPanel.add(buttonPanel, BorderLayout.PAGE_END);
JScrollPane leftLowerPanel = new javax.swing.JScrollPane();
leftLowerPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
listModel = new DefaultListModel();
dropZone = new JList(listModel);
dropZone.setCellRenderer(new FileCellRenderer());
dropZone.setTransferHandler(new ListTransferHandler(dropZone));
dropZone.setDragEnabled(true);
dropZone.setDropMode(javax.swing.DropMode.INSERT);
dropZone.setBorder(new TitledBorder("Selected files/folders"));
leftLowerPanel.setViewportView(new JScrollPane(dropZone));
childSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
leftUpperPanel, leftLowerPanel);
childSplitPane.setDividerLocation(400);
childSplitPane.setPreferredSize(new Dimension(480, 650));
console = new JTextArea();
console.setColumns(40);
console.setLineWrap(true);
console.setBorder(new TitledBorder("Console"));
parentSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
childSplitPane, console);
parentSplitPane.setDividerLocation(480);
parentSplitPane.setPreferredSize(new Dimension(800, 650));
add(parentSplitPane, BorderLayout.CENTER);
this.redirectSystemStreams();
}
private void updateTextArea(final String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
console.append(text);
}
});
}
private void redirectSystemStreams() {
OutputStream out = new OutputStream() {
#Override
public void write(int b) throws IOException {
updateTextArea(String.valueOf((char) b));
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
updateTextArea(new String(b, off, len));
}
#Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
};
System.setOut(new PrintStream(out, true));
System.setErr(new PrintStream(out, true));
}
public void setDefaultButton() {
getRootPane().setDefaultButton(ok);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == clear) {
listModel.clear();
}
if(e.getSource() == ok){
try{
if(dropZone.isSelectionEmpty() == true){
int start = 0;
int end = dropZone.getModel().getSize() - 1;
if (end >= 0) {
dropZone.setSelectionInterval(start, end);
}
}
List<File> list = dropZone.getSelectedValuesList();
for (File file : list) {
//StringEditing.editDocument(file, Integer.parseInt(wordCount.getText()));
}
}
catch(NumberFormatException nfe){
System.out.println("You did not input a number");
}
catch(Exception ef){
System.out.println("Something is wrong!");
}
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
try {
//UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel");
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}catch (Exception e){
e.printStackTrace();
}
//Create and set up the window.
JFrame frame = new JFrame("Consolidator!");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//Create and set up the menu bar and content pane.
ConsolidatorDemo demo = new ConsolidatorDemo();
demo.setOpaque(true); //content panes must be opaque
frame.setContentPane(demo);
//Display the window.
frame.pack();
frame.setVisible(true);
demo.setDefaultButton();
}
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() {
createAndShowGUI();
}
});
}
}
class FileCellRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(
list,value,index,isSelected,cellHasFocus);
if (c instanceof JLabel && value instanceof File) {
JLabel l = (JLabel)c;
File f = (File)value;
l.setIcon(FileSystemView.getFileSystemView().getSystemIcon(f));
l.setText(f.getName());
l.setToolTipText(f.getAbsolutePath());
}
return c;
}
}
class ListTransferHandler extends TransferHandler {
private JList list;
ListTransferHandler(JList list) {
this.list = list;
}
#Override
public boolean canImport(TransferHandler.TransferSupport info) {
// we only import FileList
if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
return true;
}
#Override
public boolean importData(TransferHandler.TransferSupport info) {
if (!info.isDrop()) {
return false;
}
// Check for FileList flavor
if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
displayDropLocation("List doesn't accept a drop of this type.");
return false;
}
// Get the fileList that is being dropped.
Transferable t = info.getTransferable();
List<File> data;
try {
data = (List<File>)t.getTransferData(DataFlavor.javaFileListFlavor);
}
catch (Exception e) { return false; }
DefaultListModel model = (DefaultListModel) list.getModel();
for (Object file : data) {
model.addElement((File)file);
}
return true;
}
private void displayDropLocation(String string) {
System.out.println(string);
}
}
I ended up using GridBagLayout using the various answers here, thank you for your help!
I've got a ton of extra/ unused stuff in this example, mostly because I was starting to implement the functions I needed when I figured I'd post an update here. Should still compile and run fine though.
One problem I have is that the GUI spawns with the button panel / drop zone divider sort of eating into each other. On top of that, there is a text field which has no width despite it working perfectly fine before I used the split panes. If anyone had any knowledge of how to get around these bugs I'd appreciate it!
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.io.*;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.text.*;
import java.util.*;
import java.nio.*;
public class TestGridBagLayout {
final static boolean shouldFill = true;
final static boolean shouldWeightX = true;
final static boolean RIGHT_TO_LEFT = false;
public static void addComponentsToPane(Container pane) {
if (RIGHT_TO_LEFT) {
pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}
JButton clear;
JButton ok;
JLabel num;
JTextField input;
JSplitPane childSplitPane, parentSplitPane;
PrintStream ps;
JTextArea console;
JList<File> dropZone;
DefaultListModel listModel;
pane.setLayout(new GridBagLayout());
JPanel leftUpperPanel = new JPanel(new GridBagLayout());
leftUpperPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
GridBagConstraints c = new GridBagConstraints();
if (shouldFill) {
//natural height, maximum width
c.fill = GridBagConstraints.HORIZONTAL;
}
JFileChooser fc = new JFileChooser();;
fc.setMultiSelectionEnabled(true);
fc.setDragEnabled(true);
fc.setControlButtonsAreShown(false);
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 40; //make this component tall
c.weightx = 0.0;
c.gridwidth = 4;
c.gridx = 0;
c.gridy = 1;
leftUpperPanel.add(fc, c);
ok = new JButton("OK");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 0; //reset to default
c.anchor = GridBagConstraints.PAGE_END; //bottom of space
c.insets = new Insets(10,0,0,0); //top padding
c.weightx = 0.5;
c.gridx = 0; //aligned with button 2
c.gridwidth = 1;
c.gridy = 2; //third row
leftUpperPanel.add(ok, c);
num = new JLabel("Word Count:");
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.PAGE_END;
c.insets = new Insets(10,0,0,0); //top padding
c.weightx = 0.25;
c.gridx = 1;
c.gridy = 2;
leftUpperPanel.add(num, c);
input = new JTextField("", 50);
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.PAGE_END;
c.insets = new Insets(10,0,0,0); //top padding
c.weightx = 0.25;
c.gridx = 2;
c.gridy = 2;
leftUpperPanel.add(input, c);
clear = new JButton("Clear All");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 0;
c.anchor = GridBagConstraints.PAGE_END;
c.insets = new Insets(10,0,0,0); //top padding
c.weightx = 0.5;
c.gridx = 3;
c.gridy = 2;
leftUpperPanel.add(clear, c);
JScrollPane leftLowerPanel = new javax.swing.JScrollPane();
leftLowerPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
listModel = new DefaultListModel();
dropZone = new JList(listModel);
dropZone.setCellRenderer(new FileCellRenderer());
dropZone.setTransferHandler(new ListTransferHandler(dropZone));
dropZone.setDragEnabled(true);
dropZone.setDropMode(javax.swing.DropMode.INSERT);
dropZone.setBorder(new TitledBorder("Selected files/folders"));
leftLowerPanel.setViewportView(new JScrollPane(dropZone));
childSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
leftUpperPanel, leftLowerPanel);
childSplitPane.setDividerLocation(400);
childSplitPane.setPreferredSize(new Dimension(480, 650));
console = new JTextArea();
console.setColumns(40);
console.setLineWrap(true);
console.setBorder(new TitledBorder("Console"));
parentSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
childSplitPane, console);
parentSplitPane.setDividerLocation(480);
parentSplitPane.setPreferredSize(new Dimension(800, 650));
pane.add(parentSplitPane);
}
public static void initUI() {
JFrame frame = new JFrame("GridBagLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TestGridBagLayout testMultiplePanels = new TestGridBagLayout();
testMultiplePanels.initUI();
}
});
}
}
You could start by using a GridLayout setup to display two columns and one row. This would start out as the primary display/container/panel for the vertical split. You would then need another JPanel, possibly with a GridLayout setup to display one column and two rows, this would display the file chooser and drop zone.
You would then add this panel and the text area to the primary panel.
You could also do this using a single GridBagLaout, but you might find using compound GridLayouts easier.
See How to Use GridLayout and How to Use GridBagLayout for more details
I would probably create a panel with BoxLayout with a y-axis orientation, and put my 'two halves' in that, and put it on the west end of the JFrame's default BoxLayout. Then I'd put the other panel in the center, assuming you want it to stretch and shrink in both directions as the user changes the window size.
For flexibility, you could use a JSplitPane having HORIZONTAL_SPLIT; put the console on the right and a nested JSplitPane having VERTICAL_SPLIT on the left to hold the fcPanel and dropZone.
I have a form with lots of text fields and some of those text fields may contain very long strings. To make it work I made those text fields scrollable using this code:
JScrollPane scroll = new JScrollPane(textField);
scroll.setPreferredSize(new Dimension((int)textField.getPreferredSize().getWidth(), (int)textField.getPreferredSize().getHeight() * 2));
Then I put scroll into my form using GridBagLayout.
Second line in my example is required for scroller to show up. But it has downside. When I resize window to fit whole text in text field, then scroll disapears leaving me with just two times higher then others text field, which looks ridiculous.
How can I make this all work and show me normal size of text field after scroller is hidden?
EDIT:
You may use following as a demo code to reproduce the issue:
import javax.swing.*;
import java.awt.*;
public class ScrollTextDemo extends JFrame{
public ScrollTextDemo(){
super();
this.setPreferredSize(new Dimension(500, 300));
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
textField.setCursor(new Cursor(0));
textField.setEditable(false);
JScrollPane scroll = new JScrollPane(textField);
scroll.setPreferredSize(new Dimension(70, 40) );
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(scroll,gbc);
//let's add one more text field without scroll bar to compare
JTextField textField2 = new JTextField("abc");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(textField2,gbc);
this.add(panel);
}
public static void main(String args[]){
ScrollTextDemo demo = new ScrollTextDemo();
demo.pack();
demo.setVisible(true);
}
}
For this , in the absence of a good SSCCE, I think you hadn't provided any constraint that goes for fill, which is used for
Used when the component's display area is larger than the component's requested size to determine whether and how to resize the component. Valid values (defined as GridBagConstraints constants) include NONE (the default), HORIZONTAL (make the component wide enough to fill its display area horizontally, but do not change its height), VERTICAL (make the component tall enough to fill its display area vertically, but do not change its width), and BOTH (make the component fill its display area entirely).
So you must add something like this to your GridBagConstraints
constraintsGridBag.fill = GridBagConstraints.HORIZONTAL;
This will only allow it to expand HORIZONTALLY not both ways.
** EDIT : As for the added code **
Never specify setPreferredSize(...) for any component in Swing. Let the Layout Manager you are using, take care for that. Remove all setPreferredSize(...) thingies, will let it remain in normal size upon resizing.
*EDIT 2 : *
Code to tell you what I am saying :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class GridBagTest extends JFrame
{
private JPanel topPanel;
private JPanel bottomPanel;
public GridBagTest()
{
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
//gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 0.8;
// Setting TOP PANEL.
topPanel = new JPanel();
topPanel.setLayout(new GridBagLayout());
GridBagConstraints constraintsTopPanel = new GridBagConstraints();
constraintsTopPanel.gridwidth = 2; // Specifies that this component will take two columns.
constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.
/*
* fill with HORIZONTAL, means the component upon resize, will
* only expand along the X-Axis.
*/
constraintsTopPanel.fill = GridBagConstraints.NONE;
constraintsTopPanel.insets = new Insets(5, 5, 5, 5);
constraintsTopPanel.ipadx = 2;
constraintsTopPanel.ipady = 2;
constraintsTopPanel.weightx = 0.3;
constraintsTopPanel.weighty = 0.2;
constraintsTopPanel.gridx = 0;
constraintsTopPanel.gridy = 0;
JTextField tfield1 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield1, constraintsTopPanel);
constraintsTopPanel.gridx = 2;
constraintsTopPanel.gridy = 0;
final JTextField tfield2 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield2, constraintsTopPanel);
constraintsTopPanel.gridx = 4;
constraintsTopPanel.gridy = 0;
JTextField tfield3 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield3, constraintsTopPanel);
topPanel.setBackground(Color.WHITE);
add(topPanel, gbc);
constraintsTopPanel.gridx = 0;
constraintsTopPanel.gridy = 2;
constraintsTopPanel.gridwidth = 6; // Specifies that this component will take two columns.
constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.
JButton button = new JButton("REMOVE");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
topPanel.remove(tfield2);
topPanel.revalidate();
topPanel.repaint();
}
});
topPanel.add(button, constraintsTopPanel);
//Setting BOTTOM PANEL.
bottomPanel = new JPanel();
bottomPanel.setLayout(new BorderLayout());
bottomPanel.setBackground(Color.DARK_GRAY);
JLabel label3 = new JLabel("I am a new JLABEL for the bottom JPanel", JLabel.CENTER);
label3.setForeground(Color.WHITE);
bottomPanel.add(label3, BorderLayout.CENTER);
gbc.weighty = 0.2;
add(bottomPanel, gbc);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
pack();
setVisible(true);
}
public static void main(String... args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new GridBagTest();
}
});
}
}
Well the best I've got is looking ugly in code, but does exactly what I need to the textField. Below is changed sample code from initial question. I'd be thankfull for any ideas how to make it better:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
public class ScrollTextDemo extends JFrame{
public ScrollTextDemo(){
super();
this.setPreferredSize(new Dimension(500, 300));
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
textField.setCursor(new Cursor(0));
textField.setEditable(false);
JScrollPane scroll = new JScrollPane(textField, JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
//gbc.ipady = 20;//gives some room for scroll to appear and don't hide text area under the scroll.
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(scroll,gbc);
//let's add one more text field without scroll bar to compare
JTextField textField2 = new JTextField("bbbbbbbb");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(textField2,gbc);
scroll.addComponentListener( new ScrollTextComponentListener(scroll, textField2));
this.add(panel);
}
public static void main(String args[]){
ScrollTextDemo demo = new ScrollTextDemo();
demo.pack();
demo.setVisible(true);
}
}
class ScrollTextComponentListener implements ComponentListener {
private boolean scrollVisible;
private JScrollPane scroll;
private JComponent compareComponent;
public ScrollTextComponentListener(JScrollPane scroll, JComponent compareComponent) {
this.scroll = scroll;
this.compareComponent = compareComponent;
}
private boolean isScrollVisible() {
return scroll.getHorizontalScrollBar().getModel().getExtent() != scroll.getHorizontalScrollBar().getModel().getMaximum();
}
private void setScrollSize(){
boolean scrollVisible = isScrollVisible();
if (scrollVisible){
scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
//also had to set both min and max sizes, because only preffered size didn't always work
scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
}
else {
scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
}
this.scrollVisible = scrollVisible;
}
#Override
public void componentResized(ComponentEvent e) {
if (isScrollVisible() != scrollVisible) setScrollSize();
}
#Override
public void componentMoved(ComponentEvent e) {
}
#Override
public void componentShown(ComponentEvent e) {
setScrollSize();
}
#Override
public void componentHidden(ComponentEvent e) {
}
}