Adding ScrollPane to BoxLayout - java

IN MY PROGRAM,
I have a button when pressed, adds a new JPanel to a JPanel with BOXLAYOUT. Since when I add the JPanel it adds it to the bottom of the previous one. BUT THERE IS NO SCROLL BAR.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
public class tes{
public static void main(String[] args) {
JFrame newL = new JFrame();
newL.setTitle("New Level Files");
//newL.setLayout(new BoxLayout());
//t.setSize(500,600);
//newL.pack();
newL.setVisible(true);
newL.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(listPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setPreferredSize(new Dimension(600, 100));
newL.add(scrollPane, BorderLayout.CENTER);
JPanel levelP = new JPanel();
levelP.setBorder(BorderFactory.createLineBorder(Color.black));
levelP.setLayout(new GridBagLayout());
GridBagConstraints l = new GridBagConstraints();
l.insets = new Insets(10,10,10,5);
JButton okForFileEdit = new JButton("Edit this File");
l.gridx = 1;
l.gridy = 6;
levelP.add(okForFileEdit, l);
okForFileEdit.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent n){
JPanel createInPanel = new JPanel();
createInPanel.setSize(200,200);
createInPanel.setBorder(BorderFactory.createLineBorder(Color.black));
createInPanel.setLayout(new GridBagLayout());
listPane.add(createInPanel);
JLabel yout = new JLabel("YEah this is a long sentence to see the placement");
createInPanel.add(yout);
listPane.revalidate();
listPane.repaint();
newL.revalidate();
}});
listPane.add(levelP);
listPane.revalidate();
listPane.repaint();
newL.add(listPane);
newL.pack();
}
** I added a SIMPLIFIED VERSION OF THE PROGRAM THAT DOESN'T MAKE THE SCROLLBAR
Hope this makes more sense. Thanks for the help in advance :);

I have a button when pressed, adds a new JPanel to a JPanel with BOXLAYOUT.
When you dynamically add components to a panel the basic logic need in your ActionListener is:
panel.add(...);
panel.revalidate();
panel.repaint();
You need to invoke the revalidate method to invoke the layout manager of the panel so the preferred size can be recalculated.
Edit:
newL.add(listPane);
You don't need the above statement. A Swing component can only have a single parent. That statement removed the panel from the scroll pane so you don't see the scroll bars.
newL.revalidate();
You don't need that statement. As I said in my answer you only need to revalidate() the panel that you changed.
Also you don't need all the statements below:
listPane.add(levelP);
listPane.revalidate();
listPane.repaint();
newL.add(listPane);
That is the layout manager is invoked when you pack the frame of make the frame visible. Your code should be:
newl.pack();
newl.setVisible(true);
That is you should only make the frame visible AFTER adding all the components to the frame.

Related

Java - Change location of JTextField

The search bar is 'search_bar', I'm trying to move it to the left hand side of the box with 'j_panel.add(search_bar, BorderLayout.WEST);' but it doesn't move from the middle. Any ideas on how to do this? Thanks
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
public class Main {
public static void main(String args[]) {
JFrame jfrm = new JFrame("Test");
jfrm.setSize(1024, 600);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jfrm.setResizable(false);
JTextField search_bar = new JTextField("Search...", 25);
search_bar.setPreferredSize(new Dimension(1,35));
JTextArea body = new JTextArea(32,83);
body.setPreferredSize(new Dimension());
body.setEditable(false);
JButton search_button = new JButton("Search");
JPanel j_panel = new JPanel();
j_panel.setLayout(new FlowLayout());
j_panel.add(search_bar, BorderLayout.WEST);
j_panel.add(search_button, null);
j_panel.add(body, BorderLayout.EAST);
j_panel.setBackground(Color.gray);
search_button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
final String text = search_bar.getText();
body.setText(text);
}
});
jfrm.setContentPane(j_panel);
jfrm.setVisible(true);
}
}
j_panel.setLayout(new FlowLayout());
j_panel.add(search_bar, BorderLayout.WEST);
BorderLayout.WEST is not applicable for FlowLayout. If you want to use a BorderLayout, use one instead of FlowLayout.
You cannot position components exactly the way you'd like when using FlowLayout.
By using BorderLayout you are bound to have only 5 components, because BorderLayout can handle 5 components max.

How can I add "boxes" (just bordered rectangles) to a JLayeredPane?

My overall goal is to create a jigsaw puzzle game that moves a set of images around the GUI screen with mousedrag. My current issue is to make this snapping function that when the mouse dragging the image releases, the image will snap into a predetermined place. This is where I want to create "boxes". I want to create 16 boxes for the 16 puzzle pieces and use their coordinates as the snapping location for the images when I release the mouse. (Just how in puzzle games the pieces snap to the correct place when you hover a general area). I am attempting this by making 16 JPanels, but I don't know if this is the smart way. Also, it seems I can't even add the JPanels to my JLayeredPane. I tried to set a border for one of the JPanels to help me see if it was added, and it was not.
Mouse drag works fine, everything works fine. I just want to be able to add some sort of representation of a box that the images when released by the mouse will snap into the box's location. Please let me know if you have any insights to this problem!
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Gui1 {
public static void main(String[] args) {
new Gui1();
}
public Gui1() { //Constructor for setting up the GUI
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JLayeredPane pane = new JLayeredPane();
JFrame frame = new JFrame("Testing");
JPanel canvas1 = new JPanel();
JPanel canvas2 = new JPanel();
JPanel canvas3 = new JPanel();
JPanel canvas4 = new JPanel();
JPanel canvas5 = new JPanel();
JPanel canvas6 = new JPanel();
JPanel canvas7 = new JPanel();
JPanel canvas8 = new JPanel();
JPanel canvas9 = new JPanel();
JPanel canvas10 = new JPanel();
JPanel canvas11 = new JPanel();
JPanel canvas12 = new JPanel();
JPanel canvas13 = new JPanel();
JPanel canvas14 = new JPanel();
JPanel canvas15 = new JPanel();
JPanel canvas16 = new JPanel();
canvas1.setPreferredSize(new Dimension(300,300));
canvas1.setBorder(BorderFactory.createLineBorder(Color.blue,10));
pane.add(canvas1, JLayeredPane.DEFAULT_LAYER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ImageGrab());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

GridBagLayout: How to set fixed column width?

I've been trying to set fixed column width in the following code for ages...The thing is that when I add a label to the panel on the left, then the width is incremented automatically...and i Would like the column width to be fixed...
Could anyone help me please??
This is the code:
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import java.io.IOException;
public class CurrentItem extends JPanel{
private static JFrame currentScreen;
public CurrentItem(JFrame p) {
GridBagConstraints c = new GridBagConstraints();
//Borramos todo lo que haya en la pantalla
this.removeAll();
this.revalidate();
currentScreen = p;
this.setBackground(Color.LIGHT_GRAY);
this.setLayout(new GridBagLayout());
currentScreen.add(this);
// --->
Panel leftPanel = new Panel();
leftPanel.setBackground(Color.BLACK);
c.weightx = 1.5;
c.weighty = 1;
//c.fill = GridBagConstraints.BOTH;
this.add(leftPanel, c);
// <---
// --->
Panel secondPanel = new Panel();
secondPanel.setBackground(Color.green);
c.weightx = 0.25;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
this.add(secondPanel, c);
// <---
// --->
Panel rightPanel = new Panel();
rightPanel.setBackground(Color.CYAN);
c.weightx = 1.5;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
this.add(rightPanel, c);
// <---
currentScreen.setVisible(true);
this.requestFocusInWindow();
}
}
GridBagLayout places components in rectangles (cells) in a grid, and then uses the components' preferred sizes to determine how big the cells should be.
Weights are used to determine how to distribute space among columns (weightx) and among rows (weighty); this is important for specifying resizing behavior.
Generally weights are specified with 0.0 and 1.0 as the extremes: the numbers in between are used as necessary.
Read more How to Use GridBagLayout
Sample code: (below code set fixed width column with 100% vertical size.)
Panel leftPanel = new Panel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(..., ...);
}
};
Remove weightx for first column and override getPreferredSize() method.
leftPanel.setBackground(Color.BLACK);
c.weighty = 1;
c.fill = GridBagConstraints.VERTICAL;
this.add(leftPanel, c);
If you know ahead of time the labels that you'll be adding, and how wide each one is:
You can call label.getPreferredSize().width on each label to determine the width of the largest label.
Then, add an invisible component (Box.createHorizontalStrut(width)) to the column to force it to be that wide at all times.
Then, when you add all of your labels, the width of that column of the panel will not change.

Why is JScrollPane not working?

When I comment out frame.add(hidden) it only shows the text area. When I don't comment it out, it only shows a large gray box with a grayed out Scrollbar.
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Panlindrome{
public Panlindrome(){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Panlindrome?");
frame.setSize(240,320);
//frame.setLayout(new GridLayout(3,1));
JTextArea inputText = new JTextArea(30,1);
inputText.setLineWrap(true);
JScrollPane hidden = new JScrollPane(inputText);
hidden.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
frame.add(inputText);
//frame.add(hidden);
frame.setVisible(true);
}
public static void main(String[] args){
Panlindrome check = new Panlindrome();
}
}
Don't add inputText to the frame; only add hidden.
The content of the scroll pane is already a child of the scroll pane. If you also try to add it to the frame (actually the frame's content pane, but whatever) as well, it will be in two places at once, which doesn't work.

How to refresh a panel?

I have a JMenu and when a person clicks on a JMenuItem I want the middle panel to refresh and display some new stuff. So I tried the .removeAll which works fine but when I try to add something it wont show.
Note: I'm using the WindowBuilder PRO, so I still trying to get use to it and whatnot
Here is my code:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import java.awt.List;
import javax.swing.JLabel;
import javax.swing.JTextPane;
import javax.swing.JSeparator;
import org.eclipse.wb.swing.FocusTraversalOnArray;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Panel;
import java.awt.GridBagConstraints;
public class HomeScreen {
JFrame frame;
private final Panel panel = new Panel();
public HomeScreen(String name) {
initialize(name);
}
/**
* Initialize the contents of the frame.
*/
private void initialize(String name) {
frame = new JFrame("Timzys CMS / Monitor / Account( " + name + " )");
frame.setResizable(false);
frame.setSize(694,525);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu mnMonitor = new JMenu("Monitor");
menuBar.add(mnMonitor);
JMenuItem mntmUsers = new JMenuItem("Users");
mnMonitor.add(mntmUsers);
JMenuItem mntmContentPosts = new JMenuItem("Content Posts");
mnMonitor.add(mntmContentPosts);
JMenuItem mntmLogs = new JMenuItem("Logs");
mnMonitor.add(mntmLogs);
JMenu mnExtras = new JMenu("Extras");
menuBar.add(mnExtras);
mntmUsers.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
frame.getContentPane().removeAll();
frame.getContentPane().add(new JLabel("Test"));
frame.getContentPane().revalidate();
}
});
JMenuItem mntmFeedbacksuggestions = new JMenuItem("Feedback/Suggestions");
mnExtras.add(mntmFeedbacksuggestions);
frame.getContentPane().setLayout(null);
panel.setBounds(0, 0, 688, 476);
frame.getContentPane().add(panel);
panel.setLayout(null);
JTextPane txtpnWelcomeTimzysCms = new JTextPane();
txtpnWelcomeTimzysCms.setFont(new Font("Arial", Font.PLAIN, 18));
txtpnWelcomeTimzysCms.setEditable(false);
txtpnWelcomeTimzysCms.setText("Welcome Timzys CMS Monitor. If you are here then you are a admin! So please do not tamper with any important things. If you have questions or suggestions goto the extras tab and submit a feedback idea. Enjoy!");
txtpnWelcomeTimzysCms.setBounds(10, 11, 668, 72);
panel.add(txtpnWelcomeTimzysCms);
}
}
Probably you're facing similar problem as someone else in the question:
Java Swing revalidate() vs repaint()
As suggested: try to call repaint instead of revalidate (the one you're calling right now in your implementation of method actionPerformed)
The problem is that because you have set the frame's layout to null, the new JLabel that you add will need to have its size set. e.g.:
JLabel label = new JLabel("Test");
label.setSize(100, 100);
frame.getContentPane().add(label);
As an aside:
Actually I wonder why you are mixing AWT & Swing components here. You have a heavyweight AWT panel added to the frame which blocks out the menus. Switching to JPanel would fix this.

Categories

Resources