so I want to make my Jscrollpane to show Pascals triangle. I have this:
labelPanel= new JPanel();
lRows = new JLabel[n];
for (int i=0;i<n;i++){
lRows[i]=new JLabel(Arrays.toString(tri.tri[i]));
labelPanel.add(lRows[i]);
}
But it's not what I want and I am not sure how to fix that, picture included. Any help?
By default, JPanel uses a flow layout. To get the vertical arrangement you are looking for, you should be able to do this by using a BoxLayout with a vertical orientation on your labelPanel, then add your JLabel rows.
labelPanel= new JPanel();
//set this up to order things vertically
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
lRows = new JLabel[n];
for (int i=0;i<n;i++){
lRows[i]=new JLabel(Arrays.toString(tri.tri[i]));
//to center your label, just set the X alignment
lRows[i].setAlignmentX(Component.CENTER_ALIGNMENT)
labelPanel.add(lRows[i]);
}
I also threw in a line to center the rows like your picture. Component comes from the java.awt package.
You can read up on the different layout managers available by default in the Java Tutorial
The easiest solution is to rotate the triangle to make it look like:
1 1 1 1 1 1 1
1 2 3 4 5 6
1 3 6 10 15
1 4 10 20
1 5 15
1 6
1
However, if you must print sth like this
I did it this way:
for (int i = 0; i<n; i++){
for (int j = 0; j<Triangle.trojkat[i].length; j++){
sb.append(Triangle.trojkat[i][j]);
len = String.valueOf(Triangle.trojkat[i][j]).length();
while (12-len>0){
sb.append(" ");
len++;
}
//sb.append(" ");
}
TriangleRes[i] = new JLabel(sb.toString(), JLabel.CENTER);
TriangleRes[i].setFont(new Font("Serif",Font.PLAIN,8));
sb = new StringBuilder();
}
Let me explain:
I decided, that I want my triangle print beautifuly for the size smaller that 35. Then I've checked, that the numbers in such a triangle come up to 10 digits. Then, when I added next number to the existing row, I checked it's length and while total length wasn't 12 yet, I add spaces. This lead to the triangle that you have attached on the picture.
If this is for Ph.D Macyna classes, just post a question on a group and I'll respond :)
Use a JTextArea
Give it a monospaced font, i.e., Font.MONOSPACED
Append your lines of text to the JTextArea, similar to how you'd do this in the console.
Put the JTextArea into a JScrollPane
VoilĂ . You're done.
If you need to use JLabels, then put them in a JPanel that uses GridLayout with enough columns to show your bottom row.
If you did this, you'd be putting empty JLabels in every other cell, so that the cells branch correctly.
Related
I have started trying to write a code similar to the game 2048, however the size of the board can have any value depending on what the user inputs. I decided to make the numbers on the board, for style purposes, separate buttons.
This is the current GUI:
How can I make it so that when the buttons: up, down left, or right are pressed each of the button's in the board texts are changed? I know about event listeners I just mean how can I replace the button's in the same grid with different values when I defined the buttons on the board as:
`for(int i = 2; i < rows + 2; i++) {
for(int j = 2; j < columns + 2; j++) {
gbc.gridx = j;
gbc.gridy = i;
num = new JButton(board.board[j-2][i-2].getValue()+"");
num.setFont(new Font("monospaced", Font.PLAIN, screenSize.height/50));
num.setEnabled(false);
this.add(num, gbc);
}
}`
The only ideas I've had was to create an array of buttons and then change the button's text in the array of buttons and then replace the old array of buttons with the new one. Also sorry if it has some super simple answer that I just couldn't find, I am just about finished with one semester of coding courses in college.
You could store the JButtons on a HashMap and use column number and row number as a key to find the correct button.
Something like:
Map<String, JButton> grid = new HashMap<String, JButton>;
for(int i = 2; i < rows + 2; i++) {
for(int j = 2; j < columns + 2; j++) {
grid.put(String.valueOf(i) + String.valueOf(i), new JButton("some text"));
// we transform the integers into String, otherwise the operator "+" will sum them
// instead of concatenate them.
}
}
Now you cant get the desired button with grid.get(row + column);
JButton bt;
JButton bt = grid.get("4" + "6");
bt.setText("different text");
grid.put("4" + "6", bt);
I don't think you should use Buttons to do such a game button it's something that you can click on it since your are not supposed to click on numbers. If I were you I would use a gamePanel which contains fixed labels since it's easier changing text of label than moving label.
I would add MouseListener to the gamePanel and then fill implemented methods in order to manage when the mouse left button is pressed and move to left and so on.
So create an array of Label.
Create a method which add and move numbers according to the direction of the move. For instance if you make a left to right move you will start to add the numbers of the first column into the second column when they have same values. Next you just have to do it recursively until the last column.
If you need a bit more explainations ,I'll be pleased to help you.
I'm new to swing and I've been trying some new things. I'd like to create and place JLabels on a JPanel, but as many as I want, using a loop. I'm trying to make a snake game, btw.
/*Up here I set the number of parts (JLabels) I want and instantiate my ArrayList
to store them later.*/
snakeBodyParts = 3;
snakeBody = new ArrayList<>();
/*This is the part I'm struggling with. First, bodyPartIndex is going to go from 0
to my desired number of parts. On each time it's going to store an int for the X position
of the JLabel and an int for the Y position. That way I'm going to get
JLabels on a horizontal line, each time an unit farther away.*/
for (int bodyPartIndex = 0; bodyPartIndex < snakeBodyParts; bodyPartIndex++) {
snakePositionsX[bodyPartIndex] = 50 - (bodyPartIndex * UNIT_SIZE);
snakePositionsY[bodyPartIndex] = 50;
/*Then, I add a JLabel to my list, and get it back to my "bodyPart" JLabel.*/
snakeBody.add(new JLabel());
bodyPart = snakeBody.get(bodyPartIndex);
/*Here I set the location on my "bodyPart" JLabel, using the coordinates I created before,
and set its icon (it's out of the loop)*/
bodyPart.setLocation(snakePositionsX[bodyPartIndex], snakePositionsY[bodyPartIndex]);
bodyPart.setIcon(imgIconBodyPart);
/*And finally I replace the old bodyPart with the recently modified one, I then add it to my JPanel (this.add) */
snakeBody.set(bodyPartIndex, bodyPart);
this.add(bodyPart, new org.netbeans.lib.awtextra.AbsoluteConstraints(snakePositionsX[bodyPartIndex], snakePositionsY[bodyPartIndex], UNIT_SIZE, UNIT_SIZE));
}
I'm pretty sure I've done a lot of things wrong, I'm still trying to understand what I'm doing, but the end result is a blank screen, can anyone help me? I really need to know how to do this.
so I want to make my Jscrollpane to show Pascals triangle. I have this:
labelPanel= new JPanel();
lRows = new JLabel[n];
for (int i=0;i<n;i++){
lRows[i]=new JLabel(Arrays.toString(tri.tri[i]));
labelPanel.add(lRows[i]);
}
But it's not what I want and I am not sure how to fix that, picture included. Any help?
By default, JPanel uses a flow layout. To get the vertical arrangement you are looking for, you should be able to do this by using a BoxLayout with a vertical orientation on your labelPanel, then add your JLabel rows.
labelPanel= new JPanel();
//set this up to order things vertically
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
lRows = new JLabel[n];
for (int i=0;i<n;i++){
lRows[i]=new JLabel(Arrays.toString(tri.tri[i]));
//to center your label, just set the X alignment
lRows[i].setAlignmentX(Component.CENTER_ALIGNMENT)
labelPanel.add(lRows[i]);
}
I also threw in a line to center the rows like your picture. Component comes from the java.awt package.
You can read up on the different layout managers available by default in the Java Tutorial
The easiest solution is to rotate the triangle to make it look like:
1 1 1 1 1 1 1
1 2 3 4 5 6
1 3 6 10 15
1 4 10 20
1 5 15
1 6
1
However, if you must print sth like this
I did it this way:
for (int i = 0; i<n; i++){
for (int j = 0; j<Triangle.trojkat[i].length; j++){
sb.append(Triangle.trojkat[i][j]);
len = String.valueOf(Triangle.trojkat[i][j]).length();
while (12-len>0){
sb.append(" ");
len++;
}
//sb.append(" ");
}
TriangleRes[i] = new JLabel(sb.toString(), JLabel.CENTER);
TriangleRes[i].setFont(new Font("Serif",Font.PLAIN,8));
sb = new StringBuilder();
}
Let me explain:
I decided, that I want my triangle print beautifuly for the size smaller that 35. Then I've checked, that the numbers in such a triangle come up to 10 digits. Then, when I added next number to the existing row, I checked it's length and while total length wasn't 12 yet, I add spaces. This lead to the triangle that you have attached on the picture.
If this is for Ph.D Macyna classes, just post a question on a group and I'll respond :)
Use a JTextArea
Give it a monospaced font, i.e., Font.MONOSPACED
Append your lines of text to the JTextArea, similar to how you'd do this in the console.
Put the JTextArea into a JScrollPane
VoilĂ . You're done.
If you need to use JLabels, then put them in a JPanel that uses GridLayout with enough columns to show your bottom row.
If you did this, you'd be putting empty JLabels in every other cell, so that the cells branch correctly.
I have the following,
GridLayout layout = new GridLayout(4, 0);
In the event that I have 5 items, this will create 2 columns, where the first contains 3 rows and the second contains 2 rows. This is not what I want, nor is this what I expected. I expected the first column to contain 4 rows and the second column to contain 1 row.
Why isn't this layout manager respecting the number of rows I want per column? Or better yet, how do I make this layout manager respect this?
The result seems expected: "Specifying the number of columns affects the layout only when the number of rows is set to zero."
You can get the desired effect using JList, as shown here.
private static final int N = 5;
...
list.setLayoutOrientation(JList.VERTICAL_WRAP);
list.setVisibleRowCount(N - 1);
Disclaimer: This is not provided as a concrete answer, but rather to prove a point of the helpfulness of a SSCCE...
GridLayout constructor is GridLayout(int rows,int cols) (The reason I mention it is as #AndrewThompson said in his answer seems like you might have mixed up the parameters of rows/cols for the LayoutManager). Thus 4,0 will give us 4 rows and a variable amount of columns.
When I add 4 labels I get 4 rows and 1 coloumn (as expected):
when you add 5 labels I get 3 rows and 2 coloumns each having 2 items except for the last which has 1:
IMO this is expected GridLayout must honor column/row count >0 (anything less than 0 and the LayoutManager calculates the amount), thus if we add more components than the rows allowed it creates a new coloumn >0 but also >1 as 0 and 1 perform the same. Thus it creates 2 coloums now when we fill a Grid thats 4x0 with 5 components, we expect the 2 components on each line ( for each coloums) and the remaining on the last row (not necessarily the last row depending on the amount of components i.e 8 would fill it to the last row as now its 4x2 but adding 9 components would cause a GridLayout of 4x3 - filling all coloumns of the row before going to the new row)
Please post an SSCCE which re-inacts the problem or else we are just guessing here is my example I made which shows different behavior than what you said/get:
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class Test {
public Test() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
GridLayout layout = new GridLayout(4, 0);
frame.setLayout(layout);
for (int i = 0; i < 5; i++) {
frame.add(new JLabel(String.valueOf(i + 1)));
}
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Create Swing components on EDT
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
}
The GridLayout you specified has number of columns as 0. That means number of columns is to be decided by the layout. In which case it tries to compute number of columns required based on number of items.
If you added 4 components you would have got 4 rows with one component each. If you add 5 components two columns are required and they are filled with the components serially that means only 3 rows will be consumed.
So depending on your number of components you may see all specified rows utilized or not. For instance try with 7 components.
Does GridLayout ever not honor the number of rows and columns you've specified if you don't fill it completely?
I'm creating a GridLayout with 3 rows and 4 columns. However, I'm only adding 9 components. It ends up showing me these 9 components in a 3x3 grid, rather than a 3x4 grid (with only 1 component on the third row (and two blanks)).
rather than a 3x4 grid (with only 1 component on the third row (and two blanks)).
Then you should be creating your GridLayout using:
setLayout(new GridLayout(0,4));
It tell the layout that you don't know how many rows you have, but you want 4 columns. So the columns will be filled up before moving to the next row.
No need for empty components.
Just fill empty cells with empty items (like a JLabel), eg:
class MyFrame extends JFrame
{
MyFrame()
{
setLayout(new GridLayout(3,4));
for (int i = 0; i < 9; ++i)
this.getContentPane().add(new JLabel(""+i));
for (int i = 0; i < 3; ++i)
getContentPane().add(new JLabel());
pack();
setVisible(true);
}
}
This layouts them as
0 1 2 3
4 5 6 7
9