JFrame, JPanel, and Gridlayout Issues - java

As a quick overview, my project involves taking a .txt file and converting that into a 2d array, then drawing it into a JFrame. As I was testing, I used JButtons instead of a custom class that will be built later. I have ran into two bugs that I don't know how to solve. For these pictures, this is all based on a Gridlayout that is 2 Rows and 16 Columes. When I add JButtons to the panel, it looks like this.
When I add them to the JFrame, it looks like this.
Here is my code for creating the JFrame and JPanel and rendering it:
/**
* This method creates a JFrame, JPanel, and then renders
* all of the level in the JFrame
*/
public void render()
{
JFrame frame = new JFrame("<Insert Title>");
//Make it full screen for any computer monitor
frame.setSize(JFrame.MAXIMIZED_HORIZ, JFrame.MAXIMIZED_HORIZ);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setUndecorated(true);
frame.setVisible(true);
JPanel panel = new JPanel(grid);
frame.setLayout(grid);
frame.add(panel);
panel.getInputMap(IFW).put(KeyStroke.getKeyStroke("ESCAPE"), "quit");
panel.getActionMap().put("quit", quit);
//Draw!
for(int row = 0; row < drawStuff.length; row++)
{
for(int col = 0; col < drawStuff[row].length; col++)
{
//Either panel.add or frame.add here
panel.add(new JButton("Row :"+row+" Col: "+col));
}
}
panel.revalidate();
panel.repaint();
}
Anything that I am doing wrong here?
Thanks!

Remove frame.setLayout(grid); - this will allow the panel to occupy the entire content area of the frame, instead of been one row of one column
frame.setSize(JFrame.MAXIMIZED_HORIZ, JFrame.MAXIMIZED_HORIZ) really isn't doing what you think it is, not unless you want a frame which is 2x4

Related

JTable only shows the right border of the table

I have a JTable and I want to make a tic tac toe themed table. I have managed to get rid of three borders without really knowing how...
Here's my code:
public class Table extends JPanel {
public static void main( String[] args ) {
JFrame jFrame = new JFrame();
JTable table = new JTable(3, 3);
table.setBounds(90, 20, 200, 200);
for(int i = 0; i < 3; i++) {
table.setRowHeight(i, 67);
}
table.setBackground(Color.black);
table.setGridColor(Color.white);
table.setForeground(Color.white);
// content pane so I can set the background
jFrame.getContentPane().add(table);
jFrame.getContentPane().setBackground(Color.black);
jFrame.setSize(400, 400);
jFrame.setLayout(null);
jFrame.setVisible(true);
}
}
I also have some stuff that initializes the table more like setting values but I don't think that will matter but I can add it if you want. So how could I get the right border of the table to disappear too?
When I compile this code, the top, left and bottom borders are not visible
You can usesetBorder method with a LineBorder in order to fill it:
table.setGridColor(Color.white);
table.setBorder(BorderFactory.createLineBorder(table.getGridColor()));
By the way, setLayout(null) and setBounds is a bad practice that is going to give you hard time in the future (plus it is not user-friendly, since you cannot resize your frame and won't work in different screen sizes). Try to use LayoutManagers and let them do the work for you.
Also, take a look at initial threads. All swing applications should run on their own thread and not in the main thread.

How can i add JButtons to a panel in vertical way? [duplicate]

This question already has answers here:
Java: vertical alignment within JPanel
(3 answers)
Closed 4 years ago.
the task i am trying to do is simple. I want to add JButtons to a panel in a vertical way, but using a loop to adding it, i tried to do it using .setBounds() and .setLocation() mehtod, but i dont have any results.
In a simple way, i want to do this but adding the buttons vertically and keeping the JScroll bar...:
public class NewMain {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.setLayout(null);
for (int i = 0; i < 10; i++) {
JButton asd=new JButton("HOLA "+i);
asd.setLocation(i+20, i+20);
panel.add(asd);
}
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setBounds(50, 30, 300, 50);
JPanel contentPane = new JPanel(null);
contentPane.setPreferredSize(new Dimension(500, 400));
contentPane.add(scrollPane);
frame.setContentPane(contentPane);
frame.pack();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
Give the JPanel that holds the JButtons an appropriate layout manager that adds components in a vertical manner. A GridLayout(0, 1) would work, the parameters referring to 0 rows -- meaning variable number of rows, and 1 column. This will add the JButtons into a vertical grid, column of one
Other possible solutions include BoxLayout and GridBagLayout, both of which are a little more complex than the GridLayout.
Also avoid using null layouts as you're doing as this leads to inflexible GUI's painful debugging and changes.

How can get components to stretch across an entire row using BoxLayout?

I'm looking at the How To Use BoxLayout documentation, which clearly says that
What if none of the components has a maximum width? In this case, if
all the components have identical X alignment, then all components are
made as wide as their container.
Let's assume we're adding a lot of JButton instances to a JPanel. If the maximum width of these buttons are none AND we invoke setAlignmentX(Component.LEFT_ALIGNMENT) on all of these buttons - then each of these buttons should stretch across its entire row. The documentation even illustrates this using the below picture.
I can't get this to work!
I've tried doing setMaximumSize(null) and setMaximumSize(new Dimension(-1,-1)) and setMaximumSize(new Dimension(0,0)) on the buttons but nothing gives me the described behaviour.
What excactly does the documentation mean when it says :
What if none of the components has a maximum width?
What is a maximum width of none?
The best I've been able to produce is the below. Reading the documentation I would expect that the buttons should be able to stretch across their entire rows. I know I can use other layout managers as well for this, but I would like to achieve this with BoxLayout (granted the documentation is right / I've understood the documentation right).
public class CustomList extends JPanel {
private final Box box = Box.createVerticalBox();
public CustomList() {
for (int i = 0; i < 10; i++) {
JButton b = new JButton("Button item" + i);
//b.setMaximumSize(new Dimension(0,0));
b.setAlignmentX(Component.LEFT_ALIGNMENT);
box.add(b);
}
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(box, BorderLayout.CENTER);
}
public static void main(String[] args) {
CustomList l = new CustomList();
l.setSize(200, 200);
l.setBackground(Color.red);
JFrame frame = new JFrame("Vertical Box");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(l, BorderLayout.CENTER);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
Your buttons actually have a maximum width.
What you can do is create JPanel objects with BorderLayout in your loop, add each button to each panel (to BorderLayout.CENTER, which is the default anyway).
BorderLayout.CENTER doesn't care about the maximum size of its child Component, so you end up with a JPanel whose whole content is filled by a JButton.
Since the JPanel itself has a huge default maximum size of new Dimension(Short.MAX_VALUE, Short.MAX_VALUE) (this is width=32767,height=32767 !!) which is the default maximum size of Component, you will get the expected result :
public CustomList() {
for (int i = 0; i < 10; i++) {
JPanel panel = new JPanel(new BorderLayout());
JButton b = new JButton("Button item" + i);
//b.setMaximumSize(new Dimension(0,0));
b.setAlignmentX(Component.LEFT_ALIGNMENT);
panel.add(b);
box.add(panel);
}
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(box, BorderLayout.CENTER);
}

Java: How to nest JPanel in a GridLayout?

I want to know how to nest JPanels using a GridLayout. This is how it should look like.
I approached this problem by 2 ways so far,
using JPanels and
using JLabels,
and none of them worked (only the first panel created is shown).
Here is the code for the JPanel approach:
int x=20, y=20;
JPanel [] panels = new JPanel[3];
JLabel animal = new JLabel(new ImageIcon(getClass().getResource("Pictures/animal.gif")));
JLabel map = new JLabel(new ImageIcon(getClass().getResource("Pictures/map.gif")));
JLabel mountain = new JLabel(new ImageIcon(getClass().getResource("Pictures/mountain.gif")));
for(int i=0;i<panels.length;i++)
{
if(i>0)
{
x+=x;
y+=y;
}
panels[i] = new JPanel(new GridLayout(2,2));
panels[i].setPreferredSize(new Dimension(x,y));
if(i==0)
panels[i].add(new JPanel());
else
panels[i].add(panels[i-1]);
panels[i].add(mountain);
panels[i].add(map);
panels[i].add(animal);
}
add(panels[2]);
One option is to create a class that will represent a panel divided into the grid with the images. The only issue would be the top left quadrant which would usually contain the nested panel, at some point you want this to contain just a blank panel. So maybe something like this (barring various optimizations):
class GridPanel extends JPanel{
JLabel mountain, map, animal;
public GridPanel(JPanel panel){
super();
setLayout(new GridLayout(2, 2));
animal = new JLabel(new ImageIcon(getClass().getResource("pictures/animal.gif")));
map = new JLabel(new ImageIcon(getClass().getResource("pictures/map.gif")));
mountain = new JLabel(new ImageIcon(getClass().getResource("pictures/mountain.gif")));
add(panel);
add(mountain);
add(map);
add(animal);
}
}
Notice that it accepts the panel that is to be displayed in the top left corner of the grid. This coud then be called with the panel specified. So at the point where you want to create the main panel:
JPanel grid = new GridPanel(new JPanel()); //initial
for(int i = 1; i <= 5; i++){
grid = new GridPanel(grid);
}
add(grid);
The initial grid is created with a blank JPanel. And every subsequent grid will contain the previous one as the top left panel. You have to resize your images and such and maybe even avoid loading the images multiple times etc. But that is another question. This example shows 5 nested panels.
Just to be clear, you should use ImageIO to load the images once and reuse the images. For example You can create a BufferedImage like this in your main class:
BufferedImage mointainImg = ImageIO.read(new File("pictures/mountain.gif"));
And when you want to create the JLabel you can do this:
mountain = new JLabel(new ImageIcon(mountainImg));
And the advantage is that you can manipulate the image a bit if you want.
One issue that you have is that the images are not scaled. To scale images, use Image.getScaledInstance(). Proper scaling would at least fix the problem of the visible images being cut off. It also might cause the other images to be shown as they might just be hiding behind the visible images because they are too big.

Create a matrix using JTextFields or JTextAreas

I have to do make a program that has to be able to show a matrix in form of Jtextfields or Jtextareas, so that the user can write in them(a number of the matrix for each Jtextfield).
The problem is that I have no idea how to create a custom JPanel with the size and quantity of Jtextfields that the user specifies(a different each time).
I have already googled the question, to no avail.
Take a look at GridLayout. It is pretty simple to put together a grid together with a couple params (row and col count). To paraphrase from the JavaDoc:
public static void main (String[] args) {
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3,2));
panel.add(new JTextField("1"));
panel.add(new JTextField("2"));
panel.add(new JTextField("3"));
panel.add(new JTextField("4"));
panel.add(new JTextField("5"));
panel.add(new JTextField("6"));
would result in a 3 row by 2 col grid of JTextFields
EDIT:
here is some more, in a class named Demo:
public class Demo {
public static void main(final String[] args) {
if (args.length < 2) {
System.out.print("please enter row and col on commandline");
}
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new Demo(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
}
});
}
public Demo(int colCnt, int rowCnt) {
JFrame frame = new JFrame("Demo");
frame.setSize(600, 600);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(colCnt,rowCnt));
for (int i =0; i < rowCnt*colCnt; i++) {
panel.add(new JTextField(""+i));
}
frame.setContentPane(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
First of all, I would build a 2d array of the text fields\areas. When you get the user input you can then initialize the arrays and "new up" all of the widgets. After adding all of them to the parent panel\frame you may have to do some calculation based on the used up size and resize your top level window. Aside from that, as already suggested, GridLayout will be a good choice for the direct parent component.
Hope this helps.
To change the appearance at runtime, all you need to do is replace the content with new components.
So depending on how you get your input, you replace the numbers given in akf's answer with the input.
panel.setLayout(new GridLayout( rows, columns));
and then to show the new panel you add it in the JFrame with
add( panel );
Your assignment however might be something along the lines of subclassing a JPanel to show a matrix. I get that impression in your wording. Then its a whole different solution.
If your only goal is to implement a matrix where you can edit values a JTable is by far the simplest. Put the following in a JFrame
DefaultTableModel data = new DefaultTableModel(3 , 3);// rows, cols
JTable table = new JTable(data);
add(table);
pack();
setVisible(true);
This would also simplify modifying the height and width of the matrix by using data.setRowCount( newValue ).

Categories