JFrame large grid map - java

I'm trying to make a large grid map of 160x120 JButtons with JFrame but it's too much to fit on the window.
How can I overcome this?
public class DisplayTable extends JFrame {
public static void main() {
JFrame frame = new JFrame("puzzle layout");
//frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(3200, 800);
JPanel panel = new JPanel();
panel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
panel.setBorder(new EmptyBorder(0,0,0,0));
panel.setLayout(new GridLayout(12,16));
for(int i=0; i<120; i++) {
for(int j=0; j<160; j++) {
JButton temp = new JButton("1");
panel.add(temp);
}
}
frame.add(panel);
frame.setVisible(true);
}
}

Use a JScrollPane to wrap the panel ... also, you should use pack instead of setSize, but only after you've added all your components to the screen
See How to use scroll panes for more details

Related

Java Swing 13 GridLayout does not exist?

I can't seem to get a swing GridLayout to work in java 13. The error is that GridLayout cannot be resolved to a type in the following code:
import javax.swing.*;
public class GameFrame extends JFrame {
public static final void NewFrame() {
new GameFrame();
}
public GameFrame() {
this.setSize(1600, 800);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("The Game");
this.setVisible(true);
this.setResizable(false);
JPanel MainPanel = new JPanel();
MainPanel.setLayout(new GridLayout());
}
}
The issue is caused by the class not being imported.
import java.awt.GridLayout;
Since it is not in the swing package it doesn't get imported with the star import.
Also it is better to use explicit imports.
This might be related to the fact that panel is empty. Try running this code and it should work.
public class GridLayoutTest {
private static JButton[] arrayBtn;
public static void main(String[] args) {
// the frame that contains the components
JFrame frame = new JFrame("GridLayoutTest from JCG");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// set the size of the frame
frame.setSize(350, 350);
// set the rows and cols of the grid, as well the distances between them
GridLayout grid = new GridLayout(5, 3, 10, 10);
// what layout we want to use for our frame
frame.setLayout(grid);
// add a text field with a specified text to the frame
JTextArea text = new JTextArea();
text.setText("Result");
text.setEditable(false);
frame.add(text);
// add buttons to the frame
frame.add(new JButton("+"));
frame.add(new JButton("="));
arrayBtn = new JButton[10];
// add JButtons dynamically
for(int i=0; i < arrayBtn.length; i++) {
arrayBtn[i] = new JButton(Integer.toString(i));
frame.add(arrayBtn[i]);
}
frame.setVisible(true);
}
}

How to for loop jPanel in jFrame?

May I know why my jPanel does not appear in the jFrame? I want to make 5 blue jPanel appear in the jFrame but why only 1 blue jPanel appear in my jFrame? Thanks for helping!
public class NewJFrame2 extends javax.swing.JFrame {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
/**
* Creates new form NewJFrame2
*/
public NewJFrame2() {
initComponents();
JPanel[] panelArray = new JPanel[5];
JButton btnArray[] = new JButton[5];
for(int i = 0; i<5;i++)
{
panelArray[i] = new JPanel();
//panelArray[i].setVisible(true);
System.out.println(panelArray[i]);
javax.swing.border.Border border = BorderFactory.createLineBorder(Color.BLUE, 5);
panelArray[i].setBackground(Color.YELLOW);
panelArray[i].setBorder(border);
frame.getContentPane().add(panelArray[i]);
}
frame.setSize(new Dimension(500, 400));
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("A Simple JFrame");
frame.setVisible(true);
}
As mentioned in the comments you want a LayoutManager.
The current issue is that you are adding all five panels to the exact same space on your frame. To solve this issue you need to provide a structure for the frame to associate different coordinates with different areas.
This answer contains a good jumping off point for you to start to play with layouts in Java.
Using a container JPanel with a BoxLayout -- see comments below for further info :
initComponents();
JPanel[] panelArray = new JPanel[5];
JButton btnArray[] = new JButton[5];
JPanel container = new JPanel(); // Container JPanel
container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS)); // With a BoxLayout
for (int i = 0; i < 5; i++) {
panelArray[i] = new JPanel();
//panelArray[i].setVisible(true);
System.out.println(panelArray[i]);
javax.swing.border.Border border = BorderFactory.createLineBorder(Color.BLUE, 5);
panelArray[i].setBackground(Color.YELLOW);
panelArray[i].setBorder(border);
container.add(panelArray[i]); // Adding 5 JPanels to container JPanel
}
frame.getContentPane().add(container); // Adding container JPanel to JFrame
frame.setSize(new Dimension(500, 400));
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("A Simple JFrame");
frame.setVisible(true);

How to arrange the Components in multiple rows in a Scrollpane

I need to add about 600 Images to a Scrollpane, but all the Images are arranged side-by-side
public CollectionPanel(Controller controller)
this.setBackground(Color.white);
this.setLayout(new BorderLayout());
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
JScrollPane scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
for(int i = 0; i < 100; ++i){
content.add(new Sticker(i+1));
}
scrollPane.setViewportView(content);
this.add(scrollPane, BorderLayout.CENTER);
}
How is it possible to arrange them to make a "linebreak" when they reached the end of the screen?
Have a look at Rob Camick's WrapLayout.
You can resize the frame, and all your components will be reformatted for you. Here's an example usage
import java.awt.*;
import javax.swing.*;
public class TestWrapLayout {
public TestWrapLayout () {
ImageIcon icon = new ImageIcon(getClass().getResource("/resources/stackoverflow2.png"));
JPanel panel = new JPanel(new WrapLayout());
for (int i = 1; i <= 250; i++) {
JLabel iconlabel = new JLabel(icon);
iconlabel.setLayout(new BorderLayout());
JLabel textlabel = new JLabel(String.valueOf(i));
textlabel.setHorizontalAlignment(JLabel.CENTER);
textlabel.setForeground(Color.WHITE);
textlabel.setFont(new Font("impact", Font.PLAIN,20));
iconlabel.add(textlabel);
panel.add(iconlabel);
}
JFrame frame = new JFrame();
frame.add(new JScrollPane(panel));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new TestWrapLayout();
}
});
}
}
Use GridLayout instead of FlowLayout that fits the components side by side.
JPanel content = new JPanel();
content.setLayout(new GridLayout(rows,1));
//pass no of rows with just one column
You can try with BoxLayout as well.
JPanel content = new JPanel();
content.setLayout(new BoxLayout(content, BoxLayout.PAGE_AXIS));
Please have a look at Using Layout Managers & A Visual Guide to Layout Managers for more info with working sample codes.
Myself, I would try to keep things as simple as possible by putting images, ImageIcons actually, into a JList which can handle ImageIcons quite well. Give it a horizontal wrap set its visible row count to 0, plop it into a JScrollPane, and there you go.

Keep BoxLayout From Expanding Children

I want to stack some JComponents vertically inside a JPanel so they stack at the top and any extra space is at the bottom. I'm using a BoxLayout. The components will each contain a JTextArea that should allow the text to wrap if necessary. So, basically, I want the height of each of these components to be the minimum necessary for displaying the (possibly wrapped) text.
Here's a contained code example of what I'm doing:
import javax.swing.*;
import java.awt.*;
public class TextAreaTester {
public static void main(String[] args){
new TextAreaTester();
}
public TextAreaTester(){
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel,BoxLayout.PAGE_AXIS));
panel.setPreferredSize(new Dimension(100,400));
for(int i = 0; i<3; i++){
JPanel item = new JPanel(new BorderLayout());
JTextArea textarea = new JTextArea("this is a line of text I want to wrap if necessary");
textarea.setWrapStyleWord(true);
textarea.setLineWrap(true);
textarea.setMaximumSize( textarea.getPreferredSize() );
item.add(textarea,BorderLayout.NORTH);
panel.add(item);
}
panel.add(Box.createGlue());
frame.add(panel);
frame.setVisible(true);
frame.pack();
}
}
The child JPanels are expanding to fill the vertical space. I tried using glue because I thought that's what glue was for, but it seems to do nothing at all. Any help?
Note: I have found questions that look almost identical, but none with answers I can apply.
One solution: nest JPanels with the outer JPanel using Borderlayout and adding the BoxLayout using JPanel to this one BorderLayout.NORTH, also known as BorderLayout.PAGE_START:
Edit for Kleopatra:
import javax.swing.*;
import java.awt.*;
public class TextAreaTester {
public static void main(String[] args) {
new TextAreaTester();
}
public TextAreaTester() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
// panel.setPreferredSize(new Dimension(100,400));
for (int i = 0; i < 3; i++) {
JPanel item = new JPanel(new BorderLayout());
// item.setLayout(new BoxLayout(item,BoxLayout.LINE_AXIS));
JTextArea textarea = new JTextArea(
"this is a line of text I want to wrap if necessary", 3, 35);
textarea.setWrapStyleWord(true);
textarea.setLineWrap(true);
// textarea.setMaximumSize(textarea.getPreferredSize());
// item.setMaximumSize( item.getPreferredSize() );
item.add(new JScrollPane(textarea), BorderLayout.NORTH);
panel.add(item);
}
panel.add(Box.createGlue());
JPanel mainPanel = new JPanel(new BorderLayout()) {
private final int prefW = 100;
private final int prefH = 400;
#Override
public Dimension getPreferredSize() {
return new Dimension(prefW, prefH);
}
};
// mainPanel.setPreferredSize(new Dimension(100, 400));
mainPanel.add(panel, BorderLayout.PAGE_START);
frame.add(mainPanel);
frame.setVisible(true);
// frame.getContentPane().add(jp);
frame.pack();
}
}
Alternatively, you can use Box.Filler. Just replace your call to panel.add(Box.createGlue()) with
panel.add(new Box.Filler(new Dimension(0, 0),
new Dimension(0, Short.MAX_VALUE),
new Dimension(0, Short.MAX_VALUE)));
If you want to achieve the same for a horizontal layout, just use Short.MAX_VALUE for width instead of height in the Dimension call.

JScrollPane won't work

Hey guys I wanted to create a JScrollPane but it won't work... and I don't know why... here's my code...
public class test extends JFrame{
public test(){
setSize(1000,600);
}
private static JButton[] remove;
private static JPanel p = new JPanel();
public static void main(String[]args){
p.setLayout(null);
JFrame t=new test();
remove = new JButton[25];
for(int i=0;i<25;i++){
remove[i]=new JButton("Remove");
remove[i].setBounds(243,92+35*i,85,25);
p.add(remove[i]);
}
JScrollPane scrollPane = new JScrollPane(p);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
t.add(scrollPane);
t.setVisible(true);
}
Umm and Im pretty sure the frame isn't big enough for these 25 buttons... But if i delete that p.setLayout(null); A horizontal scroll bar will be created automatically... I don't really know what is wrong with my code... Pls help thank you very much!
You need to set p's preferredSize for this to work.
p.setPreferredSize(new Dimension(800, 2000));
Or you could have p extend JPanel and then override the getPreferredSize() method to return the proper dimension.
And I agree -- get rid of your null layouts. Learn about and use the layout managers if you want to use Swing correctly and have robust Swing GUI's.
e.g.,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Foo extends JFrame {
private static final int BUTTON_COUNT = 25;
public static void main(String[] args) {
JPanel btnPanel = new JPanel(new GridLayout(0, 1, 0, 20));
btnPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
AbstractAction removeAction = new AbstractAction("Remove") {
#Override
public void actionPerformed(ActionEvent evt) {
JButton src = (JButton) evt.getSource();
JPanel container = (JPanel) src.getParent();
container.remove(src);
container.revalidate();
container.repaint();
}
};
for (int i = 0; i < BUTTON_COUNT; i++) {
JButton removeBtn = new JButton(removeAction);
btnPanel.add(removeBtn);
}
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.add(btnPanel, BorderLayout.NORTH);
JScrollPane scrollpane = new JScrollPane(borderPanel,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollpane.setPreferredSize(new Dimension(400, 800));
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(scrollpane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
The issue is that a scroll pane checks the component inside it for a "preferred size" so a pane with a null layout has a preferred size of (0,0). Which it ignores.
You should do something along the lines of:
p.setPreferredSize(1000,600);
And you should see some scroll bars appear, I'm not sure how accurate they will be though.

Categories